5

The following code works with the busy wait, but if I replace the while loop with a call to wiringPiISR() it always returns 0 for the distance. I also tried calling wiringPiISR() before raising the trigger pin thinking that the echo pin might have already been raised HIGH before the callback was registered to handle it, but that didn't make a difference. Any idea what might be the problem?

#include <iostream>
#include <wiringPi.h>

#define GPIO22     3
#define GPIO23     4

using namespace std;

static int trigger = GPIO22;
static int echo = GPIO23;

static volatile long startTimeUsec;
static volatile long endTimeUsec;

void recordPulseLength (void) {
    startTimeUsec = micros();
    while ( digitalRead(echo) == HIGH );
    endTimeUsec = micros();
}


/**
 * Uses the HC SR04 ultrasonic sensor to measure distance. The HC SR04
 * provides 2cm to 400cm range measurement.
 */
int main()
{
    double speedOfSoundMetersPerSecond = 340.29;

    wiringPiSetup();

    pinMode(trigger, OUTPUT);
    pinMode(echo, INPUT);

    // Initialize the sensor's trigger pin to low. If we don't pause
    // after setting it to low, sometimes the sensor doesn't work right.
    digitalWrite(trigger, LOW);
    delay(500); // .5 seconds

    // Triggering the sensor for 10 microseconds will cause it to send out
    // 8 ultrasonic (40Khz) bursts and listen for the echos.
    digitalWrite(trigger, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigger, LOW);

    // The sensor will raise the echo pin high for the length of time that it took
    // the ultrasonic bursts to travel round trip.
    // Doesn't work; endTimeUsec and startTimeUsec are always the same.
    //wiringPiISR(echo, INT_EDGE_RISING, &recordPulseLength);
    while ( digitalRead(echo) == LOW);
    recordPulseLength();

    long travelTimeUsec = endTimeUsec - startTimeUsec;
    double distanceMeters = ((travelTimeUsec/1000000.0)*speedOfSoundMetersPerSecond)/2;

    cout << "Distance is " << distanceMeters*100 << " cm." << endl;

    return 0;
}
2
  • 1
    Presumably it takes too long to set up the callback. Why not set the callback up at the start of main(). However there is no guarantee that the callback will be actually called before the pulse is over. A busy wait is probably the best you will achieve with wiringPi.
    – joan
    Commented Aug 9, 2014 at 16:57
  • I did try moving it up to the beginning of main, but it didn't help. Commented Aug 9, 2014 at 17:21

1 Answer 1

1

Okay, I think the problem is that wiringPiISR() runs asynchronously. If I add a waiting loop that puts the main thread to sleep then checks if the distance has been recorded, then it works!

4
  • 1
    The overall result is the busy loop has moved and will be under recording the echo time.
    – joan
    Commented Aug 9, 2014 at 19:09
  • Can you recommend an approach to recording an accurate echo time without consuming CPU cycles in a busy loop? Commented Aug 10, 2014 at 15:52
  • I'd use my own pigpio library as its likely to give the most accurate and repeatable results. There is nothing wrong with busy loops if the software isn't going to be do something else, you'd just get more accurate results leaving the busy loop in-line rather than in the callback which adds another unknown. The callback on average will be called 430 micros after the rising edge so you could factor that in to your calculations.
    – joan
    Commented Aug 10, 2014 at 17:29
  • The easiest way to measure a SR04 is to record the time of rises and falls, constantly. The when you do a trigger, wait some time, it doesn't matter as long as its more than the max, and compare time of fall to time of rise. as long as fall > rise, it is good, pulse width (fall - rise) will be your echo value. joan's library seems to provide that kind of thing.
    – Spiked3
    Commented Apr 7, 2015 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.