Trouble timing how long a value is greater than 0

Hello everybody,

I've been trying to time how long a value is greater than 0 in micros().

I haven't had any luck with the pulseIn() function so what I'm doing is reading the micros() time when the sensor value exceeds 0, and then I take another reading when the value drops back to 0.
Once I have the time when the spike started and when it ended. Then I can just subtract the time of when the spike started from the when it ended.

The problem I'm having is the serial monitor prints second time as if the first time reading was 0 even though I have an if() statement saying that if the value of the first reading is 0 then the total time (second reading) is 0 instead of the current micros() time.

Please delete the screenshot and copy/paste the code in using code tags (<code/> post editor button)

Nothing . . . except fritzing.

2 Likes
int Sensor = A0;
  unsigned long Start_Time;
  unsigned long Total_Time;
  unsigned long Sprite_Time;
void setup() {
  Serial.begin(2000000);
  pinMode(Sensor,INPUT);
}
void loop() {
  int X = 0;
  int SensorVal = analogRead(Sensor);
  while(SensorVal > 0){
    X = X + 1;  // The variable X is used to ensure that the time reading is only taken the first time through the while loop
    if(X == 1){
      Start_Time = micros();     // Read the microsecond time when the spike starts
    }else {
      delay(0);
    }
    if(analogRead(Sensor) == 0){  // If the value is no longer greater than 0 (the spike has ended) leave the while loop
      break;
    }
  }
  if(Start_Time > 0){     // If a reading was taken read the current microsecond time
    Total_Time = micros();
  }
  else {
    Total_Time = 0;
  }
  Sprite_Time = Total_Time - Start_Time;  // Find the difference between the two readings
  Serial.println(Sprite_Time); 
}

It seems you want to catch a spike only once.
If so, then you can do it all in setup().

Note that analogRead catches a spike of ~5mV, but is relatively slow (~0.1ms).

Try this.
Leo..

const byte sensorPin = A0;
unsigned long startTime, elapsedTime;

void setup() {
  Serial.begin(115200);
  while (!analogRead(sensorPin)); // wait for pulse
  startTime = micros(); // mark
  while (analogRead(sensorPin)); // wait for zero
  elapsedTime = micros() - startTime; // calculate
  Serial.print(elapsedTime);
  Serial.println(" microseconds");
}

void loop() {
}
1 Like

After 65535 iterations of this while loop, X will be 1 again, so this may give a wrong start time.
analogRead() takes about 110 µs on an Uno (if you're using another Arduino this may be different), so that will be an issue if your signal is longer than 7.2 seconds.

This also means your minimum resolution of timing is about 110 µs. That sounds like a very coarse resolution when you're looking at the duration of a signal in microseconds.

This is very sensitive to noise and inaccuracy of the ADC, it may vary 1-2 points between readings. Depending on the actual range of readings you get, it may be a good idea to set the threshold to 5.

Thanks your advice everyone!

I tried all of your ideas and everything is working great!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.