ADC auto-triggering - how to switch it off

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

I have an ATmega32 that i've set up to sample analog signals at 1 ms intervals. To get exact timings, i use the Timer1 compare match B as the trigger source for the ADC. The ADC complete interrupt then does some follow-on calculations.

This all works very well and i do get my samples. But, from time to time i'd like to stop sampling, so i thought it'd be enough to simply stop Timer 1 via setting the prescaler bits all to zero. What happens is that the ADC keeps happily sampling and the ADC complete interrupts continue to occur, as if stopping timer 1 would have no effect at all.

Now, do i misinterpret the manual? My understanding is that due to a stopped timer, no compare match event will occur, therefore no triggering of the ADC could happen.

Where am i wrong here? Of course i could change the ADC settings to have it stop, but i'd like to simply stop timer 1 for that purpose.

advTHANKSance,

-- Thilo

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Stopping the timer should work, however, it will not stop any conversion currently in progress.

Regards,
Steve A.

The Board helps those that help themselves.

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

Let's see some code. In particular, the "stop timer" sequence.

IIRC the trigger is the xxIFxx bit being set. So you could get one more. I don't know if it is the edge of the flag bit or the level--does the datasheet discuss that?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

D you have the ADC set to free run?

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

Maybe i wasn't clear enough, but i'm not complaining about one additional conversion. My problem is an unstoppable ADC!

Quote:
D you have the ADC set to free run?

Well, my understanding of free run is having the ADTS2:0 bits in SFIOR set to "free run", vs. "Timer/Counter 1 compare match B", which is what i am using.

My initialization looks like this:

void Init_ADC(void) {
	// channel 0, internal reference
	ADMUX   = _BV(REFS1) | _BV(REFS0); 
	
	ADCSRA  = _BV(ADEN)	// enable ADC
					| _BV(ADATE)// enable auto-trigger
					| _BV(ADIF)	// clear ADIF flag
					| _BV(ADIE)	// enable ADC completion interrupt
					| _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);// prescaler = 128
// select Timer 1 OCR1B match as trigger source					
	SFIOR   = _BV(ADTS2) | _BV(ADTS0);	
}

void Init_Timers(void) {
	// set up Timer 1
	TIMSK	 = 0;					// we don't want any timer-related interrupts
	OCR1A  = 1500;			// This resets the timer each ms @ 12 MHz
	OCR1B  = 1500;			// This triggers the ADC each ms @ 12 MHz
	TCCR1A = 0;
	TCCR1B = _BV(WGM12);// CTC mode up to OCR1A value, Timer still stopped!
											// We don't enable the timer here, this is done via
											// a macro that defines a prescale factor of 8.
											// A second macro disables the timer, see #defines above
}

Note that i didn't yet set any prescaler value, so the timer should still be stopped, however, the conversions start right after the initialization! So, in fact i do have 2 probems: the conversions take place before i even start the trigger source (timer 1), and they don't stop when i disable the trigger source (timer 1).

This is how i stop the timer:

TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10);

-- Thilo

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Try clearing the timer flag before enabling the timer as a trigger source for the ADC via the SFIOR bits.

Quote:

Note that switching from a trigger source that is cleared to a trigger source that is set,
will generate a positive edge on the trigger signal. If ADEN in ADCSRA is set, this will
start a conversion.

the SFIOR bits are 0's before you set them, if the timer flag is set when you switch the SFIOR bits, then a conversion will start.

As for the conversions not stopping... please show us your ADC ISR.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Quote:
Try clearing the timer flag before enabling the timer as a trigger source for the ADC.

??? After my ADC & Timer init code, i start with the prescaler bits still being set to "Timer stopped". Then at some time i finally set the prescaler bits to some nonzero value that basically enables the timer. This is where the first conversion should be triggered (after timer 1 hit the OCR1B value). Then, some time later i reset the prescaler bits again to zero, which should stop the timer again, according to the docs. And then no more conversions (ok +/- one) should be triggered.

And yes, i could modify the ADC settings (esp. ADATE), but i need to stop the timer anyway, and i don't understand why stopping the timer isn't sufficient.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Then, either you are NOT stopping the timer OR you are not running the ADC in the mode you think you are.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Here's the ADC INT routine. If DATAN samples have been collected, a flag is set (StateMask), which then will be read in my main() and the timer will be stopped accordingly.

