From 93c3efc1ec25544e94a01c0dac96aedaa36667d1 Mon Sep 17 00:00:00 2001 From: Ollie Walsh Date: Fri, 14 Apr 2023 13:54:03 +0100 Subject: [PATCH 1/3] Improve ADC accuracy Use the charge voltage ADC when mowing to determine ADC offset. --- Firmware/LowLevel/src/main.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Firmware/LowLevel/src/main.cpp b/Firmware/LowLevel/src/main.cpp index e5b526ca..43f9016a 100644 --- a/Firmware/LowLevel/src/main.cpp +++ b/Firmware/LowLevel/src/main.cpp @@ -62,6 +62,10 @@ SerialPIO uiSerial(PIN_UI_TX, PIN_UI_RX, 250); #define R_SHUNT 0.003f #define CURRENT_SENSE_GAIN 100.0f +int next_adc_offset_sample = 0; +float adc_offset_samples[20] = {0}; +float adc_offset = 0.0f; + #define BATT_ABS_MAX 28.7f #define BATT_ABS_Min 21.7f @@ -677,15 +681,28 @@ void loop() { updateNeopixel(); status_message.v_battery = - (float) analogRead(PIN_ANALOG_BATTERY_VOLTAGE) * (3.3f / 4096.0f) * ((VIN_R1 + VIN_R2) / VIN_R2); - status_message.v_charge = - (float) analogRead(PIN_ANALOG_CHARGE_VOLTAGE) * (3.3f / 4096.0f) * ((VIN_R1 + VIN_R2) / VIN_R2); + ((float)analogRead(PIN_ANALOG_BATTERY_VOLTAGE) - adc_offset) * (3.33f / 4096.0f) * ((VIN_R1 + VIN_R2) / VIN_R2); #ifndef IGNORE_CHARGING_CURRENT status_message.charging_current = - (float) analogRead(PIN_ANALOG_CHARGE_CURRENT) * (3.3f / 4096.0f) / (CURRENT_SENSE_GAIN * R_SHUNT); + ((float)analogRead(PIN_ANALOG_CHARGE_CURRENT) - adc_offset) * (3.33f / 4096.0f) / (CURRENT_SENSE_GAIN * R_SHUNT); #else status_message.charging_current = -1.0f; #endif + status_message.v_charge = ((float)analogRead(PIN_ANALOG_CHARGE_VOLTAGE) - adc_offset) * (3.33f / 4096.0f) * ((VIN_R1 + VIN_R2) / VIN_R2); + + + // If mowing use charge current ADC to determine adc offset + if( last_high_level_state.current_mode == HighLevelMode::MODE_AUTONOMOUS && last_high_level_state.gps_quality != 0 ) { + adc_offset_samples[next_adc_offset_sample++] = (float)analogRead(PIN_ANALOG_CHARGE_VOLTAGE); + next_adc_offset_sample %= 20; + + float tmp = 0.0f; + for(int i=0; i<20; i++) { + tmp += adc_offset_samples[i]; + } + adc_offset = tmp / 20.0f; + } + status_message.status_bitmask = (status_message.status_bitmask & 0b11111011) | ((charging_allowed & 0b1) << 2); status_message.status_bitmask = (status_message.status_bitmask & 0b11011111) | ((sound_available & 0b1) << 5); From 6d6980dc2b8f940f40094cf89d7baf23bba4dc65 Mon Sep 17 00:00:00 2001 From: Ollie Walsh Date: Tue, 23 Apr 2024 02:33:30 +0100 Subject: [PATCH 2/3] Limit adc_offset to 3% --- Firmware/LowLevel/src/main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Firmware/LowLevel/src/main.cpp b/Firmware/LowLevel/src/main.cpp index 43f9016a..39e356ba 100644 --- a/Firmware/LowLevel/src/main.cpp +++ b/Firmware/LowLevel/src/main.cpp @@ -65,6 +65,8 @@ SerialPIO uiSerial(PIN_UI_TX, PIN_UI_RX, 250); int next_adc_offset_sample = 0; float adc_offset_samples[20] = {0}; float adc_offset = 0.0f; +// Limit adc_offset to 3% +#define MAX_ADC_OFFSET_PC 0.03f #define BATT_ABS_MAX 28.7f #define BATT_ABS_Min 21.7f @@ -700,7 +702,13 @@ void loop() { for(int i=0; i<20; i++) { tmp += adc_offset_samples[i]; } - adc_offset = tmp / 20.0f; + float new_adc_offset = tmp / 20.0f; + // Limit maximum offset + if(new_adc_offset > 0.0f) { + adc_offset = min(new_adc_offset, (4096 * MAX_ADC_OFFSET_PC)); + } else { + adc_offset = max(new_adc_offset, -(4096 * MAX_ADC_OFFSET_PC)); + } } status_message.status_bitmask = (status_message.status_bitmask & 0b11111011) | ((charging_allowed & 0b1) << 2); From 1c470ab6a06ab02bb2c06b7efe40cf2ba5d374ee Mon Sep 17 00:00:00 2001 From: Ollie Walsh Date: Tue, 23 Apr 2024 09:12:36 +0100 Subject: [PATCH 3/3] Do not adjust adc_offset if ROS is not running --- Firmware/LowLevel/src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Firmware/LowLevel/src/main.cpp b/Firmware/LowLevel/src/main.cpp index 39e356ba..177bdab8 100644 --- a/Firmware/LowLevel/src/main.cpp +++ b/Firmware/LowLevel/src/main.cpp @@ -694,7 +694,11 @@ void loop() { // If mowing use charge current ADC to determine adc offset - if( last_high_level_state.current_mode == HighLevelMode::MODE_AUTONOMOUS && last_high_level_state.gps_quality != 0 ) { + if( + ROS_running && + last_high_level_state.current_mode == HighLevelMode::MODE_AUTONOMOUS && + last_high_level_state.gps_quality != 0 + ) { adc_offset_samples[next_adc_offset_sample++] = (float)analogRead(PIN_ANALOG_CHARGE_VOLTAGE); next_adc_offset_sample %= 20;