arduino program to measure time interval between two peaks

Hai friends,

I am working on PPG so as a part of it I need to find the interval between the sinusoidal waveform.
I have been trying to find the time intervals between peaks of sinusoidal wave and the code is provided below, when I run the code it shows the value as 4294925424. Someone please sort the mistake in my code!!!

testedarduinocodeforppg.ino (1.03 KB)

int count = 0; Should be unsigned, maybe even unsigned long .

Hello Larry,

I have changed the count to unsigned and even unsigned long but it shows the same (2^32)-1 value.

Prior I wish to know whether my program logic correct.

Thank you Larry,

Is the sine wave offset so it stays between 0 and 5 volts? .

To Larry:

Yes I provided the offset and it stays between 0 to 5v

  • Put some in comments so we can following your thinking.
  • Press CTRL T to format your code.
  • To get help, you must show us your complete sketch. Attach your code using the </> icon on the left side of the posting menu.

EDIT:
What is the frequency range?
You know this would be so much simpler if you squared the sine wave off and did this digitally :wink:

else if (now == prev)
this may never happen or take a very long time.
.

Larry I didn't get you so I have posted the whole code, sorry if it annoys you and the frequency ranges from 0.5-5Hz.

int ain = A2;            //Analog pin to read signals
int now = 0;            //checks current status of analog pin 2
int prev= 0;            //checks previous state
unsigned long count = 0;

unsigned long firstpulse = 0;
unsigned long totaltime = 0;
unsigned long lastpulse = 0;


void setup() {
  // put your setup code here, to run once:
  pinMode(ain,INPUT);
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  now = analogRead(ain);
  delay(100);
  if(now!=prev) 
  {
    if( now >= prev) 
    {
       prev = now;
       Serial.println("Current value is greater than previous value"); 
    }
    
    else
    {
    if(count == 0)
    {
      firstpulse = millis();
      count += 1;
    }

    else if(count >= 1)
    {
      count += 1;
      lastpulse = millis();
    }
    }
  }
  else if (now == prev)
  {
    Serial.println(lastpulse - firstpulse);
    Serial.print("----->Count:");
    Serial.print(count);
    Serial.println("--------------");
    firstpulse = lastpulse;
    lastpulse = 0; 
    count = 0;
  }
}

Is there a reason why you are doing the calculation using an analog input. You could square the waveform and do the calculation on a digital input. Which is easier.

Comments help us follow your thought process, example:

//have we reached a maximum level? if( now >= prev) {

For two analog readings to be the same, may take a very long time as there is input noise, time delays in your program and input fluctuations. (you may miss several/numerous cycles til you reach the same levels)

What are you thinking is happening here? else if (now == prev)

:sleeping: Time

This isn’t what you want but might give you some ideas:

int analogInput = A0;            
int thisReading = 0;    

byte hysteresis = 10;
byte flag = 0;

unsigned long startMicros = 0;
unsigned long lastPeakMicros = 0;

void setup() 
{
  // put your setup code here, to run once:
  pinMode(analogInput,INPUT);
  Serial.begin(115200);
  
  //Debug
  pinMode(13,OUTPUT);

} //END of setup()

void loop() 
{
  thisReading = analogRead(analogInput);

  //Debug
  if(thisReading >= 512 + hysteresis)
  {
    digitalWrite(13,LOW); //Turn on LED
  }
  else if(thisReading <= 512 - hysteresis)
  {
    digitalWrite(13,HIGH); //Turn off LED
  }
  //End of debug

  //have we gone above 512
  if(flag == 0 && thisReading >= 512 + hysteresis) 
  {
    flag = 1;
    //record this time
    startMicros = micros();    
  }

  //have we gone below 512
  if(flag == 1 && thisReading < 512 - hysteresis)
  {
    //Print the time it took form 512+hys to 512-hys
    Serial.print("It took " );
    Serial.print(micros() - startMicros);
    Serial.println(" micro seconds for 1/2 cycle." );
    flag = 0;
  } 
} //END of loop()

If the sine wave signal is regular (ie not frequency modulated) and you are simply trying to determine the frequency, you can simply do this with a digital pin and an interrupt.
The interrupt service routine, which is triggered by a status change on the digital pin, simply counts the number of times it is triggered (once per zero crossing) in a unit time.
As is clear also from Larryd’s code, your use of millis() (milliseconds) to measure time intervals in a 5KHz signal is too rough to yield usable results.