As a test i even stopped the timer directly in the ADC INT routine after DATAN samples, with absolutely no difference: the ADC simply continues to do conversions forever. And ADC_USE_CHANNEL is simply a one-line macro that sets the right bits to select either channel 0 or 1.

ISR(ADC_vect) {
	*CapturePtr++ = ADC;	// getADC sample
	SampleCnt--;
	if (SampleCnt == (DATAN/2)) {
		ADC_USE_CHANNEL(1);	// switch ADC channel after DATA/2 samples
	}
	else if (!SampleCnt) {
		StateMask = COMPLETE;	// tell main we're done
	}
	TIFR |= (_BV(OCF1B) | _BV(OCF1A));// clear OCR interrupt flags
	ADCSRA |= _BV(ADIF); // shouldn't be necessary, just a test
}

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Quote:
Then, either you are NOT stopping the timer OR you are not running the ADC in the mode you think you are.

Exactly! But then PLEASE show me what i'm doing wrong! I modify the right bits in TCCR1B to set the prescaler bits to zero, that should stop timer 1, right?

TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10));

And i do not see what would be wrong with my init of ADCSRA!

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

Last Edited: Tue. Sep 28, 2010 - 09:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

i don't understand why stopping the timer isn't sufficient.

Quote:

TIMSK = 0; // we don't want any timer-related interrupts

Earlier, I guessed:
Quote:

IIRC the trigger is the xxIFxx bit being set. So you could get one more. I don't know if it is the edge of the flag bit or the level--does the datasheet discuss that?

Given your symptoms, I'm guessing you are getting continuous conversions even when the timer is running, rather than one every few ms. Digging in the datasheet...

Nope, it is the opposite if you have no code to clear OCF1B. So either your ADC is not running off the trigger source you think it is, or something is happening in unseen code.

Quote:
Alternatively, a conversion can be triggered automatically by various sources. Auto Triggering is enabled by setting the ADC Auto Trigger Enable bit, ADATE in ADCSRA. The trigger source is selected by setting the ADC Trigger Select bits, ADTS in SFIOR (see description of the ADTS bits for a list of the trigger sources). When a positive edge occurs on the selected trigger signal, the ADC prescaler is reset and a conversion is started. This provides a method of starting conversions at fixed intervals. If the trigger
signal still is set when the conversion completes, a new conversion will not be started. If another positive edge occurs on the trigger signal during conversion, the edge will be ignored. Note that an interrupt flag will be set even if the specific interrupt is disabled or the global interrupt enable bit in SREG is cleared. A conversion can thus be triggered without causing an interrupt. However, the interrupt flag must be cleared in order to trigger a new conversion at the next interrupt event.

So, as a sanity check, for you and us, post the small[est] complete program that demonstrates the behaviour.

Also, how are you determining the symptoms? If you say "simulator" then try on a real chip--the simulator is not known for doing advanced timing modes well.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

No no, this is happening on a real chip. I'm using the UART to report some info at strategic points.

I'll see if i can trim the app. down to a couple dozen lines of code, but only after some hours of sleep!

Thanks so far, guys!

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

@theusch: yes, it is quite possible that even when the timer is running, my conversions are taking place at random/unknown intervals.

But regarding "different trigger sources"... Surely, a conversion can be triggered by various sources, but you can only select exactly one particular trigger source with SFIOR. Once set, this source and nothing else will ever trigger the ADC (unless you use the ADSC bit to manually trigger a conversion).

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

Last Edited: Tue. Sep 28, 2010 - 09:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'll see if i can trim the app. down to a couple dozen lines of code, but only after some hours of sleep!


If you have a 'scope or frequency counter, toggle some pins based on conditions such as hitting ISRs.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

DO1THL wrote:
Quote:
Try clearing the timer flag before enabling the timer as a trigger source for the ADC.

??? After my ADC & Timer init code, i start with the prescaler bits still being set to "Timer stopped".

Yes, BUT, as the quote I included above suggests, if you transition from a trigger flag source that is clear, to one that is set, you will trigger a conversion if ADEN is set.

