From 73a5a6974a98aa73ab392272b4d69d285c85dee5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 19 Aug 2017 17:20:46 -0600 Subject: Completely reorganized SpaghettiMonster code into smaller logical pieces: fsm-*.c and fsm-*.h. --- spaghetti-monster/fsm-adc.c | 136 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 spaghetti-monster/fsm-adc.c (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c new file mode 100644 index 0000000..11468b9 --- /dev/null +++ b/spaghetti-monster/fsm-adc.c @@ -0,0 +1,136 @@ +/* + * fsm-adc.c: ADC (voltage, temperature) functions for SpaghettiMonster. + * + * Copyright (C) 2017 Selene ToyKeeper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FSM_ADC_C +#define FSM_ADC_C + +inline void ADC_on() +{ + // read voltage on VCC by default + // disable digital input on VCC pin to reduce power consumption + //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin + // VCC / 1.1V reference + ADMUX = ADMUX_VCC; + // enable, start, prescale + ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL; +} + +inline void ADC_off() { + ADCSRA &= ~(1<> 2; + + voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; + } + #else // no USE_LVP_AVG + // calculate actual voltage: volts * 10 + // ADC = 1.1 * 1024 / volts + // volts = 1.1 * 1024 / ADC + voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + #endif + // if low, callback EV_voltage_low / EV_voltage_critical + // (but only if it has been more than N ticks since last call) + if (lvp_timer) { + lvp_timer --; + } else { // it has been long enough since the last warning + if (voltage < VOLTAGE_LOW) { + if (lvp_lowpass < LVP_LOWPASS_STRENGTH) { + lvp_lowpass ++; + } else { + // try to send out a warning + //uint8_t err = emit(EV_voltage_low, 0); + //uint8_t err = emit_now(EV_voltage_low, 0); + emit(EV_voltage_low, 0); + //if (!err) { + // on successful warning, reset counters + lvp_timer = LVP_TIMER_START; + lvp_lowpass = 0; + //} + } + } else { + // voltage not low? reset count + lvp_lowpass = 0; + } + } + } + #endif // ifdef USE_LVP + + // TODO: temperature + + // start another measurement for next time + #ifdef USE_THERMAL_REGULATION + #ifdef USE_LVP + if (adc_step < 2) ADMUX = ADMUX_VCC; + else ADMUX = ADMUX_THERM; + #else + ADMUX = ADMUX_THERM; + #endif + #else + #ifdef USE_LVP + ADMUX = ADMUX_VCC; + #endif + #endif +} + +#endif -- cgit v1.2.3 From 5631564b329d0445fb282e5e387217ba4e4ff191 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 23 Aug 2017 19:22:22 -0600 Subject: Added thermal regulation to SpaghettiMonster / Baton. Made some LVP values configurable. Removed high_temperature() / low_temperature() shortcuts for now. --- spaghetti-monster/fsm-adc.c | 136 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 4 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 11468b9..8af3487 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -35,9 +35,18 @@ inline void ADC_off() { ADCSRA &= ~(1<> 2; + // More precise method: use noise as extra precision + // (values are now basically fixed-point, signed 13.2) + temperature = total; + } + + // guess what the temperature will be in a few seconds + { + uint8_t i; + int16_t diff; + + // algorithm tweaking; not really intended to be modified + // how far ahead should we predict? + #define THERM_PREDICTION_STRENGTH 4 + // how proportional should the adjustments be? + #define THERM_DIFF_ATTENUATION 4 + // acceptable temperature window size in C + #define THERM_WINDOW_SIZE 8 + // highest temperature allowed + // (convert configured value to 13.2 fixed-point) + #define THERM_CEIL (therm_ceil<<2) + // bottom of target temperature window (13.2 fixed-point) + #define THERM_FLOOR (THERM_CEIL - (THERM_WINDOW_SIZE<<2)) + + // rotate measurements and add a new one + for (i=0; i THERM_FLOOR) { + underheat_lowpass = 0; // we're definitely not too cold + } else if (projected_temperature < THERM_CEIL) { + overheat_lowpass = 0; // we're definitely not too hot + } + + if (temperature_timer) { + temperature_timer --; + } else { // it has been long enough since the last warning + + // Too hot? + if (projected_temperature > THERM_CEIL) { + if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { + overheat_lowpass ++; + } else { + // how far above the ceiling? + int16_t howmuch = (projected_temperature - THERM_CEIL) >> THERM_DIFF_ATTENUATION; + if (howmuch < 1) howmuch = 1; + // try to send out a warning + emit(EV_temperature_high, howmuch); + // reset counters + temperature_timer = TEMPERATURE_TIMER_START; + overheat_lowpass = 0; + } + } + + // Too cold? + else if (projected_temperature < THERM_FLOOR) { + if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { + underheat_lowpass ++; + } else { + // how far below the floor? + int16_t howmuch = (THERM_FLOOR - projected_temperature) >> THERM_DIFF_ATTENUATION; + if (howmuch < 1) howmuch = 1; + // try to send out a warning + emit(EV_temperature_low, howmuch); + // reset counters + temperature_timer = TEMPERATURE_TIMER_START; + underheat_lowpass = 0; + } + } + } + } + #endif // ifdef USE_THERMAL_REGULATION + // start another measurement for next time #ifdef USE_THERMAL_REGULATION -- cgit v1.2.3 From badf37072988156a4cee753b922306195ee45916 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 24 Aug 2017 02:09:33 -0600 Subject: Added a ramping UI example. Added ramping support in general. --- spaghetti-monster/fsm-adc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 8af3487..b3ae4e9 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -231,6 +231,8 @@ ISR(ADC_vect) { if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { underheat_lowpass ++; } else { + // FIXME: don't warn about underheating when voltage is low + // (LVP and underheat warnings fight each other) // how far below the floor? int16_t howmuch = (THERM_FLOOR - projected_temperature) >> THERM_DIFF_ATTENUATION; if (howmuch < 1) howmuch = 1; -- cgit v1.2.3 From 2249f9913058c534fba51fbc6285e49c67bce726 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 24 Aug 2017 03:03:55 -0600 Subject: Don't send underheat warnings when LVP is active. The signals conflict. Also, avoid immediate thermal step-down after battery change. (init array with correctly-scaled values) --- spaghetti-monster/fsm-adc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index b3ae4e9..9a6e2e7 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -148,7 +148,7 @@ ISR(ADC_vect) { for(uint8_t i=0; i> THERM_DIFF_ATTENUATION; if (howmuch < 1) howmuch = 1; - // try to send out a warning - emit(EV_temperature_low, howmuch); + // try to send out a warning (unless voltage is low) + // (LVP and underheat warnings fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_low, howmuch); // reset counters temperature_timer = TEMPERATURE_TIMER_START; underheat_lowpass = 0; -- cgit v1.2.3 From 39b30b41f92978a3e05a8de0a416279fb35b35b1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 25 Aug 2017 02:14:31 -0600 Subject: Added battcheck mode to ramping-ui. It's bigger than I had hoped. :( Added fsm-misc.*, which currently only has interruptible blink functions in it. (for blinking out numbers and such) --- spaghetti-monster/fsm-adc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 9a6e2e7..70e3bb3 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -263,4 +263,28 @@ ISR(ADC_vect) { #endif } +#ifdef USE_BATTCHECK +#ifdef BATTCHECK_4bars +PROGMEM const uint8_t voltage_blinks[] = { + 30, 35, 38, 40, 42, 99, +}; +#endif +#ifdef BATTCHECK_8bars +PROGMEM const uint8_t voltage_blinks[] = { + 30, 33, 35, 37, 38, 39 40, 41, 42, 99, +}; +#endif +void battcheck() { + #ifdef BATTCHECK_VpT + blink_num(voltage); + #else + uint8_t i; + for(i=0; + voltage >= pgm_read_byte(voltage_blinks + i); + i++) {} + blink_num(i); + #endif +} +#endif + #endif -- cgit v1.2.3 From 4052efbf6d7993c6b846105e870b1fcbcdb761e7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 25 Aug 2017 02:32:43 -0600 Subject: Made 4bar and 8bar battcheck styles work. Added LVP handling for other modes, including battcheck. --- spaghetti-monster/fsm-adc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 70e3bb3..622ef0f 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -271,7 +271,7 @@ PROGMEM const uint8_t voltage_blinks[] = { #endif #ifdef BATTCHECK_8bars PROGMEM const uint8_t voltage_blinks[] = { - 30, 33, 35, 37, 38, 39 40, 41, 42, 99, + 30, 33, 35, 37, 38, 39, 40, 41, 42, 99, }; #endif void battcheck() { @@ -282,7 +282,8 @@ void battcheck() { for(i=0; voltage >= pgm_read_byte(voltage_blinks + i); i++) {} - blink_num(i); + if (blink_digit(i)) + nice_delay_ms(1000); #endif } #endif -- cgit v1.2.3 From d32ae87d50e92cb59fdc28cf58622b32aede2f3e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 26 Aug 2017 13:52:52 -0600 Subject: Avoid suspending at weird times by deferring the call to standby mode. Turned strobe into a function to avoid repeating code, and made it tolerate interruption better. Got rid of delay after battcheck, since it caused problems if the user didn't wait long enough before trying to turn the light back on. --- spaghetti-monster/fsm-adc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 622ef0f..541f9a4 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -282,9 +282,13 @@ void battcheck() { for(i=0; voltage >= pgm_read_byte(voltage_blinks + i); i++) {} + #ifdef DONT_DELAY_AFTER_BATTCHECK + blink_digit(i); + #else if (blink_digit(i)) nice_delay_ms(1000); #endif + #endif } #endif -- cgit v1.2.3 From 0a801bff0f22be650aed6c3724c41cae03814d8f Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 31 Aug 2017 23:45:36 -0600 Subject: Started a Meteor M43 clone UI. So far, UI1 and battcheck both work. UI2 and UI3 and other blinkies aren't implement yet. Added 6-bar battcheck style to match Meteor (ish). Increased maximum number of clicks to 12, because WTF. If your UI needs 12 clicks, what are you even doing in life? --- spaghetti-monster/fsm-adc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 541f9a4..7f26fde 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -269,6 +269,11 @@ PROGMEM const uint8_t voltage_blinks[] = { 30, 35, 38, 40, 42, 99, }; #endif +#ifdef BATTCHECK_6bars +PROGMEM const uint8_t voltage_blinks[] = { + 30, 34, 36, 38, 40, 41, 43, 99, +}; +#endif #ifdef BATTCHECK_8bars PROGMEM const uint8_t voltage_blinks[] = { 30, 33, 35, 37, 38, 39, 40, 41, 42, 99, -- cgit v1.2.3 From fd3f600c7b17995ba6509802da71a3d2fd0fce6e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 9 Sep 2017 23:07:35 -0600 Subject: Reworked thermal regulation. Now actually works on turbo (was previously emitting "temp low" instead of "temp high" while in direct-drive, probably due to an overflow). Made stepdown work based on an average of the last few temperature predictions instead of just the most recent one. (reduced noise sensitivity) Made each temperature sample based on 8 measurements instead of 4, to reduce noise. Made standby mode re-init thermal measurement arrays, to avoid weird behavior next time light is used. Reduced fixed-point precision to avoid overflows. Reduced prediction strength to encourage stepping down faster while hot. (unfortunately also steps down later, I think, if it wasn't already hot) Not totally happy with new algorithm, but it's the least crappy of a whole bunch of things I tried. (for example, a PID approach with correction based mostly on I... didn't work very well) (taking an average of the last few predictions is very similar though, and works) (but the result is still kind of meh) Saving this so I'll have a functional base next time I try to improve it. --- spaghetti-monster/fsm-adc.c | 85 ++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 31 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 7f26fde..4efb11c 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -60,12 +60,14 @@ ISR(ADC_vect) { // thermal declarations #ifdef USE_THERMAL_REGULATION - #define NUM_THERMAL_VALUES 4 + #define NUM_THERMAL_VALUES 8 #define NUM_THERMAL_VALUES_HISTORY 16 + #define NUM_THERMAL_PROJECTED_HISTORY 8 #define ADC_STEPS 4 - static uint8_t first_temp_reading = 1; static int16_t temperature_values[NUM_THERMAL_VALUES]; // last few readings in C - static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; // 13.2 fixed-point + static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; // 14.1 fixed-point + static int16_t projected_temperature_history[NUM_THERMAL_PROJECTED_HISTORY]; // 14.1 fixed-point + static uint8_t projected_temperature_history_counter = 0; static uint8_t temperature_timer = 0; static uint8_t overheat_lowpass = 0; static uint8_t underheat_lowpass = 0; @@ -143,18 +145,21 @@ ISR(ADC_vect) { int16_t temp = measurement - 275 + THERM_CAL_OFFSET; // prime on first execution - if (first_temp_reading) { - first_temp_reading = 0; + if (reset_thermal_history) { + reset_thermal_history = 0; for(uint8_t i=0; i> 2; // More precise method: use noise as extra precision // (values are now basically fixed-point, signed 13.2) - temperature = total; + //temperature = total; + // 14.1 is less prone to overflows + temperature = total >> 2; } // guess what the temperature will be in a few seconds { uint8_t i; int16_t diff; + int16_t t = temperature; // algorithm tweaking; not really intended to be modified // how far ahead should we predict? - #define THERM_PREDICTION_STRENGTH 4 + #define THERM_PREDICTION_STRENGTH 3 // how proportional should the adjustments be? - #define THERM_DIFF_ATTENUATION 4 + #define THERM_DIFF_ATTENUATION 2 // acceptable temperature window size in C #define THERM_WINDOW_SIZE 8 // highest temperature allowed - // (convert configured value to 13.2 fixed-point) - #define THERM_CEIL (therm_ceil<<2) - // bottom of target temperature window (13.2 fixed-point) - #define THERM_FLOOR (THERM_CEIL - (THERM_WINDOW_SIZE<<2)) + // (convert configured value to 14.1 fixed-point) + #define THERM_CEIL (((int16_t)therm_ceil)<<1) + // bottom of target temperature window (14.1 fixed-point) + #define THERM_FLOOR (THERM_CEIL - (THERM_WINDOW_SIZE<<1)) // rotate measurements and add a new one for (i=0; i THERM_FLOOR) { + // average prediction to reduce noise + int16_t avg_projected_temperature = 0; + for (uint8_t i = 0; i < NUM_THERMAL_PROJECTED_HISTORY; i++) + avg_projected_temperature += projected_temperature_history[i]; + avg_projected_temperature /= NUM_THERMAL_PROJECTED_HISTORY; + + // cancel counters if appropriate + if (avg_projected_temperature > THERM_FLOOR) { underheat_lowpass = 0; // we're definitely not too cold - } else if (projected_temperature < THERM_CEIL) { + } else if (avg_projected_temperature < THERM_CEIL) { overheat_lowpass = 0; // we're definitely not too hot } @@ -211,15 +232,16 @@ ISR(ADC_vect) { } else { // it has been long enough since the last warning // Too hot? - if (projected_temperature > THERM_CEIL) { + if (avg_projected_temperature > THERM_CEIL) { if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { overheat_lowpass ++; } else { // how far above the ceiling? - int16_t howmuch = (projected_temperature - THERM_CEIL) >> THERM_DIFF_ATTENUATION; - if (howmuch < 1) howmuch = 1; - // try to send out a warning - emit(EV_temperature_high, howmuch); + int16_t howmuch = (avg_projected_temperature - THERM_CEIL) >> THERM_DIFF_ATTENUATION; + if (howmuch > 0) { + // try to send out a warning + emit(EV_temperature_high, howmuch); + } // reset counters temperature_timer = TEMPERATURE_TIMER_START; overheat_lowpass = 0; @@ -227,17 +249,18 @@ ISR(ADC_vect) { } // Too cold? - else if (projected_temperature < THERM_FLOOR) { + else if (avg_projected_temperature < THERM_FLOOR) { if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { underheat_lowpass ++; } else { // how far below the floor? - int16_t howmuch = (THERM_FLOOR - projected_temperature) >> THERM_DIFF_ATTENUATION; - if (howmuch < 1) howmuch = 1; - // try to send out a warning (unless voltage is low) - // (LVP and underheat warnings fight each other) - if (voltage > VOLTAGE_LOW) - emit(EV_temperature_low, howmuch); + int16_t howmuch = (THERM_FLOOR - avg_projected_temperature) >> THERM_DIFF_ATTENUATION; + if (howmuch > 0) { + // try to send out a warning (unless voltage is low) + // (LVP and underheat warnings fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_low, howmuch); + } // reset counters temperature_timer = TEMPERATURE_TIMER_START; underheat_lowpass = 0; -- cgit v1.2.3 From b7d8faa65451a5c71b5b619c605e8623ecd627dc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 10 Sep 2017 00:27:30 -0600 Subject: Made thermal regulation slightly more prediction-heavy, less noisy at stable state, and slightly smaller. Added a bit of overflow protection since I think I saw it overflow with the prediction weight increased. Uses immediate temperature (instead of avg) for lowpass reset, to make it less noisy at stable state. (more trigger-happy reset switch biases it toward inaction) Avoid using volatile var, to reduce space. Overflow prevention also caps the maximum adjustment step, which should slightly help prevent overshooting the target. --- spaghetti-monster/fsm-adc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 4efb11c..699c6cb 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -177,6 +177,7 @@ ISR(ADC_vect) { } // guess what the temperature will be in a few seconds + int16_t pt; { uint8_t i; int16_t diff; @@ -184,7 +185,7 @@ ISR(ADC_vect) { // algorithm tweaking; not really intended to be modified // how far ahead should we predict? - #define THERM_PREDICTION_STRENGTH 3 + #define THERM_PREDICTION_STRENGTH 4 // how proportional should the adjustments be? #define THERM_DIFF_ATTENUATION 2 // acceptable temperature window size in C @@ -207,24 +208,26 @@ ISR(ADC_vect) { diff = t - temperature_history[0]; // projected_temperature = current temp extended forward by amplified rate of change //projected_temperature = temperature_history[NUM_THERMAL_VALUES_HISTORY-1] + (diff< THERM_FLOOR) { - underheat_lowpass = 0; // we're definitely not too cold - } else if (avg_projected_temperature < THERM_CEIL) { - overheat_lowpass = 0; // we're definitely not too hot + if (pt > THERM_FLOOR) { + underheat_lowpass = 0; // we're probably not too cold + } else if (pt < THERM_CEIL) { + overheat_lowpass = 0; // we're probably not too hot } if (temperature_timer) { -- cgit v1.2.3 From 4c2ac2d287fd15e1db51833c0a6cb4915191edb7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 10 Sep 2017 01:33:04 -0600 Subject: Adjusted thermal regulation based on results of some handheld runtime tests. It was bouncing before, and now it's not. (cut response magnitude in half, increased width of null zone) --- spaghetti-monster/fsm-adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 699c6cb..02fd8c2 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -187,9 +187,9 @@ ISR(ADC_vect) { // how far ahead should we predict? #define THERM_PREDICTION_STRENGTH 4 // how proportional should the adjustments be? - #define THERM_DIFF_ATTENUATION 2 + #define THERM_DIFF_ATTENUATION 3 // acceptable temperature window size in C - #define THERM_WINDOW_SIZE 8 + #define THERM_WINDOW_SIZE 10 // highest temperature allowed // (convert configured value to 14.1 fixed-point) #define THERM_CEIL (((int16_t)therm_ceil)<<1) -- cgit v1.2.3 From e4634255795f04a1d859aa691fbc6e729973b14d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 22 Sep 2017 07:22:16 -0600 Subject: Slightly increased resolution of VOLTAGE_FUDGE_FACTOR. My lights seemed to measure just a bit low, so hopefully this will help. It bumps up reported values by 0.05V. --- spaghetti-monster/fsm-adc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 02fd8c2..5be3061 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -108,7 +108,8 @@ ISR(ADC_vect) { // calculate actual voltage: volts * 10 // ADC = 1.1 * 1024 / volts // volts = 1.1 * 1024 / ADC - voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; #endif // if low, callback EV_voltage_low / EV_voltage_critical // (but only if it has been more than N ticks since last call) -- cgit v1.2.3 From 56316ceb551bc807fc1c20a2344a4b09e99e5c4c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 6 Oct 2017 00:35:08 -0600 Subject: Updated more temperature bits to be 14.1 instead of 13.2. --- spaghetti-monster/fsm-adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 5be3061..839fba8 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -151,10 +151,10 @@ ISR(ADC_vect) { for(uint8_t i=0; i THERM_FLOOR) { @@ -240,15 +249,15 @@ ISR(ADC_vect) { if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { overheat_lowpass ++; } else { + // reset counters + overheat_lowpass = 0; + temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? int16_t howmuch = (avg_projected_temperature - THERM_CEIL) >> THERM_DIFF_ATTENUATION; if (howmuch > 0) { // try to send out a warning emit(EV_temperature_high, howmuch); } - // reset counters - temperature_timer = TEMPERATURE_TIMER_START; - overheat_lowpass = 0; } } @@ -257,6 +266,9 @@ ISR(ADC_vect) { if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { underheat_lowpass ++; } else { + // reset counters + underheat_lowpass = 0; + temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? int16_t howmuch = (THERM_FLOOR - avg_projected_temperature) >> THERM_DIFF_ATTENUATION; if (howmuch > 0) { @@ -265,9 +277,6 @@ ISR(ADC_vect) { if (voltage > VOLTAGE_LOW) emit(EV_temperature_low, howmuch); } - // reset counters - temperature_timer = TEMPERATURE_TIMER_START; - underheat_lowpass = 0; } } } @@ -275,7 +284,7 @@ ISR(ADC_vect) { #endif // ifdef USE_THERMAL_REGULATION - // start another measurement for next time + // set the correct type of measurement for next time #ifdef USE_THERMAL_REGULATION #ifdef USE_LVP if (adc_step < 2) ADMUX = ADMUX_VCC; -- cgit v1.2.3 From 5ee5845d4614cb8285cdf0bf529c26bec7ce7217 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 24 Jan 2018 19:43:00 -0700 Subject: FSM: added ability to adjust temperature calibration in UI (lower-case therm_cal_offset var). --- spaghetti-monster/fsm-adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index d863b94..c6f5d2a 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -150,7 +150,7 @@ ISR(ADC_vect) { // temperature else if (adc_step == 3) { // Convert ADC units to Celsius (ish) - int16_t temp = measurement - 275 + THERM_CAL_OFFSET; + int16_t temp = measurement - 275 + THERM_CAL_OFFSET + therm_cal_offset; // prime on first execution if (reset_thermal_history) { -- cgit v1.2.3 From f62a4852be155cfb96231ee3272e082080895bf9 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 1 May 2018 19:54:19 -0600 Subject: Made voltage ADC readings work on pin7 if USE_VOLTAGE_DIVIDER is defined. --- spaghetti-monster/fsm-adc.c | 48 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'spaghetti-monster/fsm-adc.c') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index c6f5d2a..6e9f19b 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -20,13 +20,25 @@ #ifndef FSM_ADC_C #define FSM_ADC_C +#ifdef USE_VOLTAGE_DIVIDER +// 1.1V / pin7 +#define ADMUX_VOLTAGE ADMUX_VOLTAGE_DIVIDER +#else +// VCC / 1.1V reference +#define ADMUX_VOLTAGE ADMUX_VCC +#endif + inline void ADC_on() { // read voltage on VCC by default + ADMUX = ADMUX_VOLTAGE; + #ifdef USE_VOLTAGE_DIVIDER + // disable digital input on divider pin to reduce power consumption + DIDR0 |= (1 << VOLTAGE_ADC_DIDR); + #else // disable digital input on VCC pin to reduce power consumption //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin - // VCC / 1.1V reference - ADMUX = ADMUX_VCC; + #endif // enable, start, prescale ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL; } @@ -35,6 +47,16 @@ inline void ADC_off() { ADCSRA &= ~(1<> 2; + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(total); + #else voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; + #endif } #else // no USE_LVP_AVG - // calculate actual voltage: volts * 10 - // ADC = 1.1 * 1024 / volts - // volts = 1.1 * 1024 / ADC - //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; - voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(measurement); + #else + // calculate actual voltage: volts * 10 + // ADC = 1.1 * 1024 / volts + // volts = 1.1 * 1024 / ADC + //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; + #endif #endif // if low, callback EV_voltage_low / EV_voltage_critical // (but only if it has been more than N ticks since last call) @@ -287,14 +317,14 @@ ISR(ADC_vect) { // set the correct type of measurement for next time #ifdef USE_THERMAL_REGULATION #ifdef USE_LVP - if (adc_step < 2) ADMUX = ADMUX_VCC; + if (adc_step < 2) ADMUX = ADMUX_VOLTAGE; else ADMUX = ADMUX_THERM; #else ADMUX = ADMUX_THERM; #endif #else #ifdef USE_LVP - ADMUX = ADMUX_VCC; + ADMUX = ADMUX_VOLTAGE; #endif #endif } -- cgit v1.2.3