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.

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:

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

    else if(count >= 1)
      count += 1;
      lastpulse = millis();
  else if (now == prev)
    Serial.println(lastpulse - firstpulse);
    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:

} //END of setup()

void loop() 
  thisReading = analogRead(analogInput);

  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.