So imagine this. On reset [or whenever you do your ADC init], your ADTS bits are all 0's which selects free running mode [ie the ADCIF as the trigger source] and ADCIF is 0. But for some reason your OC1F is set. Now when you change the ADTS bists to use OC1F as the source, you are creating a rising edge, and thus triggering a conversion. Clearing the OC1F bit just before changing the ADTS bits will prevent this early conversion.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Tue. Sep 28, 2010 - 09:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't see an initial value for SampleCnt, or even a declaration. If it is not given an initial value, it will be zero, so if its a uint8_t, it will take 256 passes to reach back to zero again. That might not be what you expect. Do you have the ability to debug with a break at that point?

Also, since the state has to be interpreted in your main loop and THAT is the real place where the timer is supposed to be turned off, we had better see your main loop state handler.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Also, do NOT use RMW operatins like |= and &= when adjsuting flags registers, doing so will inadvertantly clear ALL flags currently set in those registers, not just the one you want to. To clear a flag register write a 1 to only the bits you wish to clear, writing 0's to all others.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

But all of the above would be just one extra conversion. I think things will become clearer when we see the sanity-check program, as well as a true indication of how many ADC conversions and their timing.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Yes, that comment was purly focused at the conversion BEFORE he enables the timer itself. Additional conversions POST disabling are another issue, though could also be the root cause.

silly question, but is the correct device being handed to GCC from the makefile?

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

@ka7ehk:
I'm aware of SampleCnt and the fact that if i don't initialize it, my ADC INT code would take one complete 8bit round (=256 samples). BUT: i see THOUSANDS of conversions, so SampleCnt should get zero not only once :-)

And again: i even tried to stop the time directly in the ADC INT routine without success. My main routine is pretty much out of scope for this error. With the current state, it exactly does nothing but sending the string "COMPLETE" to the UART when StateMask get set to COMPLETE, then main sleeps again.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

@theusch:

How would i then clear the ADC int flag ADIF in ADCSRA without modifying the other bits? I need to use the | operator to just set ADIF in ADCSRA via |=.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

DO1THL wrote:
@theusch:

How would i then clear the ADC int flag ADIF in ADCSRA without modifying the other bits? I need to use the | operator to just set ADIF in ADCSRA via |=.

You're ok with ADCSRA, as it is not purly a flags register, and there is only one flag bit. Though had there been more than one flag bit you would need to mask all the flag bits to 0 [preserving all other bits], and then set the individual flag bit you wish to clear.

The problem is with your TIFR line.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Do you ever get your "COMPLETE" string on the terminal?

I wonder if something is not happening elsewhere to "adjust" SampleCnt. Maybe it is (accidently) being reset to zero somewhere so that the equality never occurs. If you then put a timer stop in that same part of the else if() statement, that also would never be executed. So, it would appear as if it is never turned off.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Yes, seeing "COMPLETE" strings flooding the terminal is my way to see that the ADC is never stopping... And no, SampleCnt isn't touched anywhere except within a routine that sets up some data pointers and starts the timer. Right now, this whole routine is commented out.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

All,

Not to stick my nose in.
Are all variables used in your interrupt declared as volatile?

A.

AVR Studio 4 Ver. 4.18 684
avr-gcc Ver. 4.3.0
ISIS 7
ELECTRA

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

Where you say, earlier:

Quote:
This is how i stop the timer:

TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10); 

I hope that is a typo from hand transcribing code, but it looks like a ")" is missing.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Yes, volatile used.

Yes, missing ')' is a typo.

And yes: my conversions take place at quite some higher rate than 1000/s. I spit out a short string every time i expect one second to have passed, and that string appears let's say 5/sec.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Quote:

As a test i even stopped the timer directly in the ADC INT routine after DATAN samples, with absolutely no difference: the ADC simply continues to do conversions forever. And ADC_USE_CHANNEL is simply a one-line macro that sets the right bits to select either channel 0 or 1.


As mentioned, I want to see a complete program. All of it. Even if you need to re-create something. IME sanity checks are also sanity preservation. Blind guess is SFIOR getting trampled somewhere. But without a complete program or some report of instrumentation we can guess all night.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

While i didn't find the time yet to create a simple reproducer, i _think_ i found the underlying "problem". It's of course simply a lack of concise knowledge of the 317-page manual :-)

