Red Bird Racing VCU v2
 
Loading...
Searching...
No Matches
Pedal.cpp
Go to the documentation of this file.
1/**
2 * @file Pedal.cpp
3 * @author Planeson, Chiho, Red Bird Racing
4 * @brief Implementation of the Pedal class for handling throttle pedal inputs
5 * @version 1.7
6 * @date 2026-02-25
7 * @see Pedal.hpp
8 */
9
10#include "Pedal.hpp"
11#include "SignalProcessing.hpp"
12#include "CarState.hpp"
13#include <stdint.h>
14#include "Queue.hpp"
15#include "CarState.hpp"
16#include "Interp.hpp"
17#include "Curves.hpp"
18
19// ignore -Wunused-parameter warnings for Debug.h
20#pragma GCC diagnostic push
21#pragma GCC diagnostic ignored "-Wunused-parameter"
22#include "Debug.hpp" // DBGLN_GENERAL
23#pragma GCC diagnostic pop
24
25/**
26 * @brief Constructor for the Pedal class.
27 * Initializes the pedal state. fault is set to true initially,
28 * so you must send update within 100ms of starting the car to clear it.
29 * Call the initMotor function to set up the motor CAN filters and cyclic reads after constructing the Pedal object and the MCP2515 object it references.
30 * @param motor_can_ Reference to the MCP2515 instance for motor CAN communication.
31 * @param car_ Reference to the CarState structure.
32 * @param pedal_final_ Reference to the pedal used as the final pedal value. Although not recommended, you can set another uint16 outside Pedal to be something like 0.3 APPS_1 + 0.7 APPS_2, then reference that here. If in future, this become a sustained need, should consider adding a function pointer to find the final pedal value to let Pedal class call it itself.
33 */
34Pedal::Pedal(MCP2515 &motor_can_, CarState &car_, uint16_t &pedal_final_)
35 : pedal_final(pedal_final_),
36 car(car_),
37 motor_can(motor_can_),
38 fault_start_millis(0),
39 last_motor_read_millis(0),
40 got_speed(false),
41 got_error(false)
42{
43}
44
45/**
46 * @brief Initializes the CAN filters for reading motor data.
47 * Call after constructing the Pedal object and the MCP2515 object it references to ensure motor data is being read correctly.
48 * This function will block until the filter is set correctly on the MCP2515. If it never succeed, the program will be stuck here.
49 * Consider that when we can't even set the filter on the MCP2515, we probably can't communicate with the motor controller at all,
50 * so being stuck here is acceptable since the car won't be drivable without motor communication anyway.
51 */
53{
54 // set MCU CAN filter
55 motor_can.setConfigMode();
56 while (motor_can.setFilterMask(MCP2515::MASK0, false, 0x7FF) != MCP2515::ERROR_OK)
57 ;
58 while (motor_can.setFilter(MCP2515::RXF0, false, MOTOR_READ) != MCP2515::ERROR_OK)
59 ;
60 motor_can.setNormalMode();
61}
62
63/**
64 * @brief Initializes the motor CAN communication by setting up cyclic reads for motor data and configuring CAN filters.
65 * After the constructor of the Pedal class and the MCP2515 object it references are created,
66 * first call initFilter to set up the filters,
67 * then call this function to start the cyclic reads and ensure that motor data is being read correctly.
68 *
69 * @return true if both motor speed and error data are being successfully read, false otherwise, can be used for looping
70 * @see initFilter
71 */
73{
74 if (!got_speed)
75 {
76 while (sendCyclicRead(SPEED_IST, RPM_PERIOD) != MCP2515::ERROR_OK)
77 ;
79 }
80 if (!got_error)
81 {
82 while (sendCyclicRead(WARN_ERR, ERR_PERIOD) != MCP2515::ERROR_OK)
83 ;
85 }
86 return got_speed && got_error;
87}
88
89/**
90 * @brief Updates pedal sensor readings, applies filtering, and checks for faults.
91 *
92 * Stores new pedal readings, applies an average filter, and updates car state.
93 * If a fault is detected between pedal sensors, sets fault flags and logs status.
94 *
95 * @param pedal_1 Raw value from pedal sensor 1.
96 * @param pedal_2 Raw value from pedal sensor 2.
97 * @param brake Raw value from brake sensor.
98 */
99void Pedal::update(uint16_t pedal_1, uint16_t pedal_2, uint16_t brake)
100{
101 // Add new samples to the filters
102 pedal1_filter.addSample(pedal_1);
103 pedal2_filter.addSample(pedal_2);
104 brake_filter.addSample(brake);
105
106 if (pedal_1 < APPS_5V_MIN)
108 if (pedal_1 > APPS_5V_MAX)
110 if (pedal_2 < APPS_3V3_MIN)
112 if (pedal_2 > APPS_3V3_MAX)
114 if (brake < brake_min)
116 if (brake > brake_max)
118
119 if (checkPedalFault())
120 {
121 // fault now
123 {
124 // was faulty already, check time
125 if (car.millis - fault_start_millis > 100)
126 {
128 car.pedal.status.bits.force_stop = true; // critical fault, force stop; since early return, need set here
129 return;
130 }
131 }
132 else
133 {
134 // new fault
136 }
138 }
139 else
140 {
141 // no fault
143 }
144
146 {
147 car.pedal.status.bits.force_stop = true; // critical fault, force stop
148 }
149
150 return;
151}
152
153/**
154 * @brief Sends the appropriate CAN frame to the motor based on pedal and car state.
155 */
157{
158 // Update Telemetry struct
162
163 if (false && car.pedal.status.bits.force_stop)
164 {
165 motor_can.sendMessage(&stop_frame);
166 return;
167 }
168 if (car.pedal.status.bits.car_status != CarStatus::Drive)
169 {
170 motor_can.sendMessage(&stop_frame);
171 return;
172 }
173
175
176 torque_msg.data[1] = car.motor.torque_val & 0xFF;
177 torque_msg.data[2] = (car.motor.torque_val >> 8) & 0xFF;
178 motor_can.sendMessage(&torque_msg);
179 return;
180}
181
182/**
183 * @brief Maps the pedal ADC to a torque value.
184 * If no braking requested, maps throttle normally.
185 * If braking requested and regen enabled,
186 * applies regen if motor RPM larger than minimum regen RPM,
187 * preventing reverse torque at low speeds.
188 * Regen is also disabled if motor rpm isn't read recently to prevent reverse power.
189 *
190 * @param pedal Pedal ADC in the range of 0-1023.
191 * @param brake Brake ADC in the range of 0-1023.
192 * @param motor_rpm Current motor RPM for regen logic, scaled to 0-32767.
193 * @param flip_dir Boolean indicating whether to flip the motor direction.
194 * @return Mapped torque value in the signed range of -TORQUE_MAX to TORQUE_MAX.
195 */
196constexpr int16_t Pedal::pedalTorqueMapping(const uint16_t pedal, const uint16_t brake, const int16_t motor_rpm, const bool flip_dir)
197{
199 {
200 if (pedal > THROTTLE_MAP.start())
201 {
203 // to ensure BSPD can be tested, skip regen if both throttle and brake pressed
204 }
205 else if (!flip_dir)
206 {
207 if (motor_rpm < PedalConstants::MIN_REGEN_RPM_VAL)
208 return 0;
209 else
210
211 return BRAKE_MAP.interp(brake);
212 }
213 else
214 {
215 if (motor_rpm > -PedalConstants::MIN_REGEN_RPM_VAL)
216 return 0;
217 else
218 return -BRAKE_MAP.interp(brake);
219 }
220 }
221
222 if (flip_dir)
223 return -THROTTLE_MAP.interp(pedal);
224 else
225 return THROTTLE_MAP.interp(pedal);
226}
227
228/**
229 * @brief Checks for a fault between two pedal sensor readings.
230 *
231 * Scales pedal_2 to match the range of pedal_1, then calculates the absolute difference.
232 * If the difference exceeds 10% of the full-scale value (i.e., >102.4 for a 10-bit ADC),
233 * the function considers this a fault and returns true. Otherwise, returns false.
234 *
235 * @return true if the difference exceeds the threshold (fault detected), false otherwise.
236 */
238{
240 {
241 return false;
242 }
243 const int16_t delta = (int16_t)car.pedal.apps_5v - (int16_t)APPS_3V3_SCALE_MAP.interp(car.pedal.apps_3v3);
244 constexpr int16_t MAX_DELTA = THROTTLE_MAP.range() / 10; /**< MAX_DELTA is floor of 10% of APPS_5V valid range, later comparison will give rounding room */
245 // if more than 10% difference between the two pedals, consider it a fault
246 if (delta > MAX_DELTA || delta < -MAX_DELTA)
247 {
248 return true;
249 }
250 return false;
251}
252
253/**
254 * @brief Sends a cyclic read request to the motor controller for speed (rpm).
255 * @param reg_id Register ID to read from the motor controller.
256 * @param read_period Period of reading motor data in ms.
257 */
258MCP2515::ERROR Pedal::sendCyclicRead(const uint8_t reg_id, const uint8_t read_period)
259{
260 const can_frame cyclic_request = {
261 MOTOR_SEND, /**< can_id */
262 3, /**< can_dlc */
263 REGID_READ, /**< data, register ID */
264 reg_id, /**< data, sub ID */
265 read_period /**< data, read period in ms */
266 };
267 return motor_can.sendMessage(&cyclic_request);
268}
269
270bool Pedal::checkCyclicRead(const uint8_t reg_id)
271{
272 can_frame rx_frame;
273 if (motor_can.readMessage(&rx_frame) == MCP2515::ERROR_OK &&
274 rx_frame.can_id == MOTOR_READ &&
275 rx_frame.can_dlc > 3 &&
276 rx_frame.data[0] == reg_id)
277 {
278 return true;
279 }
280 return false;
281}
282
283/**
284 * @brief Reads motor data from the CAN bus and updates the CarState.
285 */
287{
288 can_frame rx_frame;
289 if (motor_can.readMessage(&rx_frame) == MCP2515::ERROR_OK)
290 {
291 if (rx_frame.can_id == MOTOR_READ && rx_frame.can_dlc > 3)
292 {
293 if (rx_frame.data[0] == SPEED_IST)
294 {
297 car.motor.motor_rpm = static_cast<int16_t>(rx_frame.data[1] | (rx_frame.data[2] << 8));
298 return;
299 }
300 else if (rx_frame.data[0] == WARN_ERR)
301 {
302 car.motor.motor_error = static_cast<uint16_t>(rx_frame.data[1] | (rx_frame.data[2] << 8));
303 car.motor.motor_warn = static_cast<uint16_t>(rx_frame.data[3] | (rx_frame.data[4] << 8));
304 return;
305 }
306 }
307 }
309 {
311 }
312 return;
313}
Definition of the CarState structure representing the state of the car.
Definition of throttle and brake mapping tables.
constexpr uint16_t APPS_3V3_MIN
Definition: Curves.hpp:20
constexpr uint16_t brake_min
Definition: Curves.hpp:42
constexpr TablePoint< uint16_t, uint16_t > APPS_5V_PERCENT_TABLE[2]
APPS_5V to percent mapping table, maps 5V readings to percent throttle (0-60000)
Definition: Curves.hpp:66
constexpr uint16_t APPS_3V3_MAX
Definition: Curves.hpp:21
constexpr uint16_t brake_max
Definition: Curves.hpp:43
constexpr uint16_t APPS_5V_MIN
Definition: Curves.hpp:17
constexpr uint16_t APPS_5V_MAX
Definition: Curves.hpp:18
Debugging macros and functions for serial and CAN output.
Declaration and definition of the LinearInterp class template for linear interpolation.
Declaration of the Pedal class for handling throttle and brake pedal inputs.
constexpr uint16_t FAULT_CHECK_HEX
Definition: Pedal.hpp:34
constexpr bool FLIP_MOTOR_DIR
Definition: Pedal.hpp:30
constexpr bool REGEN_ENABLED
Definition: Pedal.hpp:28
constexpr uint32_t MAX_MOTOR_READ_MILLIS
Definition: Pedal.hpp:36
Declaration of a simple RingBuffer (circular buffer) template class.
Declaration of signal processing functions.
void addSample(TypeInput sample) override
Adds a new sample to the ExponentialFilter. Updates the filtered value using the exponential moving a...
TypeInput getFiltered() const override
Retrieves the filtered value from the ExponentialFilter.
constexpr Tout interp(Tin input) const
Performs linear interpolation for the given input value, using the table.
Definition: Interp.hpp:45
constexpr Tin range() const
Returns the input range of the interpolation table (last input - first input)
Definition: Interp.hpp:83
constexpr Tin start() const
Returns the starting input value of the interpolation table.
Definition: Interp.hpp:74
void update(uint16_t pedal_1, uint16_t pedal_2, uint16_t brake)
Updates pedal sensor readings, applies filtering, and checks for faults.
Definition: Pedal.cpp:99
void sendFrame()
Sends the appropriate CAN frame to the motor based on pedal and car state.
Definition: Pedal.cpp:156
Pedal(MCP2515 &motor_can_, CarState &car, uint16_t &pedal_final_)
Constructor for the Pedal class. Initializes the pedal state. fault is set to true initially,...
Definition: Pedal.cpp:34
bool initMotor()
Initializes the motor CAN communication by setting up cyclic reads for motor data and configuring CAN...
Definition: Pedal.cpp:72
bool checkCyclicRead(uint8_t reg_id)
Definition: Pedal.cpp:270
bool checkPedalFault()
Checks for a fault between two pedal sensor readings.
Definition: Pedal.cpp:237
static constexpr uint8_t WARN_ERR
Definition: Pedal.hpp:122
static constexpr LinearInterp< uint16_t, int16_t, int32_t, 5 > BRAKE_MAP
Definition: Pedal.hpp:113
void initFilter()
Initializes the CAN filters for reading motor data. Call after constructing the Pedal object and the ...
Definition: Pedal.cpp:52
MCP2515 & motor_can
Definition: Pedal.hpp:80
static constexpr LinearInterp< uint16_t, int16_t, int32_t, 5 > THROTTLE_MAP
Definition: Pedal.hpp:112
CarState & car
Definition: Pedal.hpp:79
static constexpr canid_t MOTOR_READ
Definition: Pedal.hpp:117
static constexpr LinearInterp< uint16_t, uint16_t, uint32_t, 3 > APPS_3V3_SCALE_MAP
Definition: Pedal.hpp:114
const can_frame stop_frame
CAN frame to stop the motor.
Definition: Pedal.hpp:90
static constexpr uint8_t REGID_READ
Definition: Pedal.hpp:119
void readMotor()
Reads motor data from the CAN bus and updates the CarState.
Definition: Pedal.cpp:286
uint32_t last_motor_read_millis
Definition: Pedal.hpp:82
static constexpr uint8_t RPM_PERIOD
Definition: Pedal.hpp:124
ExponentialFilter< uint16_t, uint16_t > brake_filter
Definition: Pedal.hpp:110
uint16_t & pedal_final
Definition: Pedal.hpp:76
static constexpr canid_t MOTOR_SEND
Definition: Pedal.hpp:116
ExponentialFilter< uint16_t, uint16_t > pedal1_filter
Definition: Pedal.hpp:108
static constexpr uint8_t SPEED_IST
Definition: Pedal.hpp:121
can_frame torque_msg
CAN frame for torque command.
Definition: Pedal.hpp:100
constexpr int16_t pedalTorqueMapping(const uint16_t pedal, const uint16_t brake, const int16_t motor_rpm, const bool flip_dir)
Maps the pedal ADC to a torque value. If no braking requested, maps throttle normally....
Definition: Pedal.cpp:196
static constexpr uint8_t ERR_PERIOD
Definition: Pedal.hpp:125
MCP2515::ERROR sendCyclicRead(uint8_t reg_id, uint8_t read_period)
Sends a cyclic read request to the motor controller for speed (rpm).
Definition: Pedal.cpp:258
uint32_t fault_start_millis
Definition: Pedal.hpp:81
ExponentialFilter< uint16_t, uint16_t > pedal2_filter
Definition: Pedal.hpp:109
bool got_error
Definition: Pedal.hpp:85
bool got_speed
Definition: Pedal.hpp:84
Pedal pedal(mcp2515_DL, car, car.pedal.apps_5v)
struct CarState car
Global car state structure.
Definition: main.cpp:65
constexpr int16_t MIN_REGEN_RPM_VAL
Definition: Pedal.hpp:58
Represents the state of the car. Holds telemetry data and status, used as central data sharing struct...
Definition: CarState.hpp:158
uint32_t millis
Definition: CarState.hpp:163
TelemetryFramePedal pedal
Definition: CarState.hpp:159
TelemetryFrameMotor motor
Definition: CarState.hpp:160
uint16_t motor_error
Definition: CarState.hpp:100
uint16_t motor_rpm
Definition: CarState.hpp:99
StateByteStatus status
Definition: CarState.hpp:70
StateByteFaults faults
Definition: CarState.hpp:71
struct TelemetryFramePedal::StateByteFaults::Bits bits
struct TelemetryFramePedal::StateByteStatus::Bits bits