diff options
| author | Selene ToyKeeper | 2018-05-01 19:54:19 -0600 |
|---|---|---|
| committer | Selene ToyKeeper | 2018-05-01 19:54:19 -0600 |
| commit | f62a4852be155cfb96231ee3272e082080895bf9 (patch) | |
| tree | 87bcea4ae73d835e2172e4a3e596700ee10d6d9f /spaghetti-monster/fsm-adc.c | |
| parent | Added BLF GT 150-level ramp. Is a bit of a mess though. (diff) | |
| download | anduril-f62a4852be155cfb96231ee3272e082080895bf9.tar.gz anduril-f62a4852be155cfb96231ee3272e082080895bf9.tar.bz2 anduril-f62a4852be155cfb96231ee3272e082080895bf9.zip | |
Made voltage ADC readings work on pin7 if USE_VOLTAGE_DIVIDER is defined.
Diffstat (limited to '')
| -rw-r--r-- | spaghetti-monster/fsm-adc.c | 48 |
1 files changed, 39 insertions, 9 deletions
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<<ADEN); //ADC off } +#ifdef USE_VOLTAGE_DIVIDER +static inline uint8_t calc_voltage_divider(uint16_t value) { + // use 9.7 fixed-point to get sufficient precision + uint16_t adc_per_volt = ((ADC_44<<7) - (ADC_22<<7)) / (44-22); + // incoming value is 14.2 fixed-point, so shift it 2 bits less + uint8_t result = ((value<<5) / adc_per_volt) + VOLTAGE_FUDGE_FACTOR; + return result; +} +#endif + // Each full cycle runs 7.8X per second with just voltage enabled, // or 3.9X per second with voltage and temperature. #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) @@ -109,14 +131,22 @@ ISR(ADC_vect) { total += measurement; total = total >> 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 } |
