forked from HanzeRacingDivision/HRD05-pedalbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcan.ino
168 lines (138 loc) · 4.87 KB
/
can.ino
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
#include "./can.h"
/**
* Sets up mcp2515 CAN bus.
*
* @todo set up message filters.
*
*/
void CAN::setup()
{
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
}
/**
* Determine if we're ready to send an update based on the configured data rate.
*/
bool CAN::should_send_update() {
return (millis() - last_can_sent) >= DATA_RATE;
}
/**
* Retrieve CAN messages from the bus.
*
* Note that there is always a 'stack' of messages to be read.
* readMessage() only retrieves the first message. Therefore, this function should be called continously.
*/
void CAN::get_messages()
{
int read_status = mcp2515.readMessage(&MSG);
// Read first CAN message on the CAN stack
if (read_status == MCP2515::ERROR_OK)
{
if (MSG.can_id == CAN::DASH::DASH_MSG.can_id) {
ReadyToDrive = MSG.data[0]; // RTD button from the dashboard
TSReady = MSG.data[1]; // TS status from the dashboard
last_valid_can_received = millis();
}
if (MSG.can_id == CAN::DMC514::DMC_TRQS.can_id) {
DMC_Ready = MSG.data[0];
DMC_SpdAct = MSG.data[6];
last_valid_can_received = millis();
}
}
// If we haven't received valid CAN in a while, something must be wrong. Go into safe state!
// @todo Pulling the car out of ready to drive mode **IS NOT A SAFE STATE**.
// If the car would be out of RTD, the inverter would be set to standby, and would be unable to combat the motors back-EMF.
if ((millis() - last_valid_can_received) >= CAN_TIMEOUT)
{
Serial.println("ERROR: CAN CONNECTION LOST! PEDALBOX SET TO SAFE STATE.");
TSReady = 0;
ReadyToDrive = 0;
DMC_Ready = 0;
DMC_TrqRq = 0;
}
}
/**
* Sends a control message to DMC514 inverter.
*
* @param THROTTLE The torque (in Nm) that the driver requested
* @param BRAKE The braking torque (in Nm) that the driver requested
*/
void CAN::DMC514::send_DMC_CTRL(float THROTTLE, float BRAKE)
{
float TORQUE_REQUEST = 0.0f;
// Re-constrain requested values to make this idiot-proof.
THROTTLE = constrain(THROTTLE, 0.0f, MAX_TORQUE);
BRAKE = constrain(BRAKE, 0.0f, MAX_BRAKE);
// Prevent BSPD from triggering (torque request > 5Nm and braking more than 50%)
if (THROTTLE > 5.0f && (BRAKE > (MAX_BRAKE * 0.5f)))
THROTTLE = 0.0f;
// Reduce requested torque by the braking request. Allows the torque request to become negative (regenerative braking).
TORQUE_REQUEST = THROTTLE - BRAKE;
if (DMC_SpdAct > MIN_SPEED) {
// If regenerative braking is disabled, do not allow negative torque request.
if (!ENABLE_REGENERATIVE_BRAKING) TORQUE_REQUEST = constrain(TORQUE_REQUEST, 0.0f, MAX_TORQUE);
} else {
// Prevent backwards driving by only allowing positive torque below MIN_SPEED.
// Note that this *should* also be handled by the DMC_NegTrqSpd setting.
TORQUE_REQUEST = constrain(TORQUE_REQUEST, 0.0f, MAX_TORQUE);
// Prevent bucking by disabling inverter control at low speed. Also refer to Brusa control PDF.
if (TORQUE_REQUEST < 1.0f) {
DMC_EnableRq = 0;
TORQUE_REQUEST = 0.0f;
} else {
DMC_EnableRq = 1;
}
}
// Convert final torque (Nm) to 0.01Nm/bit
DMC_TrqRq = TORQUE_REQUEST * 100.0f;
byte bitData[8];
bitData[0] = DMC_EnableRq;
bitData[1] = DMC_ModeRq;
bitData[2] = DMC_OscLimEnableRq;
bitData[3] = 0;
bitData[4] = DMC_ClrError;
bitData[5] = 0;
bitData[6] = DMC_NegTrqSpd;
bitData[7] = DMC_PosTrqSpd;
// Serial.println(DMC_CTRL.data[0]); // Needs testing
DMC_CTRL.data[0] = *bitData;
DMC_CTRL.data[2] = highByte(DMC_SpdRq); // Motorola format
DMC_CTRL.data[3] = lowByte(DMC_SpdRq); // Motorola format
DMC_CTRL.data[4] = highByte(DMC_TrqRq); // Motorola format
DMC_CTRL.data[5] = lowByte(DMC_TrqRq); // Motorola format
Serial.println("SENDING APPS: ");
Serial.println(DMC_TrqRq);
mcp2515.sendMessage(&DMC_CTRL);
last_can_sent = millis();
}
/**
* Set the DMC514 inverter to standby mode.
*
* @todo Handle / track inverter errors.
*
* @param clearError requests an error clear to continue operation
*/
void CAN::DMC514::set_standby(const bool& clearError)
{
DMC_TrqRq = 0;
DMC_EnableRq = 0;
byte bitData[8];
bitData[0] = DMC_EnableRq;
bitData[1] = DMC_ModeRq;
bitData[2] = DMC_OscLimEnableRq;
bitData[3] = 0;
bitData[4] = clearError;
bitData[5] = 0;
bitData[6] = DMC_NegTrqSpd;
bitData[7] = DMC_PosTrqSpd;
DMC_CTRL.data[0] = *bitData;
DMC_CTRL.data[2] = 0;
DMC_CTRL.data[3] = 0;
DMC_CTRL.data[4] = 0;
DMC_CTRL.data[5] = 0;
mcp2515.sendMessage(&DMC_CTRL);
last_can_sent = millis();
// if (clearError)
// clearError = 0;
}