-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathVehicle.cpp
314 lines (268 loc) · 10.3 KB
/
Vehicle.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
#include <can-serial.h>
#include <mcp2515_can.h>
#include <mcp2515_can_dfs.h>
#include <mcp2518fd_can.h>
#include <mcp2518fd_can_dfs.h>
#include <mcp_can.h>
#ifndef TESTING
#include <Arduino.h>
#endif // Testing
#ifdef __AVR_ATmega2560__
// Only for Arduino Mega
#include <PinChangeInterrupt.h>
#endif // Mega
#include "DBW_Pins.h"
#include "Vehicle.h"
#include "Can_Protocol.h"
RC_Controller Vehicle::RC;
Brakes Vehicle::brake;
ThrottleController Vehicle::throttle;
#ifdef __AVR_ATmega2560__
mcp2515_can CAN(CAN_SS_PIN); // pin for CS on Mega
#endif
volatile int16_t Vehicle::desired_speed_mmPs;
volatile int16_t Vehicle::desired_brake;
volatile int16_t Vehicle::desired_angle;
/****************************************************************************
Constructor
****************************************************************************/
Vehicle::Vehicle() {
// Intialize default values
currentSpeed = 0;
currentAngle = 0;
currentBrake = 0;
brakeHold = 0;
desired_speed_mmPs = 0;
desired_brake = 0;
desired_angle = 0;
#ifdef __AVR_ATmega2560__
// Keep trying to initialize CAN
while (CAN_OK != CAN.begin(CAN_500KBPS)) {
if (DEBUG) {
Serial.println("CAN BUS Shield init fail");
}
delay(1000);
}
if (DEBUG)
Serial.println("CAN BUS init ok!");
#else
if (Can0.begin(CAN_BPS_500K)) // initalize CAN with 500kbps baud rate
{
Serial.println("Can0 init success");
} else {
Serial.println("Can0 init failed");
}
#endif // Mega
//attachPCINT(digitalPinToPCINT(IRPT_ESTOP_PIN), eStop, RISING);
//attachPCINT(digitalPinToPCINT(IRPT_CAN_PIN), recieveCan, RISING);
}
/*****************************************************************************
Destructor
****************************************************************************/
Vehicle::~Vehicle() {
}
/*****************************************************************************
Struct for sending current speed and angle to high-level board through CAN
****************************************************************************/
typedef union {
struct {
uint16_t sspeed;
uint16_t brake;
uint16_t angle;
uint16_t reserved;
};
} speedAngleMessage;
/*******************************************************************************************************
Checks for receipt of new CAN message and updates current
Vehicle speed and steering angle by passing code received from CAN
from RC or high-level board to the throttle and steering controllers
*******************************************************************************************************/
void Vehicle::update() {
recieveCan(); //check for new message
int16_t tempDspeed;
int16_t tempDbrake;
int16_t tempDangle;
noInterrupts();
tempDspeed = desired_speed_mmPs;
tempDbrake = desired_brake;
tempDangle = desired_angle;
interrupts();
//*******************************************************************************************
//CHOOSE between the 2 below based on test or actually running the system
//hard_Coded_Test(0, 24000); //test only, no vehicle results
real_System(tempDspeed, tempDbrake, tempDangle); //real system when using bike, not test
//*******************************************************************************************
//If speed not less than zero, send current speed and angle to high-level for processing
if (currentSpeed < 0) //stopped
return;
//build struct to send data to Highlevel through CAN
speedAngleMessage MSG;
MSG.sspeed = currentSpeed;
MSG.brake = currentBrake;
MSG.angle = currentAngle;
MSG.reserved = 0;
// unknown status (120 - 145)
#ifdef __AVR_ATmega2560__
CAN.MCP_CAN::sendMsgBuf(Actual_CANID, 0, 8, (uint8_t*)&MSG);
if (DEBUG) {
if (CAN_OK == CAN.MCP_CAN::sendMsgBuf(Actual_CANID, 0, 8, (uint8_t*)&MSG)) {
Serial.println("Sending Message to MEGA");
} else {
Serial.println("Message Failed");
}
}
#else
outgoing.data.int16[0] = MSG.sspeed;
outgoing.data.int16[1] = MSG.brake;
outgoing.data.int16[2] = MSG.angle;
outgoing.data.int16[3] = MSG.reserved;
Can0.sendFrame(outgoing);
if (DEBUG) {
if (Can0.sendFrame(outgoing)) {
Serial.println("Sending Message to DUE");
} else {
Serial.println("Message Failed");
}
}
#endif
// Update every second
delay(1000);
}
/********************************************************************************************************
Actual system for executing results with bike
*******************************************************************************************************/
void Vehicle::real_System(int16_t tempDspeed, int16_t tempDbrake, int16_t tempDangle) {
currentSpeed = throttle.update(tempDspeed);
currentBrake = tempDbrake; // brakes will update when recieving CAN messages
currentAngle = steer.update(tempDangle);
Serial.println("-----------------------------------------");
Serial.println("Actual Speed: " + String(currentSpeed));
Serial.println("Actual Brake: " + String(currentBrake));
Serial.println("Actual Angle: " + String(currentAngle));
}
/********************************************************************************************************
Hard coded to give back feedback to high level as if
the lowlevel had responded to the speed and angle requested by Highlevel board
*******************************************************************************************************/
void Vehicle::hard_Coded_Test(int16_t tempDspeed, int16_t tempDbrake, int16_t tempDangle) {
currentSpeed = tempDspeed;
currentBrake = tempDbrake;
currentAngle = tempDangle;
}
/*************************************************************************************
Checks for receipt of a message from CAN bus for new
speed/angle/brake instructions from RC or high-level board
************************************************************************************/
void Vehicle::recieveCan() { //need to ADD ALL the other CAN IDs possible (RC instructions etc. 4-23-19)
noInterrupts();
unsigned char len = 0;
unsigned char buf[8];
unsigned int canId = 0;
#ifdef __AVR_ATmega2560__ // CAN message receipt, if system is using Arduino Mega
if (CAN_MSGAVAIL == CAN.checkReceive()) { //found new instructions
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
canId = CAN.getCanId();
interrupts();
if (canId == HiDrive_CANID) { // the drive ID receive from high level
if (DEBUG) {
Serial.println("RECEIVED CAN MESSAGE FROM HIGH LEVEL WITH ID: " + String(canId, HEX));
}
// SPEED IN mm/s
uint16_t low_result = (buf[1] << 8) | buf[0];
desired_speed_mmPs = (int16_t)low_result;
// BRAKE ON/OFF
uint16_t mid_result = (buf[3] << 8) | buf[2];
desired_brake = (int16_t)mid_result;
if (desired_brake > 0 && brakeHold == 0) { // Activate Brakes
eStop();
} else if (desired_brake > 0 && brakeHold == 1) { // Hold Brakes
brake.Update();
} else {
brake.Release(); // Release Brakes
brakeHold = 0;
}
// WHEEL ANGLE
uint16_t high_result = (buf[5] << 8) | buf[4];
desired_angle = (int16_t)high_result;
if (DEBUG) {
Serial.print("CAN Speed: " + String(desired_speed_mmPs, DEC));
Serial.print(", CAN Brake: " + String(mid_result, DEC));
Serial.print(", CAN Angle: ");
Serial.println(desired_angle, DEC);
}
} else if (canId == HiStatus_CANID) { //High-level Status change (just e-stop for now 4/23/19)
desired_speed_mmPs = 0;
eStop();
}
}
#else // else CAN message receipt for system using Arduino Due
Can0.watchForRange(Actual_CANID, HiStatus_CANID); //filter for high level communication
while (Can0.available() > 0) { // check if CAN message available
Can0.read(incoming); // reading data from CAN message
canId = incoming.id;
}
interrupts();
if (canId == HiDrive_CANID) { // the drive ID receive from high level
if (DEBUG) {
Serial.println("RECEIVED CAN MESSAGE FROM HIGH LEVEL WITH ID: " + String(canId, HEX));
}
// SPEED IN mm/s
int16_t low_result = incoming.data.int16[0];
desired_speed_mmPs = low_result;
// BRAKE ON/OFF
int16_t mid_result = incoming.data.int16[1];
desired_brake = mid_result;
if (desired_brake > 0 && brakeHold == 0) { // Activate Brakes
eStop();
} else if (desired_brake > 0 && brakeHold == 1) { // Hold Brakes
brake.Update();
} else { // Release Brakes
brake.Release();
brakeHold = 0;
}
// WHEEL ANGLE
int16_t high_result = incoming.data.int16[2];
desired_angle = high_result;
if (DEBUG) {
Serial.print("CAN Speed: " + String(low_result, DEC));
Serial.print(", CAN Brake: " + String(mid_result, DEC));
Serial.print(", CAN Angle: ");
Serial.println(high_result, DEC);
Serial.println("mapped angle: " + String(desired_angle));
}
} else if (canId == HiStatus_CANID) { //High-level Status change (just e-stop for now 4/23/19)
desired_speed_mmPs = 0;
eStop();
}
#endif
}
//Estop method for high or RC calls
void Vehicle::eStop() {
if (DEBUG)
Serial.println("E-Stop!");
noInterrupts();
brake.Stop();
throttle.stop();
brakeHold = 1;
interrupts();
}
// RC Control of Trike
void Vehicle::updateRC() {
RC.mapValues();
if (RC.checkValidData()) {
if (RC.getMappedValue(RC_CH2_THROTTLE_BR) == -1 && brakeHold == 0) { // Activate brakes
//Serial.println("24V is on" + String(RC.getMappedValue(RC_CH2_THROTTLE_BR)));
eStop();
} else if (RC.getMappedValue(RC_CH2_THROTTLE_BR) == -1 && brakeHold == 1) { // Hold brakes
//Serial.println("Brake is on" + String(RC.getMappedValue(RC_CH2_THROTTLE_BR)));
brake.Update();
} else { // Release brakes
brakeHold = 0;
brake.Release();
throttle.update(RC.getMappedValue(RC_CH2_THROTTLE_BR));
//Serial.println(RC.getMappedValue(RC_CH2_THROTTLE_BR));
}
//steer.update(RC.getMappedValue(RC_CH1_STEERING));
}
RC.clearFlag();
}