Author Topic: ATmega328P ADC help  (Read 3805 times)

0 Members and 1 Guest are viewing this topic.

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
ATmega328P ADC help
« on: November 11, 2017, 12:46:02 pm »
I am trying to set up continuous conversion on ATmega328P ADC. However the ADC interrupt is not firing. What mistake am I making here?

Code: [Select]
void adc_init(void)
{
skip_sample = true;
sample_id = 0;

ADMUX = 0;
ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS1) | _BV(ADPS0);
ADCSRB = 0;
DIDR0 = _BV(ADC0D);
ADCSRA |= _BV(ADSC) | _BV(ADIF);
}
 

Online MasterT

  • Frequent Contributor
  • **
  • Posts: 785
  • Country: ca
Re: ATmega328P ADC help
« Reply #1 on: November 11, 2017, 01:21:34 pm »
Have you missed to include interrupt subroutine?
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: ATmega328P ADC help
« Reply #2 on: November 11, 2017, 02:14:31 pm »
Interrupts still globally turned off? I.e., have you forgotten sei()?
 

Offline StillTrying

  • Super Contributor
  • ***
  • Posts: 2850
  • Country: se
  • Country: Broken Britain
Re: ATmega328P ADC help
« Reply #3 on: November 11, 2017, 02:28:18 pm »
_BV(ADPS1) | _BV(ADPS0);

Implies the system clock is only 1.6Mhz.

Should ADIF be ADIE.

.  That took much longer than I thought it would.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: ATmega328P ADC help
« Reply #4 on: November 11, 2017, 02:50:43 pm »
Interrupts still globally turned off? I.e., have you forgotten sei()?
Interrupts on. Other interrupts are firing normally.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: ATmega328P ADC help
« Reply #5 on: November 11, 2017, 02:55:52 pm »
Have you missed to include interrupt subroutine?

That is where a portion of application code resides. Those are left out intentionally.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: ATmega328P ADC help
« Reply #6 on: November 11, 2017, 02:58:53 pm »
_BV(ADPS1) | _BV(ADPS0);

Implies the system clock is only 1.6Mhz.

Should ADIF be ADIE.
I have a 8MHz clock. Changed the clock divider to ck/64 (125kHz at 8MHz system clock) but still no luck.

I have set both ADIF and ADIE, set ADIF to clear it, set ADIE to enable the interrupt.
 

Online MasterT

  • Frequent Contributor
  • **
  • Posts: 785
  • Country: ca
Re: ATmega328P ADC help
« Reply #7 on: November 11, 2017, 03:27:57 pm »
Have you missed to include interrupt subroutine?

That is where a portion of application code resides. Those are left out intentionally.
How we supposed to know your spelling is correct?
ISR(ADC_vect) {
 }
And what makes you think it's not fired?
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: ATmega328P ADC help
« Reply #8 on: November 11, 2017, 03:45:03 pm »
Have you missed to include interrupt subroutine?

That is where a portion of application code resides. Those are left out intentionally.
How we supposed to know your spelling is correct?
ISR(ADC_vect) {
 }
And what makes you think it's not fired?
I have no compiler warning or error with -Wall, which makes me believe that my spelling is correct. Missed typings on function prototype will lead to a compiler warning.

I have a breakpoint on this function (I am debugging through an Atmel ICE) but the it is not hit.
 

Offline HwAoRrDk

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: ATmega328P ADC help
« Reply #9 on: November 11, 2017, 04:12:04 pm »
Interrupts still globally turned off? I.e., have you forgotten sei()?

Sigh, been there. I once spent the better part of an entire day banging my head against the wall trying to figure out what was going on before I realised.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: ATmega328P ADC help
« Reply #10 on: November 11, 2017, 04:41:10 pm »
Try this:
Code: [Select]
ISR(ADC_vect)
{
    // turn on LED here. Never turn it off, so you can see if this ever fires
}

main()
{
    // turn on LED here to test it works
   delay_ms(500);
   // turn off LED here
   delay_ms(500);

   ADMUX = 0; // should be irrelevant to this problem
   // Magical code lines copypasted from some of my old random project, which works, runs ADC (ATMega640) in continuous mode and gives interrupts:
   ADCSRB = 0b00000000; // free running mode
   ADCSRA = 0b11101110; // prescaler = 64: auto trigger.

   // and...
   sei();
   while(1);

}