In my main routine, i setup everything for a complete round of 64 ADC samples, then send the chip to sleep in IDLE mode, expecting to awake with every interrupt. Then i would check my State variable if there's something to do for the main routine. If not, the sleep mode would be re-entered.

Now i just discovered one tiny little remark at the end of the paragraph describing IDLE mode:

Quote:
"If the ADC is enabled, a conversion starts automatically when this mode is entered."

I'm not at home right now and therefore unable to test this, but i'm pretty sure that's it!

Now seriously, guys: did you know that particular fact about the IDLE mode? And why the hell did Atmel design an automatic ADC conversion into the sleep mode of an AVR???

This fact complicates using the auto-triggering mode of the ADC, since there's simply no appropriate sleep mode to use when the ADC should be triggered by a timer. IDLE mode triggers an unwanted conversion, all other modes allow only Timer2 (only 8 bits wide!) as a timer source leaving Sleep mode, and Timer 2 can't be used as a trigger source for the ADC.

Frustrated,

-- Thilo

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Quote:

Now seriously, guys: did you know that particular fact about the IDLE mode? And why the hell did Atmel design an automatic ADC conversion into the sleep mode of an AVR???

This is for ADC noise reduction mode. It's expected that you setup for sleep then as you do the ADC conversion triggers just as the CPU enters (noiseless) sleep. It then re-awakes when the conversion is complete having made a clean reading.

Personally I've never understood the appeal of auto modes for the ADC. Exactly how much does it "cost" to set ADSC manually and keep the triggering in your own control? I can see the use of auto where, for example, you have a control knob and you just want to make an instantaneous reading at any moment simply by reading the result register. But if you want to synchronise your readings why not take control of the conversions yourself?

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

Sorry to disagree, Cliff, but that sentence has been copied from the paragraph describing IDLE mode, not noise reduction mode! In noise reduction mode, there's no such explicit ADC triggering when the AVR is waking up.

-- Thilo

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

...and, if awaking from IDLE sleep mode really does trigger an ADC conversion, i'd have to explicitly disable the ADC just before entering sleep mode :-( , just to be sure that an unrelated interrupt doesn't trigger an unwanted conversion. In turn, this first conversion would take 25 cycles, whereas the next ones would only take the normal 13 cycles.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Quote:

As mentioned, I want to see a complete program. All of it. Even if you need to re-create something. IME sanity checks are also sanity preservation. Blind guess is SFIOR getting trampled somewhere. But without a complete program or some report of instrumentation we can guess all night.

...and we still haven't seen it. Only responses to speculation. And now we learn that sleep modes are involved. >>My<< crystal ball is dusty... See how important the "smallest complete program that reproduces the symptoms" is? It might well have saved two days of back-and-forth, as well as probably much time for the OP.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Lee,
yes, you haven't seen a reproducer, not even the whole program. But i don't code for a living, but only after family is happy, house/garden/cleaning machine is ok, etc. So, when browsing the data sheet during the lunch break at work, i stumbled over that remark above (IDLE sleep mode triggers ADC conversion) and simply wanted to save us all the time to create/read over a complete program and jump directly to a highly suspect behaviour of the AVR. No flames intended though...

Ok, here's the reproducer:

#include 
#include 
#include 

// possible values for StateMask
#define IDLE            0
#define COMPLETE        (1 << 0)         

#define DATAN           64              // number of samples within one data set

void StartTimer1(void);
void StopTimer1(void);

volatile uint8_t StateMask, SampleCnt;
uint16_t ADC_Data;


