Temp: read ADC on-demand, instead of constantly running.

On AVRs analog conversions were running in essentially
free-running mode, i.e.  next conversion was being started
immediately after the previous one ended. This caused many
unnecessary interrupts.

Now, conversions are initiated manually by start_adc(). This
causes a single read on each of the registered channels. Once
all channels are read, conversions stop until the next call of
start_adc().
This commit is contained in:
Robert Konklewski 2016-04-21 19:32:23 +02:00 committed by Markus Hitter
parent 03c8d71a56
commit b5cbba7ed8
3 changed files with 42 additions and 10 deletions

View File

@ -46,11 +46,18 @@ void analog_init() {
DIDR2 = (analog_mask >> 8) & 0xFF; DIDR2 = (analog_mask >> 8) & 0xFF;
#endif #endif
// now we start the first conversion and leave the rest to the interrupt // Enable the ADC.
ADCSRA |= MASK(ADIE) | MASK(ADSC); ADCSRA |= MASK(ADIE);
} /* analog_mask */ } /* analog_mask */
} }
/**
Start a new ADC conversion.
*/
void start_adc() {
ADCSRA |= MASK(ADSC);
}
/*! Analog Interrupt /*! Analog Interrupt
This is where we read our analog value and store it in an array for later retrieval This is where we read our analog value and store it in an array for later retrieval
@ -77,8 +84,10 @@ ISR(ADC_vect, ISR_NOBLOCK) {
ADCSRB &= ~MASK(MUX5); ADCSRB &= ~MASK(MUX5);
#endif #endif
// After the mux has been set, start a new conversion // If there is another channel to read, start a new conversion.
ADCSRA |= MASK(ADSC); if (adc_counter != 0) {
ADCSRA |= MASK(ADSC);
}
} }
} }

View File

@ -49,10 +49,26 @@
#error REFERENCE undefined. See analog.h on how to choose it. #error REFERENCE undefined. See analog.h on how to choose it.
#endif #endif
/** \def NEEDS_START_ADC
Whether the board needs and implements start_adc(), i.e. analog reads
on-demand (as opposed to free-running ADC conversions).
Currently only implemented on AVR.
*/
#define NEEDS_START_ADC
#endif /* __AVR__ */ #endif /* __AVR__ */
void analog_init(void); void analog_init(void);
uint16_t analog_read(uint8_t index); uint16_t analog_read(uint8_t index);
#ifdef NEEDS_START_ADC
#define DO_START_ADC() do { start_adc(); } while (0)
void start_adc(void);
#else
#define DO_START_ADC()
#endif
#endif /* _ANALOG_H */ #endif /* _ANALOG_H */

19
temp.c
View File

@ -110,15 +110,19 @@ void temp_init() {
#endif #endif
#ifdef TEMP_THERMISTOR #ifdef TEMP_THERMISTOR
// handled by analog_init() // Mostly handled by analog_init().
/* case TT_THERMISTOR: case TT_THERMISTOR:
break;*/ // Start a conversion so it's ready for the first temp_sensor_tick().
DO_START_ADC();
break;
#endif #endif
#ifdef TEMP_AD595 #ifdef TEMP_AD595
// handled by analog_init() // Mostly handled by analog_init().
/* case TT_AD595: case TT_AD595:
break;*/ // Start a conversion so it's ready for the first temp_sensor_tick().
DO_START_ADC();
break;
#endif #endif
#ifdef TEMP_INTERCOM #ifdef TEMP_INTERCOM
@ -309,6 +313,8 @@ void temp_sensor_tick() {
temp = temp_table_lookup(analog_read(i), i); temp = temp_table_lookup(analog_read(i), i);
temp_sensors_runtime[i].next_read_time = 0; temp_sensors_runtime[i].next_read_time = 0;
DO_START_ADC();
break; break;
#endif /* TEMP_THERMISTOR */ #endif /* TEMP_THERMISTOR */
@ -332,6 +338,7 @@ void temp_sensor_tick() {
temp = (temp * 500L) >> 8; temp = (temp * 500L) >> 8;
temp_sensors_runtime[i].next_read_time = 0; temp_sensors_runtime[i].next_read_time = 0;
DO_START_ADC();
break; break;
#endif /* TEMP_AD595 */ #endif /* TEMP_AD595 */