Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 129 additions & 3 deletions src/intro_project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ you end up with lots of useless formatting changes. You should install
clang-format as soon as possible and set it up :)
*/

typedef struct { // These 4 variables are shared by two threads - Dinu
float current;
float wheelspeeds;
float steering_angle;
float torque;
} movement_vehicle_data;

typedef int mutex_t mutex_create(void);

extern bool mutex_take(mutex_t mutex);
extern bool mutex_give(mutex_t mutex);

for(int j = 0; j < movement_vehicle_data.wheelspeeds.length(); j++) {}

/*
Initialize the CAN peripheral with given RX and TX pins at a given baudrate.
*/
Expand Down Expand Up @@ -161,6 +175,118 @@ extern float bms_get_voltage(uint8_t n);
*/
extern float bms_get_temperature(uint8_t n);

void setup(void) {}

void loop(void) {}
#define CAN_BAUDRATE 500000
#define MOTOR_TEETH 17
#define SPEED_TIME 10
#define MOTOR_CONTROL_TIME 1
#define DISPLAY_DELAY 100
#define SAFETY_DELAY 20

static movement_vehicle_data vehicle_data;
static mutex_t vehicle_mutex;

void calculate_rpm(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine, but it might not work at high speeds, and there's a better way to do it. Think about how you could do this with interrupts

int rotation = 0;

for(;;) {
delay(SPEED_TIME);

if(wheel_pin == low) {
rotation++;
}

vehicle_data.wheelspeeds = rotation / (SPEED_TIME * 6000);
}
}

void motor_control_thread(void) {
for(;;) { // Infinite For Loop
delay(MOTOR_CONTROL_TIME);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delay will pause every thread, not just the one you call it in. Look for how to do delays in FreeRTOS


while(!mutex_take(vehicle_mutex)) {
} // Return true or false, to know whether mutex lock was acquired or not

calculate_torque_cmd(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature looks like this:

extern void calculate_torque_cmd(
  float *torques, float current, float *wheelspeeds, float steering_angle
);

The biggest issue rn (aside from the order ur passing them in), is that torques and wheelspeeds should be arrays, but in your struct movement_vehicle_data they are single values.

The idea behind calculate_torque_cmd is that the output is an array of floats for torque. So I must initialize an array of floats somewhere, then give calculate_torque_cmd a pointer to that array so it can populate it with values. On the other hand, wheelspeeds is an input, and should be an array containing 4 wheelspeeds (one for each wheel).

vehicle_data.torque, vehicle_data.current, vehicle_data.steering_angle,
vehicle_data.wheelspeeds
);

mutex_give(vehicle_mutex);

while(!mutex_take(vehicle_mutex)) {}
can_send(front_motorL_ID, torque[0]);
can_send(frontR_motor_ID, torque[1]);
can_send(rearL_motor_ID, torque[2]);
can_send(rearR_motor_ID, torue[3]);

mutex_give(vehicle_mutex);
}
}

void display_thread(void) {
for(;;) {
delay(DISPLAY_DELAY);

while(!mutex_take(vehicle_mutex)) {}

lcd_printf(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very small thing but lcd_printf should take a format string as the first parameter, something that looks like "Current: %f, FL Wheelspeed: %f, FR Wheelspeed: %f" etc.

vehicle_data.current, vehicle_data.wheelspeeds[0],
vehicle_data.wheelspeeds[1], vehicle_data.wheelspeeds[2],
vehicle_data.wheelspeeds[3], vehicle_data.torque[0],
vehicle_data.torque[1], vehicle_data.torque[2], vehicle_data.torque[3]
);

mutex_give(vehicle_mutex);
}
}

void safety_thread(void) {
for(;;) {
delay(SAFETY_DELAY);

double v_min = 5.0;
double v_max = 0.0;
double t_max = 0.0;
double v = 0;
double t = 0;

for(int i = 0; i < num_cells; i++) {
v = bms_get_voltage(i);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bms shares a SPI bus with the LCD, so this isn't safe

t = bms_get_temperature(i);

if(v < v_min) {
v = v_min;
}
if(v > v_max) {
v = v_max;
}
if(t > t_max) {
t = t_max;
}
}

if(v < 2.8 || v > 4.3 || t > 60.0) {
mcu_shutdown(); // Shutdown the car
}
}
}

void setup(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to actually spawn threads and start the scheduler in order for it to run. Right now your code will run whats in setup, then since the scheduler never starts, it'll go into loop where it does nothing forever

// Configure pins
pinMode(TS_ON, INPUT);
pinMode(RTD, INPUT);

pinMode(AIR_PLUS, OUTPUT);
pinMode(AIR_MINUS, OUTPUT);
pinMode(PRECHARGE, OUTPUT);

// Initialize peripherals
can_init(CAN_RX, CAN_TX, CAN_BAUDRATE);
lcd_init(MOSI, MISO, SCK, LCD_CS);
bms_init(MOSI, MISO, SCK, LCS_CS);

data_mutex = mutex_t();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant to call mutex_create

spi_mutex = mutex_t();
}

void loop(void) {}