Problem with microsecondsDelay when using analogRead

Hey guys,

I have recently started to get involved with Arduino boards and programming in general. For a school project, I am trying to design a sensor system with my Arduino Uno. Basically I have an analog sensor that I would like to read values from.

Part of the requirements is to have a system where the user can input the desired sampling frequency. My approach to this was to slow down the sampling by introducing delays to achieve the desired sampling frequency.

Ok, so this is the code that I am testing. I am reading 8000 data points with a given microsecond delay. I am measuring the total sampling time, then increasing the delay to measure again. At this point, I haven’t connected the sensor to my analog pin yet. However, the pin is connected to the 3.3V output to have a consistent value (around 1023*3.3/5 = 675) rather than having a floating pin.

Correspondingly, I can calculate the sampling frequency for each microsecond delay. The purpose of this test was to see how much control I would have over the sampling rate.

(fs = N/(t_total)*10^6 (Hz) where fs=sampling freq., t_total = total sampling time (us), N = number of samples=8000)

unsigned long timeStart = 0, timePassed = 0;
int voltage = 0;
int delayMics = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("Initializing...");
}

void loop() {
  delay(200);
  timeStart = micros();
  for (int i = 0; i < 8000; i ++) {
    voltage = analogRead(A1);
    delayMicroseconds(delayMics);
  }
  timePassed = micros();
  timePassed -= timeStart;
  Serial.print(timePassed);
  Serial.print(" ");
  delayMics ++;
}

I plotted the delays vs sampling frequencies. I understand that the delayMicrosecond function does not guarantee precise performance below 3 microseconds. However, this is still a very interesting result indeed. Basically, the delays are occuring in steps. For example, the program seems to have the same result for 16us delay and 22us delay, then there is a sudden jump.

This profile occurs from using the ADC together with the microsecondsDelay(). I have tested the delay function separately (commented out the analogRead) and obtained a linear profile.

I am really curious of the cause behind this. I understand that there is a fixed delay inherent in the analogRead function, but this still should no affect the code after it since for my script, delay is called after analogRead is completed. Has anyone encountered something similar?

(The link for the plot)

delay_ArduinoUno_forum.png

I understand that there is a fixed delay inherent in the analogRead function, but this still should no affect the code after it since for my script, delay is called after analogRead is completed.

Looked at another way the analogRead() is being called immediately after the delay because of the for loop.

As you do nothing with the result of the analogRead() are you sure that it is not being optimised away by the compiler ? What results do you get if you take it out of the code yourself ?

TOrcun: I am really curious of the cause behind this. I understand that there is a fixed delay inherent in the analogRead function,

No, the duration of analogRead() execution is not really "fixed", it is slightly variable.

There are always Ttimer0 interrupts active in the Arduino, Timer0 interrupts are firing roughly once per 1000µs (1ms) and the extra time for execution of the timer0 interrupt is roughly 4µs.

Normally, ececution time of analogRead() is roughly 120µs.

But in case a timer0 interrupt occurs during analog$Read, the execution time of analogRead will increase by another 4 microseconds.

UKHeliBob:
Looked at another way the analogRead() is being called immediately after the delay because of the for loop.

Yes that is a good point. I have tried adding another fixed delay before the sampling (4us), similar results.

UKHeliBob:
As you do nothing with the result of the analogRead() are you sure that it is not being optimised away by the compiler ?

In my original code I was actually storing the data in an SRAM. I got the same results with lower sampling frequency. I simplified the test to isolate the cause of the problem, resulting in with this script. So I would assume its not because the compiler is optimizing.

UKHeliBob:
What results do you get if you take it out of the code yourself ?

If I get rid of the analogread completely and just have the delays, i get a perfect linear profile. (Please refer to the attachment).

jurs:
No, the duration of analogRead() execution is not really “fixed”, it is slightly variable.

There are always Ttimer0 interrupts active in the Arduino, Timer0 interrupts are firing roughly once per 1000µs (1ms) and the extra time for execution of the timer0 interrupt is roughly 4µs.

Normally, execution time of analogRead() is roughly 120µs.

But in case a timer0 interrupt occurs during analog$Read, the execution time of analogRead will increase by another 4 microseconds.

Ok, I will look into how this timer0 interrupt works. Do you think that might affect the delays?

delay_ArduinoUno_forum_NO_ADC.png