diff options
| author | Selene ToyKeeper | 2020-02-05 23:34:44 -0700 |
|---|---|---|
| committer | Selene ToyKeeper | 2020-02-05 23:34:44 -0700 |
| commit | 14ad6787546b3a2c55c129c8bd95eb6b98f14531 (patch) | |
| tree | 14ccb220c71b00e3463a0337de8f83da72e7898b | |
| parent | still doesn't work, but at least it's a bit less broken than before... (diff) | |
| download | anduril-14ad6787546b3a2c55c129c8bd95eb6b98f14531.tar.gz anduril-14ad6787546b3a2c55c129c8bd95eb6b98f14531.tar.bz2 anduril-14ad6787546b3a2c55c129c8bd95eb6b98f14531.zip | |
brute force method for reducing ADC noise -- average a ridiculous number of samples
(because, for some reason, even though 64 samples is plenty in a test program,
it ends up being extremely erratic when used inside Anduril... and I'm not sure why)
also, use 15-bit ADC values instead of 16 bits, in the temperature logic
(to help protect against integer overflows)
... but this code still doesn't work well. It regulates down *very* fast, and then
gradually rises until the next extra-fast drop-down. :(
... also, tempcheck mode sometimes changes by 4-5 C between readouts, which is worrisome.
... and factory reset is still broken.
| -rw-r--r-- | spaghetti-monster/fsm-adc.c | 32 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-adc.h | 2 |
2 files changed, 14 insertions, 20 deletions
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 2df884e..65669b3 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -135,7 +135,7 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { // doing 32-bit math) ISR(ADC_vect) { - static uint16_t adc_sum; + static uint32_t adc_sum; // keep this moving along adc_sample_count ++; @@ -146,16 +146,10 @@ ISR(ADC_vect) { adc_sum = 0; return; } - // 64 samples collected, save the result - // (actually triggers at 64 and every 32 afterward) - else if (66 == adc_sample_count) { + // 2048 samples collected, save the result + else if (2050 == adc_sample_count) { // save the latest result - adc_smooth[adc_channel] = adc_sum; - // cut sum in half and set up another half-window of samples - // (for sort of a continuous average) - // (this seems to significantly reduce noise) - adc_sum >>= 1; - adc_sample_count = 33; + adc_smooth[adc_channel] = adc_sum >> 5; } // add the latest measurement to the pile else { @@ -275,7 +269,7 @@ static inline void ADC_voltage_handler() { static inline void ADC_temperature_handler() { // coarse adjustment #ifndef THERM_LOOKAHEAD - #define THERM_LOOKAHEAD 3 // can be tweaked per build target + #define THERM_LOOKAHEAD 4 // can be tweaked per build target #endif // fine-grained adjustment // how proportional should the adjustments be? (not used yet) @@ -297,13 +291,13 @@ static inline void ADC_temperature_handler() { if (! reset_thermal_history) { // average of recent samples - measurement = adc_smooth[1]; + measurement = adc_smooth[1] >> 1; } else { // wipe out old data // don't keep resetting reset_thermal_history = 0; // ignore average, use latest sample - measurement = adc_raw[1] << 6; + measurement = adc_raw[1] << 5; // forget any past measurements for(uint8_t i=0; i<NUM_TEMP_HISTORY_STEPS; i++) @@ -312,7 +306,7 @@ static inline void ADC_temperature_handler() { // let the UI see the current temperature in C // Convert ADC units to Celsius (ish) - temperature = (measurement>>6) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + temperature = (measurement>>5) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; // how much has the temperature changed between now and a few seconds ago? int16_t diff; @@ -335,7 +329,7 @@ static inline void ADC_temperature_handler() { // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset; // ... so ... // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC; - uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 6; + uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 5; //uint16_t floor = ceil - (THERM_WINDOW_SIZE << 6); int16_t offset_pt, offset_avg; offset_pt = (pt - ceil) >> 1; @@ -350,7 +344,7 @@ static inline void ADC_temperature_handler() { // Too hot? // (if it's too hot and not getting colder...) - if ((offset > 0) && (diff > (-1 << 5))) { + if ((offset > 0) && (diff > (-1 << 4))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? @@ -362,13 +356,13 @@ static inline void ADC_temperature_handler() { // Too cold? // (if it's too cold and not getting warmer...) - else if ((offset < -(THERM_WINDOW_SIZE << 6)) - && (diff < (1 << 4))) { + else if ((offset < -(THERM_WINDOW_SIZE << 5)) + && (diff < (1 << 3))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; - int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<6)) >> 9; + int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<5)) >> 8; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) if (voltage > VOLTAGE_LOW) diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 6283b2c..7acb505 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -40,7 +40,7 @@ #endif volatile uint8_t irq_adc = 0; // ADC interrupt happened? -uint8_t adc_sample_count = 0; // skip the first sample; it's junk +uint16_t adc_sample_count = 0; // skip the first sample; it's junk uint8_t adc_channel = 0; // 0=voltage, 1=temperature uint16_t adc_raw[2]; // last ADC measurements (0=voltage, 1=temperature) uint16_t adc_smooth[2]; // lowpassed ADC measurements (0=voltage, 1=temperature) |