int main(void) {
  DDRD  = 0x40;                         // enable Port pin D6 as output (LED)
  PORTD = 0x00;                         // switch off LED initially
  
  // init INTs
  GIFR  = 0;                            // clear all pending external INT requests
  GICR  = 0;                            // explicitly disable all external INT sources

  // init ADC
  ADMUX   = _BV(REFS1) | _BV(REFS0);    // channel 0, internal reference
  
  ADCSRA  = _BV(ADEN)                   // enable ADC
          | _BV(ADATE)                  // enable auto-trigger
          | _BV(ADIF)                   // clear ADIF flag
          | _BV(ADIE)                   // enable ADC completion interrupt
          | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // prescaler = 128

  SFIOR   = _BV(ADTS2) | _BV(ADTS0);    // select Timer 1 OCR1B match as trigger source 

  // init Timer
  TIMSK  = 0;                           // we don't want any timer-related interrupts
  OCR1A  = 15000;                       // This resets the timer every 10ms @12 MHz
  OCR1B  = 15000;                       // This triggers the ADC every 10ms @12 MHz
  TCCR1A = 0;
  TCCR1B = _BV(WGM12);                  // CTC mode up to OCR1A value, Timer still stopped!

  StateMask = 0;
  SampleCnt = DATAN;
  set_sleep_mode(SLEEP_MODE_IDLE);      // select IDLE mode when sleeping
  StopTimer1();                         // just to be sure Timer 1 is really stopped
  sei();
  
  while (1) {
    do {
      sleep_enable();
      sei();
      sleep_cpu();
      cli();
      sleep_disable();
    } while (!StateMask);

    if (StateMask & COMPLETE) {
      StateMask &= ~COMPLETE;           // reset Flag
      SampleCnt = DATAN;
    }
    else {                              // sanity check
      StateMask = 0;
    }
  }
}


// After the timer 1 output compare match triggered the ADC conversion,
// this int. routine will execute when the ADC conversion is completed.
ISR(ADC_vect) {
  ADC_Data = ADC;
  SampleCnt--;
  if (!SampleCnt) {
    StateMask = COMPLETE;               // we're done with this round
    PORTD   ^= 0x40;                    // toggle LED as indicator
  }
  TIFR = _BV(OCF1B) | _BV(OCF1A);       // clear OCR interrupt flags
  ADCSRA |= _BV(ADIF);
}


// Start Timer1 by selecting prescaler of 8
void StartTimer1(void) {
  TCNT1   = 0;
  TCCR1B |= _BV(CS11);
}


// Stop Timer1 by setting all prescaler bits to zero
void StopTimer1(void) {
  TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10));
}

Note that i changed the (expected) sampling interval from 1 ms to 10 ms, which would give me visually recognizable feedback via a blinking LED at an expected rate of 640 ms (10ms * 64 ADC samples). All i see is a dim LED, which gets toggled every 5 ms (measured via scope).

Note also that i didn't even start the timer, so, given this fact, nothing at all should happen!

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Next test:
commenting out the

      sleep_cpu();
      cli();

combo, and starting the timer gives me a nicely blinking LED at exactly the frequency i'm expecting!!

Now, DOES this point to a weird Sleep (in IDLE mode) behaviour when it comes to automatic ADC triggers?

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Hi D01THL,

Did you ever find a good solution to this?

I have been having the same problem trying to auto trigger the ADC with timer0 compare match on a Mega48. After much searching of the forums I found this one which is exactly the issue that I have.

I want to start regular ADC conversions at 50 ms intervals, so a tried using the ADC auto trigger on timer0 compare match, sleeping between conversions. But going into sleep mode idle starts an ADC conversion.

I also get different behaviour with the simulators. The original simualator only raises the timer interrupts, but not the ADC interrupts. Simulator2, however raises both the interrups, so seems better.

It would be nice to be able to use the ADC auto trigger and also use sleep mode idle. But it seems like I will need to manually start an ADC conversion after the timer interrupt. Unless there is a better option?

mp_york.

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

There's no getting around the adc doing an auto- conversion when entering idle sleep. You have to clr the ADEN bit before idle sleeping.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Quote:
Hi D01THL,

Did you ever find a good solution to this?


Well, basically yes. It involved a damaged print-out of the AVR manual, a dent in the wall, a red face, and a theoretical review if going fishing would be an alternate hobby.

My application needed to sample a signal only for several 30 ms windows within a 10-20 sec window, therefore i decided to simply let the AVR do a busy-wait loop until all ADC samples had been collected, then do some work, then sleep().

I would still like to have a chat with one of the designers of the AVR i/o subsystem to get the resaoning of this triggering behaviour, and his opinion on an intelligent usage of that feature within power-saving concepts - having returned from fishing, that is...

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

Thanks for the updates. Yes, fishing would be more relaxing. Anyway...

My application is not power critical, so I could leave the processor running and use auto triggering. However, the ADEN flag is a good suggestion, it means each ADC conversion will take more clock cycles, but the ADC can be powered down between conversions.

mp_york.