ADC - Free Running mode

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I a mucking about with ADC on a AtMega48. I seem to have it halfway working, but I cannot for the life of me iniatie free running mode. I think.

I've read an excellent tutorial for the mega128 ( https://www.avrfreaks.net/index.p... ) to get me started on the code.

This is what I have so far;

// Set the DDRC for output on 2 leds
DDRC =  0b00110000;

// Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);

// Set ADC reference to AVCC
ADMUX |= (1 << REFS0); 

// Left adjust ADC result to allow easy 8 bit reading
ADMUX |= (1 << ADLAR); 

// No MUX values needed to be changed to use ADC0

// Set ADC to Free-Running Mode11
// ADCSRA |= (1 << ADFR);  
// This part is AtMega128, so need to replace it

//  Auto Triggering is	enabled by 
//  setting the ADC Auto Trigger Enable bit, 
//  ADATE in ADCSRA
ADCSRA |= (1 << ADATE);  

//	 ADTS2:0: ADC auto trigger source to 000 per datasheet
ADCSRB |= (0 << ADTS0);  
ADCSRB |= (0 << ADTS1); 
ADCSRB |= (0 << ADTS2); 

// Enable ADC
ADCSRA |= (1 << ADEN);  

// Start A2D Conversions
ADCSRA |= (1 << ADSC);  

for(;;)  // Loop Forever
{
	if(ADCH < 128)
	{
		bit_set( PORTC, BIT(4));
		bit_clear( PORTC, BIT(5));
	}

	else
	{
		bit_set( PORTC, BIT(5));
		bit_clear( PORTC, BIT(4));
	}
}

This code seems to work. Once. It correctly detects if I have wired up almost no resitors and it measures a 0,25 volts and flashes one led. Or if I hookup 10K it measures about 2.5 volts and lights the other.

But only once, I boot up the chip, it toggles the correct led, but then it never changes again, as if there is no new measurement being made.

I am seriously doubting wether I put the free running mode correctly. But according to the table from the datasheet, I have;

Table 24-5. ADC auto trigger source selections.
ADTS2 ADTS1 ADTS0 Trigger source
0 0 0 Free running mode
0 0 1 Analog comparator
0 1 0 External interrupt request 0
0 1 1 Timer/counter0 compare match A
1 0 0 Timer/counter0 overflow
1 0 1 Timer/counter1 compare match B
1 1 0 Timer/counter1 overflow
1 1 1 Timer/counter1 capture event

Can anyone offer me some help? Cos, after reading the sheet for two days and trying a bunch of things, I got nothing.

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well a cursory glance suggests that what you are doing is correct in fact. Could you mirror all 8 bits of ADCH to a whole PORT of LEDs perhaps to see whether there was any variation in the reading? Better yet use a debugger or perhaps printf() to a UART or LCD.

Oh and silly question: AVcc is connected to Vcc?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I will try, with mirror you mean something like;

DDRB = 0xff;
PORTB = ADCH;

In the loop of course. Sadly, I don't have debugger on hand, except the AVR Simulator. Or is this something a JTAGICE mkII could do? I have a clone of that device.

And yes, AVcc is connected to Vcc, if measured it a 100 times going crazy :)

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hooked up the leds, they show no difference in the readings, sadly. However if I put this bit of code in the main loop, it does work, but that seems quite wrong to do;

ADCSRA |= (1 << ADSC);  // Start A2D Conversions

Which implies to me that somehow, some bit got set after reading ADCH. But why.

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup the need to keep setting ADSC does suggest it's not free running yet I checked the ADATE and ADTS bits you are setting - you have the right bits and the right registers and I don't see anything over-writing them. By the way this:

ADCSRB |= (0 << ADTS0); 
ADCSRB |= (0 << ADTS1);
ADCSRB |= (0 << ADTS2); 

is wrong. That's not how you set 0 bits. You should use:

ADCSRB &= ~(1 << ADTS0); 
ADCSRB &= ~(1 << ADTS1);
ADCSRB &= ~(1 << ADTS2); 

the OR with 0 will have no effect but it shouldn't matter as the ADTS bits default to 0 anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for that bit of information. At least I upgraded my coding standard a bit again.

Even if I am still stumped. Thanks for your insights.

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had an issue with ADC on atmega myself recently, and it turns out that even all syntaxis and registers names were spelled correctly, one of the bit position was not set. Could you verify printing back via serial ADMUX/ADCSRA/ADCSRB content of registers in HEX is correct? See if something is missing or vice-versa.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The free running mode was almost useless.
You save no code, because you must always handle the trigger source interrupt.
Otherwise the flag was not cleared and you get only one single conversion.

Also depending from other interrupts, it may happen,
that already the next conversion was finished and you read the wrong channel.

So the free running mode was only useful, if you read only one input and without a trigger source.

Thus I use always the timer interrupt to read multiple channels.

Timer interrupt handler:
- read the ADC result
- change the MUX to the next input
- start conversion

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is for a toy lock, it listens constantly to figure out if someone is connecting a 'lockpick' to the device. The lockpick in fact is nothing more then a resistor.

So if a kid hooks up the right resistor, the lock opens.

If they hook up the wrong resistor, the lock starts flashing bright red leds.

The way I do this now is to constantly monitor the ADC, is the value change to a certain marigin, I trigger some routine in the AVR.

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, I am confused a bit.

I am running the code as above, but something weird is happening. As long as I don't connect AREF all seems to work sorta fine. But as soon as I do conncet AREF the only value it is able to read seems to be 256.

If I disconnect AREF it reads different values depening on the resistor. I have little experience in ADC, but not connecting AREF seems wrong. Also, connectin AVCC doesn't impact the readings. This is my setup. Can anyone point out my mistake?

Attachment(s): 

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have no capacitors in your schematic !
You have AREF connected to GND!

You normally connect AREF to a capacitor. This means you can use internal references.
If you want to actualy use an external reference, you must be careful to never select the internal reference modes. (and it is unusual to select a reference of 0V i.e. GND)

As always. Find a real life production schematic on the internet. e.g. a commercial dev board.

Then COPY it.

David.

p.s. avoid schematics from internet tutorials. they are often pants. Always compare with a real-life board.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, I did get this from a tutorial, on this site no less. But I wouldn't know where to find a commercial schematic, even if I could read it. I am just a hobbyist.

In any case, thank you for your insights again, so if I hook up a capacitor to the AREF, it should be fine? Just an inline electrolyte cap? 0.1 uf? Or ceramic? I googled around and it is refered to as a low pass filter.

The thing is, this works, withouth connecting either AVCC or AREF. I just don't understand why it does.

Code, justify, code - Pitr Dubovich

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. It is recommended not to switch IO pins on PORTC while the conversion is in progress.
To avoid this I would place the Leds on another port.

2. The resistor identification in your schematic will not work. You get (nearly) the same result whichever buton you press.
To change the measured voltage you have to change R1 (or R2), not R3,4,5.

I am attaching the schematic I use.
An LC filter on AVCC would help in a noisy environment.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you all, it works. Thank you very much.

Pictures of the device in all it's glory are forthcoming.

Code, justify, code - Pitr Dubovich