Red Bird Racing VCU v2
 
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/**
2 * @file main.cpp
3 * @author Planeson, Chiho, Red Bird Racing
4 * @brief Main VCU program entry point
5 * @version 2.2.1
6 * @date 2026-02-25
7 * @dir include @brief Contains all header-only files.
8 * @dir lib @brief Contains all the libraries. Each library is in its own folder of the same name.
9 * @dir src @brief Contains the main.cpp file, the main file of the program.
10 */
11
12#include <Arduino.h>
13#include "BoardConfig.h"
14#include "Pedal.hpp"
15#include "BMS.hpp"
16#include "Enums.hpp"
17#include "CarState.hpp"
18#include "Scheduler.hpp"
19#include "Curves.hpp"
20#include "Telemetry.hpp"
21#include "Debug.hpp"
22
23// ignore -Wpedantic warnings for mcp2515.h
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wpedantic"
26#include <mcp2515.h>
27#pragma GCC diagnostic pop
28
29// ignore -Wunused-parameter warnings for Debug.h
30#pragma GCC diagnostic push
31#pragma GCC diagnostic ignored "-Wunused-parameter"
32#include "Debug.hpp"
33#pragma GCC diagnostic pop
34
35// === Pin setup ===
36// Pin setup for pedal pins are done by the constructor of Pedal object
37constexpr uint8_t INPUT_COUNT = 5;
38constexpr uint8_t OUTPUT_COUNT = 3;
40constexpr uint8_t pins_out[OUTPUT_COUNT] = {FRG, BRAKE_LIGHT, BUZZER};
41
42// === even if unused, initialize ALL mcp2515 to make sure the CS pin is set up and they don't interfere with the SPI bus ===
43MCP2515 mcp2515_motor(CS_CAN_MOTOR); // motor CAN
44MCP2515 mcp2515_BMS(CS_CAN_BMS); // BMS CAN
45MCP2515 mcp2515_DL(CS_CAN_DL); // datalogger CAN
46
47#define mcp2515_motor mcp2515_DL
48#define mcp2515_BMS mcp2515_DL
49// #define mcp2515_DL mcp2515_motor
50
51constexpr uint8_t NUM_MCP = 3;
53
54constexpr uint16_t BUSSIN_MILLIS = 2000; // The amount of time that the buzzer will buzz for
55constexpr uint16_t BMS_OVERRIDE_MILLIS = 1000; // The maximum amount of time to wait for the BMS to start HV, if passed, assume started but not reading response
56
57constexpr uint16_t BRAKE_THRESHOLD = BRAKE_TABLE[0].in; // The threshold for the brake pedal to be considered pressed
58
59bool brake_pressed = false; // boolean for brake light on VCU (for ignition)
60
61/**
62 * @brief Global car state structure.
63 * @see CarState
64 */
65struct CarState car = {
66 {}, // TelemetryPedal
67 {}, // TelemetryMotor
68 {}, // TelemetryBms
69 0, // millis
70 0 // status_millis
71};
72
73// Global objects
77
79{
81}
83{
85}
87{
88 bms.checkHv();
89}
91{
93}
95{
97}
99{
100 telem.sendBms();
101}
102
104 10000, // period_us
105 500, // spin_threshold_us
106 *micros // current_time_us function pointer
107);
108
109/**
110 * @brief Setup function for initializing the VCU system.
111 * Initializes MCP2515s, IO pins, as well as own modules such as Pedal and Debug.
112 */
113void setup()
114{
115#if DEBUG_SERIAL
117 DBGLN_GENERAL("===== VCU STARTUP =====");
118 DBGLN_GENERAL("Serial initialized");
119#endif
120
121 // init GPIO pins (MCP2515 CS pins initialized in constructor))
122 DBGLN_GENERAL("Initializing GPIO pins...");
123 for (uint8_t i = 0; i < INPUT_COUNT; ++i)
124 {
125 pinMode(pins_in[i], INPUT);
126 }
127 for (uint8_t i = 0; i < OUTPUT_COUNT; ++i)
128 {
129 pinMode(pins_out[i], OUTPUT);
130 digitalWrite(pins_out[i], LOW);
131 }
132 DBGLN_GENERAL("GPIO pins initialized");
133
134 // Initialize MCP2515 CAN controllers
135 DBGLN_GENERAL("Initializing CAN interfaces...");
136 for (uint8_t i = 0; i < NUM_MCP; ++i)
137 {
138 MCPS[i].reset();
139 MCPS[i].setBitrate(CAN_RATE, MCP2515_CRYSTAL_FREQ);
140 MCPS[i].setNormalMode();
141 }
142
143 // Initialize MCP2515 filters for Pedal and BMS
145 bms.initFilter();
146
147 while (!pedal.initMotor())
148 {
149 delay(20);
150 }
151
152 DBGLN_GENERAL("CAN interfaces initialized");
153
154#if DEBUG_CAN
155 DBGLN_GENERAL("Initializing Debug CAN...");
156 Debug_CAN::initialize(&mcp2515_DL); // Currently using datalogger CAN for debug messages
157 DBGLN_GENERAL("Debug CAN initialized");
158#endif
159
160 DBGLN_GENERAL("Adding scheduler tasks...");
166 DBGLN_GENERAL("Scheduler tasks added");
167
168 DBGLN_GENERAL("===== SETUP COMPLETE =====");
169}
170
171/**
172 * @brief Main loop function for the VCU system.
173 * Handles car state transitions, pipes dataflow between modules.
174 */
175void loop()
176{
177 // DBG_HALL_SENSOR(analogRead(HALL_SENSOR));
178 car.millis = millis();
179 pedal.update(analogRead(APPS_5V), analogRead(APPS_3V3), analogRead(BRAKE_IN));
180
182 digitalWrite(BRAKE_LIGHT, brake_pressed ? HIGH : LOW);
183 scheduler.update();
184
185 car.pedal.hall_sensor = analogRead(HALL_SENSOR);
186
188 {
189 car.pedal.status.bits.car_status = CarStatus::Init; // safety, later change to fault status
190 digitalWrite(BUZZER, LOW); // Turn off buzzer
191 digitalWrite(FRG, LOW); // Turn off drive mode LED
192 return; // If fault force stop is active, do not proceed with the rest of the loop
193 // pedal is still being updated, data can still be gathered and sent through CAN/serial
194 }
195
197 {
198 case CarStatus::Drive:
199 // send pedal update, done via Scheduler (always on)
200 return; // no need logic to check if pedal on, car started
201
202 // do not return here if not in DRIVE mode, else can't detect pedal being on while starting
203 case CarStatus::Init:
204 if (digitalRead(DRIVE_MODE_BTN) == BUTTON_ACTIVE && brake_pressed)
205 {
208
209 scheduler.addTask(McpIndex::Bms, scheduler_bms, 5); // check for HV ready in STARTIN
210 }
211 break;
212
214 if (digitalRead(DRIVE_MODE_BTN) != BUTTON_ACTIVE || !brake_pressed)
215 {
218 scheduler.removeTask(McpIndex::Bms, scheduler_bms); // stop checking BMS HV ready since return to INIT
219 break;
220 }
222 {
225 digitalWrite(BUZZER, HIGH);
226 scheduler.removeTask(McpIndex::Bms, scheduler_bms); // stop checking BMS HV ready since is already ready
227 break;
228 }
230 {
233 digitalWrite(BUZZER, HIGH);
234 scheduler.removeTask(McpIndex::Bms, scheduler_bms); // stop checking BMS HV ready since override to BUSSIN
235 break;
236 }
237 break;
238
241 {
242 digitalWrite(BUZZER, LOW);
243 digitalWrite(FRG, HIGH);
245 }
246 break;
247
248 /*
249 since we are switching on only 2 bits, and we use all 4 combinations,
250 it's physically impossible to reach a default case even with memory corruption, so no need for one
251
252 default:
253 // unreachable, reset to INIT
254 car.pedal.status.bits.state_unknown = true;
255 car.pedal.status.bits.car_status = CarStatus::Init;
256 car.status_millis = car.millis;
257 break;
258 */
259 }
260
261 // DRIVE mode has already returned, if reached here, then means car isn't in DRIVE
262 if (pedal.pedal_final > THROTTLE_TABLE[0].in) // if pedal pressed while not in DRIVE, reset to INIT
263 {
265 car.status_millis = car.millis; // Set to current time, in case any counter relies on this
266 }
267}
Declaration of the BMS class for managing the Accumulator (Kclear BMS) via CAN bus.
Board configuration for the VCU (Vehicle Control Unit)
#define BUZZER
Definition: BoardConfig.h:55
#define APPS_5V
Definition: BoardConfig.h:42
#define BRAKE_LIGHT
Definition: BoardConfig.h:48
#define APPS_3V3
Definition: BoardConfig.h:43
#define BRAKE_IN
Definition: BoardConfig.h:44
#define CAN_RATE
Definition: BoardConfig.h:205
#define CS_CAN_MOTOR
Definition: BoardConfig.h:39
#define CS_CAN_DL
Definition: BoardConfig.h:37
#define HALL_SENSOR
Definition: BoardConfig.h:45
#define MCP2515_CRYSTAL_FREQ
Definition: BoardConfig.h:61
#define DRIVE_MODE_BTN
Definition: BoardConfig.h:52
#define CS_CAN_BMS
Definition: BoardConfig.h:38
#define FRG
Definition: BoardConfig.h:51
#define BUTTON_ACTIVE
Definition: BoardConfig.h:58
Definition of the CarState structure representing the state of the car.
Definition of throttle and brake mapping tables.
constexpr TablePoint< uint16_t, int16_t > THROTTLE_TABLE[5]
Throttle mapping table (calculated), maps APPS_5V readings to torque values.
Definition: Curves.hpp:89
constexpr TablePoint< uint16_t, int16_t > BRAKE_TABLE[5]
Brake mapping table, negative values for regen.
Definition: Curves.hpp:48
Debugging macros and functions for serial and CAN output.
void DBGLN_GENERAL(const char *x)
Prints a line to the serial console for general debug.
Definition: Debug.hpp:56
Enumeration definitions for the VCU.
Declaration of the Pedal class for handling throttle and brake pedal inputs.
Declaration of the Scheduler class template, for scheduling tasks on multiple MCP2515 instances.
Declaration of the Telemetry class for sending telemetry data over CAN bus.
BMS class for managing the Accumulator (Kclear BMS) via CAN bus.
Definition: BMS.hpp:47
void checkHv()
Attempts to start HV. First check BMS is in standby(3) state, then send the HV start command....
Definition: BMS.cpp:62
void initFilter()
Initializes the CAN filters for reading BMS data. Call after constructing the BMS object and the MCP2...
Definition: BMS.cpp:45
Pedal class for managing throttle and brake pedal inputs. Handles filtering, fault detection,...
Definition: Pedal.hpp:68
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
bool initMotor()
Initializes the motor CAN communication by setting up cyclic reads for motor data and configuring CAN...
Definition: Pedal.cpp:72
void initFilter()
Initializes the CAN filters for reading motor data. Call after constructing the Pedal object and the ...
Definition: Pedal.cpp:52
void readMotor()
Reads motor data from the CAN bus and updates the CarState.
Definition: Pedal.cpp:286
uint16_t & pedal_final
Definition: Pedal.hpp:76
Scheduler class template for scheduling tasks on multiple MCP2515 instances Takes in function pointer...
Definition: Scheduler.hpp:45
Telemetry class for managing telemetry data transmission over CAN bus Grabs and sends telemetry frame...
Definition: Telemetry.hpp:27
void sendMotor()
Internal helper to get and send the motor telemetry frame.
Definition: Telemetry.cpp:34
void sendPedal()
Internal helper to get and send the Pedal telemetry frame.
Definition: Telemetry.cpp:25
void sendBms()
Internal helper to get and send the BMS telemetry frame.
Definition: Telemetry.cpp:43
Telemetry telem(mcp2515_DL, car)
Pedal pedal(mcp2515_DL, car, car.pedal.apps_5v)
void schedulerTelemetryPedal()
Definition: main.cpp:90
void schedulerPedalSend()
Definition: main.cpp:82
bool brake_pressed
Definition: main.cpp:59
MCP2515 MCPS[NUM_MCP]
Definition: main.cpp:52
void schedulerMotorRead()
Definition: main.cpp:78
void setup()
Setup function for initializing the VCU system. Initializes MCP2515s, IO pins, as well as own modules...
Definition: main.cpp:113
void scheduler_bms()
Definition: main.cpp:86
constexpr uint8_t OUTPUT_COUNT
Definition: main.cpp:38
#define mcp2515_BMS
Definition: main.cpp:48
void schedulerTelemetryBms()
Definition: main.cpp:98
constexpr uint16_t BRAKE_THRESHOLD
Definition: main.cpp:57
#define mcp2515_motor
Definition: main.cpp:47
constexpr uint8_t INPUT_COUNT
Definition: main.cpp:37
MCP2515 mcp2515_DL(CS_CAN_DL)
constexpr uint8_t NUM_MCP
Definition: main.cpp:51
constexpr uint16_t BMS_OVERRIDE_MILLIS
Definition: main.cpp:55
constexpr uint8_t pins_out[OUTPUT_COUNT]
Definition: main.cpp:40
struct CarState car
Global car state structure.
Definition: main.cpp:65
BMS bms(mcp2515_DL, car)
constexpr uint8_t pins_in[INPUT_COUNT]
Definition: main.cpp:39
constexpr uint16_t BUSSIN_MILLIS
Definition: main.cpp:54
void schedulerTelemetryMotor()
Definition: main.cpp:94
Scheduler< 3, NUM_MCP > scheduler(10000, 500, *micros)
void loop()
Main loop function for the VCU system. Handles car state transitions, pipes dataflow between modules.
Definition: main.cpp:175
void initialize(MCP2515 *can_interface)
Initializes the Debug_CAN interface. It should be called before using any other Debug_CAN functions.
Definition: Debug_can.cpp:26
void initialize()
Initializes the Debug_Serial interface. It should be called before using any other Debug_Serial funct...
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
uint32_t status_millis
Definition: CarState.hpp:162
StateByteStatus status
Definition: CarState.hpp:70
uint16_t hall_sensor
Definition: CarState.hpp:29
struct TelemetryFramePedal::StateByteStatus::Bits bits