ADC auto-triggered by TCNT overflow

Hi,

I am having a little trouble using the ADC auto-triggered by the timer/counter on the Orangutan LV-168. Since I am everything else but experienced, it is probably some simple mistake I am making. Anyway, I would be very grateful for any help on this.

Here’s what I have done so far:

I have put a voltage I would like to measure on PC3 (ADC3) and have checked it already using the ADC without auto-triggering:

ADCSRA = 0x87;		// bit 7 set: ADC enabled
						// bit 6 clear: don't start conversion
						// bit 5 clear: disable autotrigger
						// bit 4: ADC interrupt flag
						// bit 3 clear: disable ADC interrupt
						// bits 0-2 set: ADC clock prescaler is 128
ADMUX = 0x03;		// bit 7 and 6 clear: voltage ref is Vref pin
						// bit 5 clear: right-adjust result (10-bit ADC)
						// bit 4 not implemented
						// bits 0-3: ADC channel (channel 3)
ADCSRA |= (1 << ADSC);              // start conversion
		while ( ADCSRA & ( 1 << ADSC ))		// wait while converting
				;

Displaying the result on ADC shows reasonable results, so the problem I have is definitely just auto-triggering the ADC at TCNT overflows.

So the following shows how I wanted to use auto-triggering:

// ******** Set up the timer/counter ******************************/
	TCCR0A = 0x00;	// normal operation mode
	TCCR0B = 0x05; 	// 1024 prescaler => 20MHz / 1024 = ca. 20 kHz

/ *************Set up the ADC*********************************/
ADCSRA = 0x87;		// bit 7 set: ADC enabled
						// bit 6 clear: don't start conversion
						// bit 5 clear: disable autotrigger (set below)
						// bit 4: ADC interrupt flag
						// bit 3 clear: disable ADC interrupt
						// bits 0-2 set: ADC clock prescaler is 128
	
ADCSRA |= 1 << ADATE; // Auto Trigger enable

ADMUX = 0x03;		// bit 7 and 6 clear: voltage ref is Vref pin
						// bit 5 clear: right-adjust result (10-bit ADC)
						// bit 4 not implemented
						// bits 0-3: ADC channel (channel 3)
	
ADCSRB = 0x04; // triggered by TCNT0 Overflow

Checking the ADC values on the LCD it seems like the MCU is doing either one single conversion or no conversion at all. I am not completely sure, because I have tried this on both the LV168 and on an ATtiny13. The LCD shows on constant value, so I think it does one conversion. The ATtiny13 application always gives me 0 as the result, but maybe there is a mistake on the PCB I am using with the tiny13…

Thanks in advance for your help!!

-Robert

Hi Robert,

This is yet another case of having to play “connect the dots” with the datasheet:

The timer overflowing doesn’t trigger the ADC directly, it sets the overflow interrupt flag high, and it’s the setting of the flag that triggers the ADC (or selecting it as the trigger source when it is already set). This is an important distinction, because while the timer will keep counting and overflowing, the timer overflow interrupt flag will stay set until something clears it. That’s why you’re only getting one ADC conversion.

The easiest thing to do in this case is to manually clear the interrupt flag after reading the new ADC value, which you actually do by attempting to set the flag bit (another bit of AVR weirdness) like this:
TIFR0|=(1<<TOV0);//clear Timer0 overflow flag

You could also make the interrupt clear its flag automatically by enabling interrupts and the Timer0 overflow interrupt, and setting up an empty interrupt service request function, or using the empty interrupt macro. If you aren’t familiar with interrupts there really isn’t any advantage to doing it this way, except that in this case the timer will trigger a new ADC conversion even if you haven’t gotten around to the part of your code that would manually clear the flag by the time the timer overflows again. Wow, that was quite a sentence.

Did that get it working for you?

-Adam

Hi Adam,

thanks for the great explanation!!

I tried both clearing the TOV0 bit by code and using an empty ISR and it works perfectly!! Thank you!!

Best,
Robert