If this works, just compare what's different between this and yours.
 

Offline georges80

  • Frequent Contributor
  • **
  • Posts: 912
  • Country: us
Re: ATmega328P ADC help
« Reply #11 on: November 11, 2017, 06:13:08 pm »
We assume you haven't powered down the ADC via the PRR0 register.

Besides... You have set the auto trigger bits to free running (000). From the datasheet:

If ADATE in ADCSRA is written to one, the value of these bits selects which source will trigger an ADC
conversion. If ADATE is cleared, the ADTS[2:0] settings will have no effect. A conversion will be triggered
by the rising edge of the selected Interrupt Flag. 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. Switching to Free Running mode (ADTS[2:0]=0) will not cause a trigger
event, even if the ADC Interrupt Flag is set.
Table 29-6 ADC Auto Trigger Source Selection
ADTS[2:0] Trigger Source
000 Free Running mode
001 Analog Comparator
010 External Interrupt Request 0
011 Timer/Counter0 Compare Match A
100 Timer/Counter0 Overflow
101 Timer/Counter1 Compare Match B
110 Timer/Counter1 Overflow
111 Timer/Counter1 Capture Event

Hint: Seems to imply that no trigger even will occur in free running mode... No trigger event means a new conversion won't be initiated.

cheers,
george.
« Last Edit: November 11, 2017, 06:18:49 pm by georges80 »
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: ATmega328P ADC help
« Reply #12 on: November 11, 2017, 06:47:24 pm »
Try this:
Code: [Select]
ISR(ADC_vect)
{
    // turn on LED here. Never turn it off, so you can see if this ever fires
}

main()
{
    // turn on LED here to test it works
   delay_ms(500);
   // turn off LED here
   delay_ms(500);

   ADMUX = 0; // should be irrelevant to this problem
   // Magical code lines copypasted from some of my old random project, which works, runs ADC (ATMega640) in continuous mode and gives interrupts:
   ADCSRB = 0b00000000; // free running mode
   ADCSRA = 0b11101110; // prescaler = 64: auto trigger.

   // and...
   sei();
   while(1);

}


If this works, just compare what's different between this and yours.
Not working...

We assume you haven't powered down the ADC via the PRR0 register.

Besides... You have set the auto trigger bits to free running (000). From the datasheet:

If ADATE in ADCSRA is written to one, the value of these bits selects which source will trigger an ADC
conversion. If ADATE is cleared, the ADTS[2:0] settings will have no effect. A conversion will be triggered
by the rising edge of the selected Interrupt Flag. 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. Switching to Free Running mode (ADTS[2:0]=0) will not cause a trigger
event, even if the ADC Interrupt Flag is set.
Table 29-6 ADC Auto Trigger Source Selection
ADTS[2:0] Trigger Source
000 Free Running mode
001 Analog Comparator
010 External Interrupt Request 0
011 Timer/Counter0 Compare Match A
100 Timer/Counter0 Overflow
101 Timer/Counter1 Compare Match B
110 Timer/Counter1 Overflow
111 Timer/Counter1 Capture Event

Hint: Seems to imply that no trigger even will occur in free running mode... No trigger event means a new conversion won't be initiated.

cheers,
george.

I have tried to sort-of emulate continuous mode by not setting ADATE in adc_init, but set ADSC in the end of the ADC interrupt. No luck either, there isn't even an initial conversion.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: ATmega328P ADC help
« Reply #13 on: November 11, 2017, 10:13:47 pm »
Look at the ADC flag register, and the conversion result register - are the flags/value updating? What do the flags say? This way you can rule out either one:
1) ADC not enabled at all, or not triggering
2) ADC converting, but interrupt not firing

If case 2, can you set a breakpoint in the interrupt vector table - or at least take a look at the binary? That would verify there is no issue in the jump table generation. (If I remember the AVR architecture correctly.)
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: ATmega328P ADC help
« Reply #14 on: November 11, 2017, 10:34:11 pm »
Have you tried single shot first? It would narrow down possibilities.

For example, try this oneliner if you like to try random things by magic number copypasting ::):

// ADCSRB = 0 as reset value
sei();
ADCSRA = 0b11001110;
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf