help understand code for fast analogread

hi to all,

try to understand this code :

const byte adcPin = 0;  // A0
const int MAX_RESULTS = 256;
volatile int results [MAX_RESULTS];
volatile int resultNumber;

// ADC complete ISR
ISR (ADC_vect)
  {
  if (resultNumber >= MAX_RESULTS)
    ADCSRA = 0;  // turn off ADC
  else
    results [resultNumber++] = ADC;
  }  // end of ADC_vect
  
EMPTY_INTERRUPT (TIMER1_COMPB_vect);
 
void setup ()
  {
  Serial.begin(115200); // set baudrate
  Serial.println();
  pinMode(5, OUTPUT); 
  
  // reset Timer 1
  TCCR1A  = 0;
  TCCR1B  = 0;
  TCNT1   = 0;
  TCCR1B  = bit (CS11) | bit (WGM12);  // CTC, prescaler of 8
  TIMSK1  = bit (OCIE1B); 
  OCR1A   = 39;    
  OCR1B   = 39; // 20 uS - sampling frequency 50 kHz

  ADCSRA  =  bit (ADEN) | bit (ADIE) | bit (ADIF); // turn ADC on, want interrupt on completion
  ADCSRA |= bit (ADPS2);  // Prescaler of 16
  ADMUX   = bit (REFS0) | (adcPin & 7);
  ADCSRB  = bit (ADTS0) | bit (ADTS2);  // Timer/Counter1 Compare Match B
  ADCSRA |= bit (ADATE);   // turn on automatic triggering
}

void loop () {
  digitalWrite(5, HIGH);
  while (resultNumber < MAX_RESULTS) { }
    
  for (int i = 0; i < MAX_RESULTS; i++)
  {
    
    Serial.println (results [i]);
  }
  digitalWrite(5, LOW);
  resultNumber = 0; // reset counter
  ADCSRA =  bit (ADEN) | bit (ADIE) | bit (ADIF)| bit (ADPS2) | bit (ADATE); // turn ADC ON
  
}

actualy trying to include in my code for current mesurement in 40ms time ,the main question is how ADC read is triggered in this code?
i would like to trigger it at certain point if possible.
thanks

Have you read the relevant sections of the datasheet about ADC triggering (§23.3, for example)?

Pieter

This will be a problem:

while (resultNumber < MAX_RESULTS) { }

resultNumber is modified by the ISR. However, it is multi-byte and access to it will be non-atomic in the non-ISR loop() code.

Thanks for help.
i fouand solution ,turning off ADC ,

ADCSRA = 0;  // turn off ADC

when needed trigger via turning on

ADCSRA =  bit (ADEN) | bit (ADIE) | bit (ADIF)| bit (ADPS2) | bit (ADATE); // turn ADC ON

hope that could help

Did you fix the issue in Reply #2? If not, you will get intermittent failures that are very difficult to debug.

gfvalvo:
Did you fix the issue in Reply #2? If not, you will get intermittent failures that are very difficult to debug.

I doubt he'll encounter any problems if he keeps MAX_RESULTS = 256; :slight_smile:

You're absolutely right of course, you shouldn't rely on luck like this, multi-byte variables that are written to inside of an ISR should be accessed in a critical section in your main program.

So far the code run with no issues otherwise MAX_RESULTS is 1 byte array i think it shouldn't be issue ,my be i may use volatile variable type?

resultNumber is an int, which is 2 bytes on AVR. You need a critical section: disable interrupts, copy the value to a temporary variable, enable interrupts. Volatile alone is not enough, it doesn't guarantee atomic access, it just causes the compiler to load the value from memory each time rather than caching it in a register, and it prevents some optimizations.