Storing adc value in memory

Greetings

I’m setting up the ADC of the atmel 326 in autotrigger mode, triggered by timer 0. I’m toggling pin6 when the T0 interrupts, and pin2 when the ADC interrupts (so when it’s done converting).

#include <Arduino.h>

#define WINDOW_LENGTH 5000

uint16_t index;
uint16_t table[WINDOW_LENGTH];
uint16_t analog_value;


void set_ADC_channel(uint8_t channel) {

    ADMUX = (ADMUX & 0xF0)|                 //safety mask
            (channel & 0x0F);               //set ADC channel

}

void init_ADC(void) {

    ADMUX = 0;
    ADMUX |= (1 << REFS0);                  //AVcc voltage reference
    set_ADC_channel(0);

    ADCSRA = 0;
    ADCSRA |= (1 << ADATE)|                 //auto trigger enable
            (1 << ADIE)|                    //ADC interrupt enable
            (1 << ADPS2)|                   //ADC prescaler = 128 -> 125kHz
            (1 << ADPS1)|
            (1 << ADPS0);

    ADCSRB = 0;
    ADCSRB |= (1 << ADTS1)|                 //set ADC trigger source to T0 compare match
            (1 << ADTS0);

}

void enable_ADC(void) {

    ADCSRA |= 1 << ADEN;                    //enable ADC

}


void init_T0(void) {

    //set timer0 interrupt at 2kHz
    TCCR0A = 0;                             //T0 control register
    TCCR0B = 0;
    TCNT0 = 0;                              //init counter value to 0
    TCCR0B |= (1 << CS01)|                  //set 64 prescaler
            (1 << CS00);
    OCR0A = 124;                            //set compare match register = 16e6 / (2e3*64) - 1
    TCCR0A |= (1 << COM0A0)|                //toggle PD6/OC0A pin on compare match
            (1 << WGM01);                   //turn on CTC mode

}

void enable_T0(void) {

    TIMSK0 |= (1 << OCIE0A);                //enable T0 interrupt

}

void setup() {

    DDRD |= (1 << PD2)|(1 << PD6);          //set PD2 and PD6 as output

    Serial.begin(9600);

    index = 0;

    cli();                                  //stop interrupts

    init_ADC();
    enable_ADC();

    init_T0();
    enable_T0();

    sei();                                  //enable interrupts

}

void loop() {


}


ISR(TIMER0_COMPA_vect){

}


ISR(ADC_vect) {

    if (index < WINDOW_LENGTH) {
        TIFR0 |= (1 << OCF0A);                   //clear timer compare match flag
        PIND = (1 << PD2);                      //toggle pin PD2

        uint8_t val_8bit = ADCL;

        analog_value = val_8bit | (ADCH << 8);      //read analog value

        //table[index] = analog_value;

        ++index;

    }

}

The code above works, I see the led6 always burning, and led2 for a couple of seconds. But when I add “table[index] = analog_value;” in the ADC interrupt handler to store the value in the memory for later processing, led6 and led2 doesn’t burn, not at all.

How is that? It’s wierd that adding that line, not only the ADC interrupt gets broken but also the T0 interrupt.

Also, I found that I needed to include the empty T0 interrupt in my code for the ADC to work. I find this strange as I thought that the ADC gets triggered by the rising/falling edge of the T0 interrupt signal and that that happened by HW by default whether I included it in SW or not.

Thanks

I guess you mean an ATMega328P.

You're creating a 10,000 byte array in a chip with only 2,048 bytes of SRAM.

#define WINDOW_LENGTH 5000
.
uint16_t table[WINDOW_LENGTH];

You probably need to declare them volatile.

KeithRB: You probably need to declare them volatile imaginary

:facepalm:

Ofcourse this is it. I forgot the limited space on the µcontroller

Speklap: :facepalm:

Ofcourse this is it. I forgot the limited space on the µcontroller

Sorry for throwing a spanner in the works. :(

OldSteve: Sorry for throwing a spanner in the works. :(

No worries, the table doesn't have to be that big anyways, it will be used as buffer. The size was just to see the leds burning long enough, I have lowered the sample speed now :)

Can be closed.