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

View File

@ -49,10 +49,26 @@
#error REFERENCE undefined. See analog.h on how to choose it.
#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__ */
void analog_init(void);
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 */

19
temp.c
View File

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