From ad679bb9dfe57f8ed29a645e020e0e18de66e443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Grennerat?= Date: Tue, 16 Sep 2025 22:06:43 +0200 Subject: [PATCH] UART data fetching integrated --- Core/Inc/dashboard.h | 5 +- Core/Inc/float16.h | 10 ++ Core/Inc/usart.h | 1 - Core/Src/dashboard.c | 254 ++++++++++++++++++++++++++++++------------- Core/Src/float16.c | 36 ++++++ Core/Src/usart.c | 15 ++- 6 files changed, 234 insertions(+), 87 deletions(-) create mode 100644 Core/Inc/float16.h create mode 100644 Core/Src/float16.c diff --git a/Core/Inc/dashboard.h b/Core/Inc/dashboard.h index 5a58aef..3ac4864 100644 --- a/Core/Inc/dashboard.h +++ b/Core/Inc/dashboard.h @@ -15,7 +15,6 @@ void run_dashboard_loop(); void init(); -void update_values(); void update_values_setup(); void update_adc(); @@ -46,8 +45,8 @@ void draw_speed(int32_t speed); void draw_power(int32_t amps, int16_t duty, int16_t voltage); // Displays the two ADS voltages -// 2 voltages from COMM_GET_DECODED_ADC, scale 1 000 000 -void draw_adc(int32_t adc1, int32_t adc2); +// 2 voltages from reFloat - COMM_CUSTOM_APP_DATA, scale 10, adcx_en are booleans. +void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled, uint8_t adc1_en, uint8_t adc2_en); // Displays the controller and motor temperatures // 2 temperatures from COMM_GET_VALUES_SETUP, scale 10 diff --git a/Core/Inc/float16.h b/Core/Inc/float16.h new file mode 100644 index 0000000..448363d --- /dev/null +++ b/Core/Inc/float16.h @@ -0,0 +1,10 @@ +#ifndef FLOAT16_H +#define FLOAT16_H + +// Helper function to convert float16 to float (from StackOverflow) +float float16_to_float(uint16_t float16_val); + +// Convert Refloat float16 to int16_t (scaled by 10) +int16_t refloat_float16_to_int16_scaled(uint16_t float16_val); + +#endif diff --git a/Core/Inc/usart.h b/Core/Inc/usart.h index 27bf69e..235e1b4 100644 --- a/Core/Inc/usart.h +++ b/Core/Inc/usart.h @@ -6,7 +6,6 @@ void USART1_SendPacket(const uint8_t *data, uint8_t length); uint8_t USART1_ReceiveByte(void); -uint8_t USART1_ReceiveByteTimeout(uint32_t timeout); void USART1_Flush(void); diff --git a/Core/Src/dashboard.c b/Core/Src/dashboard.c index 4acffb2..7097130 100644 --- a/Core/Src/dashboard.c +++ b/Core/Src/dashboard.c @@ -7,25 +7,39 @@ #include "monomaniacone72pt.h" #include "usart.h" #include "crc.h" +#include "float16.h" #include +uint8_t initialized = 0; void run_dashboard_loop() { - init(); + LCD_Init(); + LCD_Fill_Screen(COLOR_OFF, 1); + LCD_Fill_Screen(COLOR_BG, 0); + HAL_Delay(1000); + while (1) { + update_values_setup(); + update_adc(); + HAL_Delay(100); + } + +} + +void run_dashboard_loop_test() { + LCD_Init(); + LCD_Fill_Screen(COLOR_OFF, 1); + LCD_Fill_Screen(COLOR_BG, 0); + draw_init(); uint32_t i = 0; while (1) { - if (i % 10 == 0) { - update_values(); - } - draw_battery(654, i * 100 / 4, 1321, 343); draw_speed(i * 1000 / 4); int16_t duty = 1000 - (int16_t) i * 1000 / 200; draw_power_bars(duty); draw_power(100 * i / 20 * (duty < 0 ? -1 : 1), duty, 60 * 10); - draw_adc((i % 34) * 100000, ((400 - i + 16) % 34) * 100000); + draw_adc(i % 34, (400 - i + 16) % 34, i % 34 >= 2.5, (400 - i + 16) % 34 >= 2.5); draw_temps((4 * i) % 900, ((10 * i) + 450) % 900); @@ -39,66 +53,155 @@ void run_dashboard_loop() { } -void init() { - LCD_Init(); - draw_init(); -} - -void update_values() { -// UART send 0201 04 4084 03 - +void update_values_setup() { +// UART send 0201 2F D58D 03 uint8_t packet[1]; - packet[0] = 0x04;// PAYLOAD (COMM_GET_VALUES) + packet[0] = 0x2F;// COMM_GET_VALUES_SETUP USART1_SendPacket(packet, 1); -// Wait for start byte (0x02) - while (USART1_ReceiveByte() != 0x02) { - } - ; // Read length (big-endian) - uint16_t len = USART1_ReceiveUInt16() & 0xFF; -// Read packet - uint8_t data[len]; - for (uint16_t i = 0; i < len - 2; i++) { - data[i] = USART1_ReceiveByte(); + uint8_t len = USART1_ReceiveUInt16() & 0xFF; + if (len != 0x46) { + HAL_Delay(500); + USART1_Flush(); + return;// Timed out } - uint16_t crc = USART1_ReceiveUInt16(); +// Read packet + USART1_ReceiveByte();// Packet id + int16_t temp_fet = USART1_ReceiveInt16(); + int16_t temp_motor = USART1_ReceiveInt16(); + USART1_ReceiveInt32();// Current tot + int32_t current_in_tot = USART1_ReceiveInt32(); + int16_t duty_cycle = USART1_ReceiveInt16(); + USART1_ReceiveInt32();// rpm + int32_t speed = USART1_ReceiveInt32(); + int16_t input_voltage_filtered = USART1_ReceiveInt16(); + int16_t battery_level = USART1_ReceiveInt16(); + USART1_ReceiveInt32();// ah tot + USART1_ReceiveInt32();// ah charge tot + USART1_ReceiveInt32();// wh tot + USART1_ReceiveInt32();// wh charge tot + USART1_ReceiveInt32();// distance + int32_t distance_abs = USART1_ReceiveInt32(); + USART1_ReceiveInt32();// pid pos now + uint8_t fault_code = USART1_ReceiveByte(); + USART1_ReceiveByte();// Controller Id + USART1_ReceiveByte();// Num VESCs + USART1_ReceiveInt32();// wh battery left + uint32_t distance_life = USART1_ReceiveUInt32(); + USART1_ReceiveUInt32();// System time + + USART1_ReceiveUInt16(); // CRC // End byte if (USART1_ReceiveByte() != 0x03) { return;// Invalid packet } // CRC check - if (crc != crc16(data, len)) { - return; +// if (crc != crc16(data, len)) { +// return; +// } + if (!initialized) { + draw_init(); + initialized = 1; } - __NOP(); -} -void update_values_setup() { -// UART send 0201 2F D58D 03 + draw_battery(input_voltage_filtered, battery_level, distance_abs, + distance_life); + draw_power_bars(duty_cycle); + draw_speed(speed * 10); + draw_power(current_in_tot, duty_cycle, input_voltage_filtered); + draw_temps(temp_fet, temp_motor); } void update_adc() { -// UART send 0201 20 2462 03 -} +// Replies to 0x24 0x65 for command id: 0, 1, 18, 19, 1B, 1D, C9, CA +// 0 1 24 25 27 29 201 202 -void LCD_DrawHollowRoundRect( - uint16_t x, - uint16_t y, - uint16_t w, - uint16_t h, - uint8_t radius_top, - uint8_t radius_bottom, - uint8_t border_width, - uint16_t color, - uint16_t fill_color, - uint8_t do_fill); + uint8_t packet[3]; + packet[0] = 0x24;// COMM_CUSTOM_APP_DATA + packet[1] = 0x65;// reFloat package interface + packet[2] = 0x01;// command id + USART1_SendPacket(packet, 3); + + uint8_t len = USART1_ReceiveUInt16() & 0xFF; + if (len == 0xFF) {// len is usually 0x3A = 58, but may be shorter. + HAL_Delay(500); + USART1_Flush(); + return;// Timed out + } + +// Read packet + USART1_ReceiveByte();// packet id + USART1_ReceiveByte();// reFloat package interface + USART1_ReceiveByte();// command id + USART1_ReceiveInt32();// Balance current + USART1_ReceiveInt32();// IMU Pitch + USART1_ReceiveInt32();// IMU Roll + USART1_ReceiveByte();// State + uint8_t beep_fs_state = USART1_ReceiveByte();// Beep reason + footpad sensors state + uint32_t adc1_f32 = USART1_ReceiveUInt32(); + uint32_t adc2_f32 = USART1_ReceiveUInt32(); + +// Results if command id 31 (0x1F) was working: +// uint8_t mask = USART1_ReceiveByte();// mask // 0x00 +// uint8_t extra_flags = USART1_ReceiveByte();// extra flags // 0x02 +// uint32_t time = USART1_ReceiveInt32();// time // 0x00 10 00 41 +// uint8_t state_and_time = USART1_ReceiveByte();// state_and_mode // 0x9B +// uint8_t flags_and_footpad = USART1_ReceiveByte();// flags_and_footpad // 0x8A +// uint8_t stop_cond_and_sat = USART1_ReceiveByte();// stop_cond_and_sat // 0x29 +// uint8_t alert_reason = USART1_ReceiveByte();// alert_reason // 0x41 +// +// USART1_ReceiveInt16();//motor.speed +// USART1_ReceiveInt16();//motor.erpm +// USART1_ReceiveInt16();//motor.current +// USART1_ReceiveInt16();//motor.dir_current +// USART1_ReceiveInt16();//motor.filt_current +// USART1_ReceiveInt16();//motor.duty_cycle +// USART1_ReceiveInt16();//motor.batt_voltage +// USART1_ReceiveInt16();//motor.batt_current +// USART1_ReceiveInt16();//motor.mosfet_temp +// USART1_ReceiveInt16();//motor.motor_temp +// USART1_ReceiveInt16();//imu.pitch +// USART1_ReceiveInt16();//imu.balance_pitch +// USART1_ReceiveInt16();//imu.roll +// uint16_t adc1_f16 = USART1_ReceiveUInt16();//footpad.adc1 +// uint16_t adc2_f16 = USART1_ReceiveUInt16();//footpad.adc2 +// USART1_ReceiveInt16();//remote.input +//// May have other ignored values. +// int16_t adc1 = refloat_float16_to_int16_scaled(adc1_f16); +// int16_t adc2 = refloat_float16_to_int16_scaled(adc2_f16); + + if (!initialized) { + draw_init(); + initialized = 1; + } + float adc1 = *((float*) &adc1_f32); + float adc2 = *((float*) &adc2_f32); + + uint8_t fs_state = beep_fs_state & 0b11; + uint8_t adc1_en = 0; + uint8_t adc2_en = 0; + if(fs_state == 1) { + if (adc1 > adc2){ + adc1_en = 1; + } else { + adc2_en = 2; + } + }else if(fs_state == 2) { + adc1_en = 1; + adc2_en = 1; + } + + draw_adc((int32_t) 10 * adc1, (int32_t) 10 * adc2, adc1_en, adc2_en); + +// Make sure other values are discarded + HAL_Delay(100); + USART1_Flush(); +} #define LEFT_CENTER_COL1 38 #define LEFT_CENTER_COL2 116 #define RIGHT_CENTER 400 void draw_init() { - LCD_Fill_Screen(COLOR_OFF, 1); - LCD_Fill_Screen(COLOR_BG, 0); // Draw footpad sensors rect uint16_t sensor_width = 126; @@ -142,10 +245,10 @@ void draw_init() { } // Displays the battery voltage and percent, with the trip and life distances -// Input voltage from COMM_GET_VALUES, scale 10 -// battery percent (level) from COMM_GET_VALUES_SETUP, scale 100 -// trip distance from COMM_GET_VALUES_SETUP, scale 100 -// life distance (odometer) from COMM_GET_VALUES_SETUP +// Input voltage from COMM_GET_VALUES_SETUP, scale 10 +// battery percent (level) from COMM_GET_VALUES_SETUP, scale 10 +// trip distance from COMM_GET_VALUES_SETUP, scale 1000, in m +// life distance (odometer) from COMM_GET_VALUES_SETUP, in m int16_t last_voltage = 0; int32_t last_percent = 0; int32_t last_trip_dist = 0; @@ -155,17 +258,17 @@ void draw_battery( int32_t trip_dist, uint32_t life_dist) { - if (voltage == last_voltage && percent / 100 == last_percent / 100 - && trip_dist / 10 == last_trip_dist / 10) { + if (voltage == last_voltage && percent / 10 == last_percent + && trip_dist / 100000 == last_trip_dist) { return; } last_voltage = voltage; - last_percent = percent; - last_trip_dist = trip_dist; + last_percent = percent / 10; + last_trip_dist = trip_dist / 100000; uint16_t bar_width = LCD_WIDTH - 12; uint16_t bar_height = 22; - uint16_t filled_bar_width = (((float) (percent / 100)) / 100.0) * bar_width; + uint16_t filled_bar_width = (((float) (percent / 10)) / 100.0) * bar_width; if (filled_bar_width < 6) { filled_bar_width = 6;// Must be at least the size of the border radius. } @@ -176,10 +279,10 @@ void draw_battery( char voltage_text[8]; sprintf(voltage_text, "%.1fV", ((float) voltage) / 10.0); char percent_text[6]; - sprintf(percent_text, "%lu%%", percent / 100); + sprintf(percent_text, "%lu%%", percent / 10); char distances_text[20]; - sprintf(distances_text, "%.1fKm / %luKm", ((float) trip_dist) / 100.0, - life_dist); + sprintf(distances_text, "%.1fKm / %luKm", + ((float) (trip_dist / 100000)) / 10.0, life_dist / 1000); // Drawing the bars LCD_DrawHollowRoundRect(4, LCD_HEIGHT - (bar_height + 4) - 4, bar_width + 4, @@ -193,7 +296,7 @@ void draw_battery( uint16_t left_x = 10; uint16_t right_x = LCD_WIDTH - 10; - if (percent > 20 * 100) { + if (percent > 20 * 10) { // Drawing the voltage to the left left_x = 10 + GFX_DrawText(left_x, text_y_14, voltage_text, &monomaniacone14pt, @@ -205,7 +308,7 @@ void draw_battery( COLOR_FG, COLOR_BG, 2, -2); } - if (percent > 50 * 100) { + if (percent > 50 * 10) { // Drawing the distances on the left GFX_DrawText(left_x, text_y_14, distances_text, &monomaniacone14pt, COLOR_BG, COLOR_SUCCESS, 0, -3); @@ -215,7 +318,7 @@ void draw_battery( COLOR_FG, COLOR_BG, 2, -3); } - if (percent > 80 * 100) { + if (percent > 80 * 10) { // Drawing the distances on the left GFX_DrawText(filled_bar_end_x - 4, text_y_14, percent_text, &monomaniacone14pt, @@ -386,14 +489,13 @@ void draw_power(int32_t current_i, int16_t duty_i, int16_t voltage_i) { uint16_t last_adc1 = 1000; uint16_t last_adc2 = 1000; -uint16_t adc_threshold = 29; -// Displays the two ADS voltages -// 2 voltages from COMM_GET_DECODED_ADC, scale 1 000 000 -void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) { - uint16_t adc1 = - adc1_scaled < 0 ? -adc1_scaled / 100000 : adc1_scaled / 100000; - uint16_t adc2 = - adc2_scaled < 0 ? -adc2_scaled / 100000 : adc2_scaled / 100000; +uint8_t last_adc1_en = 0; +uint8_t last_adc2_en = 0; +// Displays the two ADC voltages +// 2 voltages from reFloat - COMM_CUSTOM_APP_DATA, scale 10, adcx_en are booleans. +void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled, uint8_t adc1_en, uint8_t adc2_en) { + uint16_t adc1 = adc1_scaled < 0 ? -adc1_scaled : adc1_scaled; + uint16_t adc2 = adc2_scaled < 0 ? -adc2_scaled : adc2_scaled; if (adc1 > 33) { adc1 = 33; } @@ -401,7 +503,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) { adc2 = 33; } // Max filled height = 39 - if (adc1 != last_adc1) { + if (adc1 != last_adc1 || adc1_en != last_adc1_en) { uint16_t filled_height = adc1 * 39 / 33; uint16_t free_height = 61 - filled_height; @@ -411,7 +513,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) { COLOR_BG); // Draw the colored zone - uint16_t color = adc1 >= adc_threshold ? COLOR_SUCCESS : COLOR_ERROR; + uint16_t color = adc1_en ? COLOR_SUCCESS : COLOR_ERROR; LCD_Draw_Rectangle(RIGHT_CENTER - 3 - 54, 76 + free_height, 54, filled_height, color); @@ -422,9 +524,10 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) { &monomaniacone14pt, color, COLOR_BG, 1, -2); last_adc1 = adc1; + last_adc1_en = adc1_en; } // Max filled height = 39 - if (adc2 != last_adc2) { + if (adc2 != last_adc2 || adc2_en != last_adc2_en) { uint16_t filled_height = adc2 * 39 / 33; uint16_t free_height = 61 - filled_height; @@ -434,7 +537,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) { COLOR_BG); // Draw the colored zone - uint16_t color = adc2 >= adc_threshold ? COLOR_SUCCESS : COLOR_ERROR; + uint16_t color = adc2_en ? COLOR_SUCCESS : COLOR_ERROR; LCD_Draw_Rectangle(RIGHT_CENTER + 3, 76 + free_height, 54, filled_height, color); @@ -445,6 +548,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) { &monomaniacone14pt, color, COLOR_BG, 1, -2); last_adc2 = adc2; + last_adc2_en = adc2_en; } } @@ -470,7 +574,7 @@ void draw_temps(int16_t temp_fet_scaled, int16_t temp_motor_scaled) { sprintf(text, "%u>C", temp_mot); LCD_Draw_Rectangle(LEFT_CENTER_COL1 - 38, 138, 2 * 39, 25, COLOR_BG); GFX_DrawText(LEFT_CENTER_COL1, 159, text, &monomaniacone14pt, - COLOR_SECONDARY, COLOR_BG, 1, -1); + COLOR_SECONDARY, COLOR_BG, 1, -1); } if (temp_fet != last_temp_fet) { last_temp_fet = temp_fet; @@ -479,6 +583,6 @@ void draw_temps(int16_t temp_fet_scaled, int16_t temp_motor_scaled) { sprintf(text, "%u>C", temp_fet); LCD_Draw_Rectangle(LEFT_CENTER_COL2 - 39, 138, 2 * 39, 25, COLOR_BG); GFX_DrawText(LEFT_CENTER_COL2, 159, text, &monomaniacone14pt, COLOR_PRIMARY, - COLOR_BG, 1, -1); + COLOR_BG, 1, -1); } } diff --git a/Core/Src/float16.c b/Core/Src/float16.c new file mode 100644 index 0000000..51532ec --- /dev/null +++ b/Core/Src/float16.c @@ -0,0 +1,36 @@ +#include +#include +#include + +// Helper function to convert float16 to float (from StackOverflow) +float float16_to_float(uint16_t float16_val) { + // Implement the IEEE-754 FP16 decoding logic here. + // See: https://stackoverflow.com/a/60047308 + // Example placeholder (replace with actual implementation): + uint32_t sign = (float16_val & 0x8000) << 16; + uint32_t exponent = (float16_val & 0x7C00) >> 10; + uint32_t mantissa = float16_val & 0x03FF; + + if (exponent == 0) { + // Subnormal or zero + return (sign ? -1.0f : 1.0f) * powf(2.0f, -14.0f) * (mantissa / 1024.0f); + } else if (exponent == 0x1F) { + // Infinity or NaN (not supported in Refloat, per docs) + return sign ? -INFINITY : INFINITY; + } else { + // Normalized number + return (sign ? -1.0f : 1.0f) * powf(2.0f, exponent - 15.0f) * (1.0f + mantissa / 1024.0f); + } +} + +// Convert Refloat float16 to int16_t (scaled by 10) +int16_t refloat_float16_to_int16_scaled(uint16_t float16_val) { + float float_val = float16_to_float(float16_val); + float scaled_val = float_val * 10.0f; + + // Clamp to int16_t range to avoid overflow + if (scaled_val > 32767.0f) return 32767; + if (scaled_val < -32768.0f) return -32768; + + return (int16_t)scaled_val; +} diff --git a/Core/Src/usart.c b/Core/Src/usart.c index 6ce0806..ae8c976 100644 --- a/Core/Src/usart.c +++ b/Core/Src/usart.c @@ -13,15 +13,15 @@ void USART1_SendByte(uint8_t byte) { } // USART1 Receive Byte (blocking) -uint8_t USART1_ReceiveByte(void) { - while (!(USART1->SR & USART_SR_RXNE)); // Wait until data received - return USART1->DR; // Return received byte -} +//uint8_t USART1_ReceiveByte(void) { +// while (!(USART1->SR & USART_SR_RXNE)); // Wait until data received +// return USART1->DR; // Return received byte +//} // Receive byte with timeout (returns 0xFF if timeout) -uint8_t USART1_ReceiveByteTimeout(uint32_t timeout) { +uint8_t USART1_ReceiveByte() { uint32_t start = HAL_GetTick(); while (!(USART1->SR & USART_SR_RXNE)) { - if (HAL_GetTick() - start > timeout) { + if (HAL_GetTick() - start > 300) { // 300ms timeout return 0xFF; // Timeout } } @@ -35,12 +35,11 @@ void USART1_Flush(void) { } void USART1_SendPacket(const uint8_t *data, uint8_t length) { - + USART1_Flush(); uint16_t crc = crc16(data, length); uint8_t crc_h = (crc >> 8) & 0xFF; // CRC high byte (big-endian) uint8_t crc_l = crc & 0xFF; // CRC low byte - USART1_SendByte(0x02); // Start byte USART1_SendByte(0x02); // length type < 256 USART1_SendByte(length); for (uint16_t i = 0; i < length; i++) {