SAE Teensy ECU
IIT SAE Microcontroller programming
Loading...
Searching...
No Matches
MotorControl.cpp
Go to the documentation of this file.
1
12// @cond
13
14#include <stdint.h>
15#include <stdlib.h>
16
17#include "Canbus.h"
18#include "ECUGlobalConfig.h"
19#include "MotorControl.def"
20#include "MotorControl.h"
21#include "Pins.h"
22#include "Util.h"
23#include "log.h"
24
25namespace MC {
26
27#define NORM_VAL (double)PINS_ANALOG_MAX
28#define MAX_TORQUE CONF_MAX_TORQUE
29
30#define PEDAL_MIN CONF_PEDAL_MIN
31#define PEDAL_MAX CONF_PEDAL_MAX
32
33#define BRAKE_MIN CONF_BRAKE_MIN
34#define BRAKE_MAX CONF_BRAKE_MAX
35
36#define STEER_MIN CONF_STEER_MIN
37#define STEER_MAX CONF_STEER_MAX
38
39static LOG_TAG ID = "MotorControl";
40
41static int motorTorque[2] = {0, 0};
42
43static bool beating = true;
44static bool init = false;
45static bool forward = true;
46
47static double pAccum = 0, bAccum = 0, sAccum = 0;
48
49static Canbus::Buffer MC0_RPM_Buffer(ADD_MC0_RPM);
50static Canbus::Buffer MC1_RPM_Buffer(ADD_MC1_RPM);
51
52static void beatFunc(void) {
53 if (beating) {
54 Canbus::sendData(ADD_MC0_CTRL);
55 Canbus::sendData(ADD_MC1_CTRL);
56 }
57}
58
59constexpr float c = 2 * 3.1415926536 * 9;
60
61int32_t motorSpeed(int motor) {
62 int16_t MC_Rpm_Val_0 = -MC0_RPM_Buffer.getShort(2); // Bytes 2-3 : Angular Velocity // NOTE: motor is negative?
63 int16_t MC_Rpm_Val_1 = MC1_RPM_Buffer.getShort(2); // Bytes 2-3 : Angular Velocity
64 float MC_Spd_Val_0 = (float)(((MC_Rpm_Val_0 / CONF_CAR_GEAR_RATIO) * c) * 60) / 63360;
65 float MC_Spd_Val_1 = (float)(((MC_Rpm_Val_1 / CONF_CAR_GEAR_RATIO) * c) * 60) / 63360;
66
67 switch (motor) {
68 case 0:
69 return MC_Spd_Val_0;
70 case 1:
71 return MC_Spd_Val_1;
72 default:
73 return (MC_Spd_Val_0 + MC_Spd_Val_1) / 2;
74 }
75}
76
77static void normalizeInput(double *pedal, double *brake, double *steer) { // TODO: GET THIS OUT OF HERE! Does not belong here
78 pAccum = EMAvg(pAccum, cMap(*pedal, PEDAL_MIN, PEDAL_MAX, 0.0, NORM_VAL), 8);
79 bAccum = EMAvg(bAccum, cMap(*brake, BRAKE_MIN, BRAKE_MAX, 0.0, NORM_VAL), 8);
80 sAccum = EMAvg(sAccum, cMap(*steer, STEER_MIN, STEER_MAX, 0.0, NORM_VAL), 8);
81
82 *pedal = pAccum;
83 *brake = bAccum;
84 *steer = cMap(sAccum, 0.0, NORM_VAL, -PI / 9, PI / 9);
85}
86
87static void torqueVector(int pedal, int brake, int steer) {
88
89 double _pedal = pedal, _brake = brake, _steer = steer;
90
91 normalizeInput(&_pedal, &_brake, &_steer);
92
93 float TVAggression = (float)Pins::getCanPinValue(PINS_INTERNAL_TVAGG) / 10000.0f;
94
95 Log.d(ID, "Aggression Val x1000:", TVAggression * 1000, true);
96
97 // No TV
98
99 // TODO: Test Torque Vectoring and Regenerative braking
100
101 if (_pedal < 0) { // FIXME: Sensor on car flipped?
102 // _pedal = -_pedal;
103 // motorTorque[0] = -cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
104 // motorTorque[1] = -cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
105 } else {
106 motorTorque[0] = cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
107 motorTorque[1] = cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
108
109 // Flipped sensor?
110
111 // TV V1
112 // if (_steer > 0) {
113 // motorTorque[0] = cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
114 // motorTorque[1] = motorTorque[0] * clamp(pow(cos(TVAggression * _steer), 5), 0, 1);
115 // } else {
116 // motorTorque[1] = cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
117 // motorTorque[0] = motorTorque[1] * clamp(pow(cos(TVAggression * _steer), 5), 0, 1);
118 // }
119 }
120
121 // motorTorque[0] = cMap(_pedal, 0.0, NORM_VAL, 0.0, MAX_TORQUE);
122 // motorTorque[1] = motorTorque[0];
123}
124
125void setup(void) { // IMPROVE: receive message from MCs, not just send
126 if (!init)
127 Heartbeat::addCallback(beatFunc);
128 clearFaults();
129 init = true;
130 beating = true;
131}
132
133void clearFaults(void) {
134 Canbus::sendData(ADD_MC0_CLEAR, 20, 0, 1);
135 Canbus::sendData(ADD_MC1_CLEAR, 20, 0, 1);
136 Canbus::sendData(ADD_MC0_CTRL);
137 Canbus::sendData(ADD_MC1_CTRL);
138}
139
140void enableMotorBeating(bool enable) {
141 beating = enable;
142}
143
144int sendSpeed(uint32_t MC_ADD, int speed, bool direction, bool enableBit) {
145 if (beating) {
146 Log.w(ID, "Unable to set torque, heartbeat is on");
147 return 0;
148 }
149 int setSpeed = 0, torqueLimit = 50;
150 if (speed != 0) { // max analog should be what the max pedal readout is
151 setSpeed = cMap(speed, 200, PINS_ANALOG_MAX, 0, 10); // separate func for negative vals (regen)
152 }
153
154 uint8_t *bytes = (uint8_t *)&setSpeed;
155 uint8_t *limitBytes = (uint8_t *)&torqueLimit;
156 Canbus::sendData(MC_ADD, 0, 0, bytes[0], bytes[1], direction, 0b101 * enableBit, limitBytes[0], limitBytes[1]);
157 return setSpeed;
158}
159
160void sendTorque(uint32_t MC_ADD, int torque, bool direction, bool enableBit) { // NOTE: 0 (Clockwise = Reverse) 1 (Anticlockwise = Forward)
161 if (beating) {
162 Log.w(ID, "Unable to set torque, heartbeat is on");
163 return;
164 }
165 uint8_t *bytes = (uint8_t *)&torque;
166 Canbus::sendData(MC_ADD, bytes[0], bytes[1], 0, 0, direction, enableBit);
167}
168
169bool isForward(void) {
170 return forward;
171}
172
173void setDirection(bool runForward) { // FIXME: Inverter must be switched off before switching direction, else fault must be cleared and inverter started again
175 Log.w(ID, "Switching direction");
176 forward = runForward;
177 } else {
178 Log.e(ID, "Unable to switch direction, car is moving too much");
179 }
180}
181
182int getLastTorqueValue(bool mc0) {
183 return mc0 ? motorTorque[0] : motorTorque[1];
184}
185
186int getLastPedalValue() {
187 return pAccum;
188}
189
190int getLastBrakeValue() {
191 return (int)bAccum;
192}
193
194int getLastSteerValue() {
195 return cMap(sAccum, 0.0, NORM_VAL, -PI / 9, PI / 9);
196}
197
198void setTorque(int pedal, int brake, int steer) {
199 torqueVector(pedal, brake, steer);
200 sendTorque(ADD_MC1_CTRL, motorTorque[1], forward, 1);
201 sendTorque(ADD_MC0_CTRL, motorTorque[0], forward, 1);
202}
203
204} // namespace MC
205
206// @endcond
FlexCAN_T4 wrapper.
Configure global build properties.
Special logging functionality.
const char * LOG_TAG
Type definition of logging tags This typedef is necessary to allow for easier manipulation of code by...
Definition Log.h:48
Logging::Log_t Log
The global logging object.
#define CONF_CAR_GEAR_RATIO
The radius of the car's wheels as a float.
Motor Controller module.
#define CONF_MAXIMUM_SWITCHING_SPEED
The maximum speed value that the car can be moving before it switches between forwards and reverse.
Update, set, and get predefined pin values.
#define PINS_ANALOG_MAX
The maximum analog value, given the current PINS_ANALOG_RES.
Definition Pins.h:63
double EMAvg(double lastVal, double newVal, int memCount)
Exponential moving average.
Definition Util.cpp:14
Various utility functions.
T cMap(T x, A inMin, B inMax, C outMin, D outMax)
Map a value from one range to another while clamping the value to boundaries.
Definition Util.h:46
void addCallback(beatFunc func)
Add a callback to be run at each haertbeat.
void(* beatFunc)(void)
Function called each time the heart beats.
Definition Heartbeat.h:35
Methods used to more easily interface with RMS Motor controllers over CAN bus.
void sendTorque(uint32_t MC_ADD, int torque, bool direction, bool enableBit)
Send a raw torque command to a MC.
void setTorque(int pedal, int brake, int steer)
Calculate and set the torque of both MCs.
int getLastSteerValue()
Get the last steer value that was internally used.
int getLastBrakeValue()
Get the last brake value that was internally used.
void setDirection(bool runForward)
Set the direction of the motors.
bool isForward(void)
Get whether the motors will spin forward.
int getLastTorqueValue(bool mc0)
Get the last torque percent value sent to a MC.
int getLastPedalValue(void)
Get the last pedal value that was internally used.
int32_t motorSpeed(int motor=-1)
Get the avg motorspeed.
void enableMotorBeating(bool enable)
Start MC heartbeat function, establishing a connection with the MCs.
void clearFaults(void)
Clear MC faults by sending a clear fault command.
void setup(void)
Initialize MC heartbeat function and clear faults, if any.
int getCanPinValue(uint8_t CAN_GPIO_Pin)
Get the pin value of a predefined canbus pin.
void d(LOG_TAG TAG, LOG_MSG message)
Log a string using a debug tag.
void w(LOG_TAG TAG, LOG_MSG message)
Log a string using a warning tag.
void e(LOG_TAG TAG, LOG_MSG message)
Log a string using an error tag.