1

As the title says, the distance in my sonar is giving me 0, I think I found out the problem, but the code was working fine with wiringPi.

Functions:

  • I only changed names to be equal to Arduino
  • digitalRead = gpioRead
  • digitalWrite = gpioWrite
  • delayMicroseconds = gpioDelay
  • micros = gpioTick

This function is in a class, so I'm copying what matters.

float distance()
    {
        static float old = 0.0;
        float duration = 0.0, distance = 0.0, threshold = 0.01;

        digitalWrite(TrigPin, LOW);
        delayMicroseconds(2);

        digitalWrite(TrigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(TrigPin, LOW);

        duration = pulseIn(EchoPin, HIGH);
        distance = (duration / 2.0) * 0.0343 / 100.0;

        if (old == 0.0 || (abs(distance - old) <= threshold))
            return old = distance;
        else
            return old;
    }

Here is where I think the problem is:

uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout = 1000000L);

uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout)
{
  uint32_t start = micros();
  while (digitalRead(pin) == state && (micros() - start) < timeout);
  while (digitalRead(pin) != state && (micros() - start) < timeout);
  start = micros();
  while (digitalRead(pin) == state && (micros() - start) < timeout);
  return micros() - start;
}

2 Answers 2

0

The pigpio sonar ranger example html is not displaying for reasons I don't understand.

However this is the code given in the example.

#include <stdio.h>

#include <pigpio.h>

/*

P1  Name  gpio    used for

 2  5V    ---     5V
 6  GND   ---     Ground
24  CE0   8       Sonar echo
26  CE1   7       Sonar trigger

*/

#define SONAR_TRIGGER 7
#define SONAR_ECHO    8

/* forward prototypes */

void sonarTrigger(void);

void sonarEcho(int gpio, int level, uint32_t tick);

int main(int argc, char *argv[])
{
   if (gpioInitialise()<0) return 1;

   gpioSetMode(SONAR_TRIGGER, PI_OUTPUT);
   gpioWrite  (SONAR_TRIGGER, PI_OFF);

   gpioSetMode(SONAR_ECHO,    PI_INPUT);

   /* update sonar 20 times a second, timer #0 */

   gpioSetTimerFunc(0, 50, sonarTrigger); /* every 50ms */

   /* monitor sonar echos */

   gpioSetAlertFunc(SONAR_ECHO, sonarEcho);

   while (1) sleep(1);

   gpioTerminate();

   return 0;
}

void sonarTrigger(void)
{
   /* trigger a sonar reading */

   gpioWrite(SONAR_TRIGGER, PI_ON);

   gpioDelay(10); /* 10us trigger pulse */

   gpioWrite(SONAR_TRIGGER, PI_OFF);
}

void sonarEcho(int gpio, int level, uint32_t tick)
{
   static uint32_t startTick, firstTick=0;

   int diffTick;

   if (!firstTick) firstTick = tick;

   if (level == PI_ON)
   {
      startTick = tick;
   }
   else if (level == PI_OFF)
   {
      diffTick = tick - startTick;

      printf("%u %u\n", tick-firstTick, diffTick);
   }
}
1
  • Thanks a lot for your help. Your code and the code I posted in the question works fine. The problem was, that I was testing the PWM with an LED and I had the Vcc connected to the LED pin and when I changed the circuit I forgot to change the Vcc to 5V, meaning the sensor was using 3.3V and because of it was returning 0. Dec 1, 2017 at 20:14
0

There are a working solution for the WiringPi library here.

In my opinion WiringPi was much easier. Sadly it is not supported anymore. But we can change a few things if we want to use pigpio:

pinmode(pin, OUTPUT);
pinmode(pin, INPUT);
digitalWrite(pin, LOW);
digitalWrite(pin, HIGH);
digitalRead(pin);

would become

gpioSetMode(pin, PI_OUTPUT);
gpioSetMode(pin, PI_INPUT);
gpioWrite(pin, PI_OFF);
gpioWrite(pin, PI_ON);
gpioRead(pin);

Important information from the documentation:

The level of a GPIO. Low or High.

PI_OFF 0
PI_ON 1

PI_CLEAR 0
PI_SET 1

PI_LOW 0
PI_HIGH 1

So as example PI_OFF, PI_CLEAR, PI_LOW or 0 are the same and PI_ON, PI_SET, PI_HIGH or 1 are also the same.

I have not tested the following, as I do not have an HC-SR04 at hand at the moment. The code from the question has an error with HIGH and LOW in my opinion, because this should be renamed to PI_HIGH and PI_LOW respectively. So it would be conceivable that the following could work:

float distance()
{
    static float old = 0.0;
    float duration = 0.0, distance = 0.0, threshold = 0.01;

    digitalWrite(TrigPin, PI_LOW);
    delayMicroseconds(2);

    digitalWrite(TrigPin, PI_HIGH);
    delayMicroseconds(10);
    digitalWrite(TrigPin, PI_LOW);

    duration = pulseIn(EchoPin, PI_HIGH);
    distance = (duration / 2.0) * 0.0343 / 100.0;

    if (old == 0.0 || (abs(distance - old) <= threshold))
        return old = distance;
    else
        return old;
}

Now I have pointed to a WiringPi solution. This I will now also present. I get new Raspberry Pi accessories at the end of the week, there is then also a HC-SR04, then I can verify my solution. The change looks like this:

libSonar.h

#ifndef DEF_SONAR
#define DEF_SONAR

class Sonar
{
  public:
    Sonar();
    void init(int trigger, int echo);
    double distance(int timeout);

  private:
    void recordPulseLength();
    int trigger;
    int echo;
    volatile long startTimeUsec;
    volatile long endTimeUsec;
    double distanceMeters;
    long travelTimeUsec;
    long now;
};

#endif

libSonar.cpp

#include <iostream>
#include <stdio.h>
#include <pigpio.h>
#include "libSonar.h"

Sonar::Sonar(){}

void Sonar::init(int trigger, int echo)
{
    this->trigger=trigger;
    this->echo=echo;
    gpioSetMode(trigger, PI_OUTPUT);
    gpioSetMode(echo, PI_INPUT);

    gpioWrite(trigger, PI_LOW);
    delay(500);
}

double Sonar::distance(int timeout)
{
    delay(10);

    gpioWrite(trigger, PI_HIGH);
    delayMicroseconds(10);
    gpioWrite(trigger, PI_LOW);

    now=micros();

    while (digitalRead(echo) == PI_LOW && micros()-now<timeout);
        recordPulseLength();

    travelTimeUsec = endTimeUsec - startTimeUsec;
    distanceMeters = 100*((travelTimeUsec/1000000.0)*340.29)/2;

    return distanceMeters;
}

void Sonar::recordPulseLength()
{
    startTimeUsec = micros();
    while ( digitalRead(echo) == PI_HIGH );
    endTimeUsec = micros();
}

libSonarSample.cpp

#include <iostream>
#include <stdio.h>
#include <pigpio.h>
#include "libSonar.h"

using namespace std;

int trigger = 1;
int echo = 0;

int main()
{
    if (gpioInitialise() == -1)
        return -1;

    Sonar sonar;
    sonar.init(trigger, echo);

    while(1){
        cout << "Distance is " << sonar.distance(30000) << " cm." << endl;
    }
}

I'm curious about that myself now. Accordingly I could translate some code from WiringPi to pgpio. Seems to be very easy.

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.