From 5090774fd8ca593d3b247b099b3b6a40e837475e Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Wed, 21 Nov 2012 23:07:17 +0100 Subject: [PATCH] adc: measure the offset of the gain-20 stage We measure the offset of the ADC1:ADC1 gain 20 stage and subtract it from ADC0:ADC1 and ADC2:ADC1 differential readings. --- firmware/adc.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/firmware/adc.c b/firmware/adc.c index 38f3677..d0ee1c4 100644 --- a/firmware/adc.c +++ b/firmware/adc.c @@ -5,12 +5,14 @@ #define AMBIENT_ADC N_PWMLEDS #define BATTERY_ADC (N_PWMLEDS + 1) +#define ADC1_GAIN20 (N_PWMLEDS + 2) -#define NUM_ADCS 5 +#define NUM_ADCS 6 volatile static unsigned char current_adc; static uint16_t adc_sum; static unsigned char sum_shift; static unsigned char adc_vals; +static uint16_t adc1_gain20_offset_x16; static void inline setup_mux(unsigned char n) { @@ -38,6 +40,10 @@ static void inline setup_mux(unsigned char n) ADMUX = _BV(REFS1) | _BV(MUX2) | _BV(MUX1); sum_shift = 0; // 1 measurement break; + case 5: // gain stage offset: 1.1V, ADC1,1, gain 20 + ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); + sum_shift = 3; // 8 measurements + break; } adc_sum = 0; @@ -59,6 +65,7 @@ static void start_next_adc() void init_adc() { + unsigned char i; current_adc = NUM_ADCS; ADCSRA = _BV(ADEN) // enable @@ -71,12 +78,27 @@ void init_adc() DIDR0 = _BV(ADC0D) | _BV(ADC1D) | _BV(ADC2D) | _BV(ADC4D) | _BV(ADC5D) | _BV(ADC6D); + // 1.1V, ADC1,1, gain 20 + ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); ADCSRA |= _BV(ADSC); /* Do first conversion and drop the result */ while ((ADCSRA & _BV(ADIF)) == 0) ; ADCSRA |= _BV(ADIF); // clear the IRQ flag + + adc1_gain20_offset_x16 = 0; + + for (i = 0; i < 16; i++) { + ADCSRA |= _BV(ADSC); + + while ((ADCSRA & _BV(ADIF)) == 0) + ; + adc1_gain20_offset_x16 += ADCW; + + ADCSRA |= _BV(ADIF); // clear the IRQ flag + } + ADCSRA |= _BV(ADIE); // enable IRQ ADCSRA &= ~_BV(ADEN); // disable until needed @@ -110,6 +132,18 @@ ISR(ADC_vect) { // IRQ handler adcval = adc_sum >> sum_shift; + if (current_adc == ADC1_GAIN20) { + // running average + adc1_gain20_offset_x16 += adcval + - (adc1_gain20_offset_x16 >> 4); + } else if (current_adc == 0 || current_adc == 1) { + uint16_t offset = adc1_gain20_offset_x16 >> 4; + if (adcval >= offset) + adcval -= offset; + else + adcval = 0; + } + if (current_adc < N_PWMLEDS) pwmled_adc(current_adc, adcval); if (current_adc == AMBIENT_ADC) -- 2.39.3