ADC sampling then pausing inside loop but it breaks out of loop

Hello,

I made a sketch to sample the ADC which is connected to an AC current sensor. My objective is to take 200 continuous samples, then pause for 3ms and then repeat 1000 times. While the program waits 3ms, it should not break out of this for loop:

for (int j = 0; j < 1000; j++)
  {
    analogSample();
  }

But this is my Serial Monitor output and it seems like during the 3ms waiting time, it is breaking out of the for loop. I enabled timestamp to check. I thought the for loop was blocking? So, this should not happen. I have a suspicion that the return statement might be to blame but i’m not sure what to replace it with.

21:31:18.211 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.211 -> Low current value alert!
21:31:18.277 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.277 -> Low current value alert!
21:31:18.310 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.310 -> Low current value alert!
21:31:18.343 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.343 -> Low current value alert!
21:31:18.409 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.409 -> Low current value alert!
21:31:18.442 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.442 -> Low current value alert!
21:31:18.508 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.002 V. Irms/A: 0.017 A.
21:31:18.508 -> Low current value alert!
21:31:18.546 -> Max value: 1024. Min value: 1024. VPP: 0.02 V. VRMS: 0.007 V. Irms/A: 0.069 A.
21:31:18.546 -> Low current value alert!
21:31:18.574 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.574 -> Low current value alert!
21:31:18.641 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.002 V. Irms/A: 0.017 A.
21:31:18.641 -> Low current value alert!
21:31:18.674 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.674 -> Low current value alert!
21:31:18.740 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.002 V. Irms/A: 0.017 A.
21:31:18.740 -> Low current value alert!
21:31:18.773 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.773 -> Low current value alert!
21:31:18.839 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.839 -> Low current value alert!
21:31:18.872 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.872 -> Low current value alert!
21:31:18.905 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.905 -> Low current value alert!
21:31:18.971 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:18.971 -> Low current value alert!
21:31:19.004 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.
21:31:19.004 -> Low current value alert!
21:31:19.038 -> Max value: 1024. Min value: 1024. VPP: 0.00 V. VRMS: 0.000 V. Irms/A: 0.000 A.

Here is my complete sketch:

/* 
 * ESP-01 ADC sampling (set number of samples in one shot and pause time)
*/

const int sensorPin = A0; // connected to ADC pin of ESP-01

#define NUMBER_OF_SAMPLES 5000  // maximum number of samples taken
long samples[NUMBER_OF_SAMPLES]; // declare maximum size of array
int numberOfSamples = 200; // number of samples taken in a single shoot
unsigned long samplingTime;  // a variable value that stores the time in us to collect the numberOfSamples
int samplingPause = 3; // time in ms to pause between continuous sampling

unsigned long millisLastSample;
unsigned long showResultsTimer;

int maxValue = 0; // to store max value, initialised at lowest value.
int minValue = 1024; // to store min value, initialised at highest value.

const int mVperAmp = 100; // Output sensitivity in mV per Amp
// Use scale factor: 185 for 5A module, 100 for 20A module and 66 for 30A module

float VPP = 0.0; // peak-to-peak voltage
float VRMS = 0.0;  // RMS voltage
float IRMS = 0.0; // RMS current

float VRMSoffset = 0.0; //0.025; // set quiescent Vrms output voltage
//voltage at an output terminal with reference to a common terminal, normally ground,
//when no signal is applied to the input.

void analogSample(void)
{
  // check sampling pause time
  //if true, then escape from the analogSample function
  //else, proceed to sampling
  if (millis() - samplingPause < millisLastSample )
  {
    return; // could this be the culprit??
  }
  // start sampling
  //samplingTime = micros();
  for (int i = 0; i < numberOfSamples; i++)
  {
    samples[i] = analogRead(sensorPin);
    
    // check if there is a new maximum and minimum value
    if (samples[i] > maxValue)
    {
      // record the new maximum sensor value
      maxValue = samples[i];
    }
    if (samples[i] < minValue)
    {
      // record the new minimum sensor value
      minValue = samples[i];
    }
  }
  //samplingTime = micros() - samplingTime; // not needed but good to know.
  // end of sampling
  
  millisLastSample = millis(); // works together to set the sampling pause time
}
/*
void showResults(void)
{
  // show results every 5s
  if(millis() - 5000 > showResultsTimer)
  {
    showResultsTimer = millis();
    // show maximum and minimum analog values
    Serial.print("Max value: ");
    Serial.print(maxValue);
    Serial.print(". ");
    Serial.print("Min value: ");
    Serial.print(maxValue);
    Serial.print(". ");
    Serial.print("VPP: ");
    Serial.print(VPP);
    Serial.print(" V. ");
    Serial.print("VRMS: ");
    Serial.print(VRMS, 3);  // print to 3 decimal places
    Serial.print(" V. ");
    Serial.print("Irms/A: ");
    Serial.print(IRMS, 3);  // print to 3 decimal places
    Serial.println(" A.");
    // check threshold values
    if (IRMS <= 200)
    {
      Serial.println("Low current value alert!");
    }
    else if (IRMS >= 800)
    {
      Serial.println("High current value alert!");
    }
  }
}
*/
void showResults(void)
{
    // show maximum and minimum analog values
    Serial.print("Max value: ");
    Serial.print(maxValue);
    Serial.print(". ");
    Serial.print("Min value: ");
    Serial.print(maxValue);
    Serial.print(". ");
    Serial.print("VPP: ");
    Serial.print(VPP);
    Serial.print(" V. ");
    Serial.print("VRMS: ");
    Serial.print(VRMS, 3);  // print to 3 decimal places
    Serial.print(" V. ");
    Serial.print("Irms/A: ");
    Serial.print(IRMS, 3);  // print to 3 decimal places
    Serial.println(" A.");
    // check threshold values
    if (IRMS <= 1)
    {
      Serial.println("Low current value alert!");
    }
    else if (IRMS >= 5)
    {
      Serial.println("High current value alert!");
    }
}

void setup() 
{
  Serial.begin(115200); // Default Baud Rate for ESP-01
  pinMode(sensorPin, INPUT); // analog input
}

void loop() 
{
  // 1000 loops, each taking 200 continuous analog readings, then pausing for 3ms before taking another sample.
  // time taken is a bit more than 3ms x 1000 = 3000ms.
  for (int j = 0; j < 1000; j++)
  {
    analogSample();
  }
  // subtract min from max and convert range to volts
  VPP = ((maxValue - minValue) * 5.0) / 1024.0;
  VRMS = ((VPP / 2.0) * 0.707) - VRMSoffset; // divide by 2 to get peak voltage. 1 ÷ √(2) is 0.707
  IRMS = (VRMS * 1000.0) / mVperAmp; // first, multiply by 1000 to convert to mV
  //show immediate calculated value of IRMS
  showResults();
  //reset max and min values for next 1000 loops, each taking 200 samples.
  maxValue = 0; // to store max value, initialised at lowest value.
  minValue = 1024; // to store min value, initialised at highest value.
}

It’s not breaking out, it’s completing the for loop. It’s doing it sooner than you expect because of this:

  // check sampling pause time
  //if true, then escape from the analogSample function
  //else, proceed to sampling
  if (millis() - samplingPause < millisLastSample )
  {
    skipCount++;
    return; // could this be the culprit??
  }

If analogSample() is called and it hasn’t been more than 3 ms since the last sample, it just returns from the function immediately. So you’re zipping right through for for loop in loop() without getting many readings. When I run your code on my Mega, I only get readings 1 or 2 times out of every thousand calls of analogSample().