ROBOTIS-GIT / OpenCR

Software for ROS Embedded board (a.k.a. OpenCR). OpenCR means Open-source Control Module for ROS.
Apache License 2.0
383 stars 238 forks source link

OpenCr 1.0 HC-SR04 Sonar (NewPing) issue #291

Open usaotearoa opened 2 years ago

usaotearoa commented 2 years ago

Good day everyone,

I have been working on implementing Ultrasonic sensors with my OpenCR board and have found the issue liste below, where users have explored different approaches. However, no detais have been made available. (ultrasonic sensor hc-sr04) TRIG and ECHO individual pins, not shared

The wiring has been verified with a single "stand-alone" test sketch from the examples. And it works flawlessly and very accurate readings

I have followed some of the advise / approaches outlined in https://github.com/ROBOTIS-GIT/OpenCR/issues/233

The example using the original approach by lslabon has worked, but created very unreliable results, where the reading jumps sporadically between values in the range of +/- 20cm.

The second approach taken, was using the NewPing.h/NewPing.cpp library. But even with this library I noticed issues, despite a (blieved to be) proper implementation.

What I have noticed is that in "NewPing.cpp" function "unsigned long NewPing::ping_cm(unsigned int max_cm_distance)" calls the NewPing::ping(max_cm_distance) function, which always aborts right at the beginning, when invoking if (!ping_trigger()) returning "NO_ECHO"

unsigned int NewPing::ping(unsigned int max_cm_distance) {
    if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance.

    if (!ping_trigger())
    {
        return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function.

    }

#if URM37_ENABLED == true
    #if DO_BITWISE == true
        while (!(*_echoInput & _echoBit))             // Wait for the ping echo.
    #else
        while (!digitalRead(_echoPin))                // Wait for the ping echo.
    #endif
            if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
#else
    #if DO_BITWISE == true
        while (*_echoInput & _echoBit)                // Wait for the ping echo.
    #else
        while (digitalRead(_echoPin))                 // Wait for the ping echo.
    #endif
            if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
#endif

    return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead.
}

Below part of the pin_trigger function

digitalWrite(_triggerPin, LOW);   // Set the trigger pin low, should already be low, but this will make sure it is.
    delayMicroseconds(4);             // Wait for pin to go low.
    digitalWrite(_triggerPin, HIGH);  // Set trigger pin high, this tells the sensor to send out a ping.
    delayMicroseconds(10);            // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS.
    digitalWrite(_triggerPin, LOW);   // Set trigger pin back to low.

    #if ONE_PIN_ENABLED == true
        pinMode(_triggerPin, INPUT);  // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin).
    #endif

    #if URM37_ENABLED == true
        if (!digitalRead(_echoPin)) return false;               // Previous ping hasn't finished, abort.
        _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
        while (digitalRead(_echoPin))                           // Wait for ping to start.
            if (micros() > _max_time) return false;             // Took too long to start, abort.
    #else
        if (digitalRead(_echoPin)) return false;                // Previous ping hasn't finished, abort.
        _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
        while (!digitalRead(_echoPin))                          // Wait for ping to start.
            if (micros() > _max_time) return false;             // Took too long to start, abort.
    #endif

Here the part where the code aborts:

if (digitalRead(_echoPin)) return false;                // Previous ping hasn't finished, abort.
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)

This is where I believe the code breaks (aka aborts) due to previous ping not finished. however, I looked at the interval the

void Turtlebot3Sensor::updateSonar1(uint32_t t) float Turtlebot3Sensor::getSonarData(void)

are triggered and first noticed that updateSonar was called repeatedly in short intervals (<<100ms) So I increased the amount of time between the calls, as I thought this is the casue of the problem and now it still doesn't work.

These specs are set:

URM37_ENABLED = false
DO_BITWISE = false
ONE_PIN_ENABLED = false

Did anyone get the NewPing.h to work properly and if so, would you mind sharing your implementation please? As mentioned, using the conventional message returns unreliable results and therefore can not be uses.

Thanks.