0

Good day

I am trying to sample distance using a sonar/ultrasonic sensor for altitude measurement. When the PWM is not active, the sensor gives accurate measurements in centimeters, however with the PWM active, the sensors outputs unrealistic measurements. I have seen other having issues with the arduino platform and have resolved this issue by decoupling the supply of the sensor with an electrolytic capacitor. However this does not resolve the issue and upon closer inspection, with the PWM active, the measured pulse/echo is wrong. Is this an issue with the sonar and PWM fighting over the raspi's timer?

Is there anyway to fix this?

I have been trying to debug this problem for 3 days now. I tried using the wiring-pi library and the pigpio library but both have the same problem.

This is an example code with the same issue:

int main(int argc, char** argv){

        //Sonar Sensor Initialize LOW
        gpioInitialise(); //Initialize Wiring Pi using broadcom pin numbering
        gpioSetMode(27, PI_OUTPUT); //Set up gpio pins
        gpioSetMode(25, PI_INPUT);

        //Set-up PWM pins
        gpioSetMode(24, PI_OUTPUT);
        gpioSetMode(17, PI_OUTPUT);
        gpioSetMode(22, PI_OUTPUT);
        gpioSetMode(18, PI_OUTPUT);
        gpioSetPWMfrequency(24,400);
        gpioSetPWMfrequency(17,400);
        gpioSetPWMfrequency(22,400);
        gpioSetPWMfrequency(18,400);
        gpioPWM(24,113);  //1
        gpioPWM(17,113);  //2
        gpioPWM(22,113);  //3
        gpioPWM(18,113);  //4

        delay(30);


    while(1){ //While loop (pseudo pid control loop)
        //-------Poll Sensor-------
        //Start TRIG pulse HIGH
        gpioWrite(27, 1);
        delayMicroseconds(10);      
        gpioWrite(27, 0);

        while(gpioRead(25) == 0){};
        long timeInitial = micros(); //Get time since program started in microseconds
        while(gpioRead(25) == 1){};
        long timeEcho = micros() - timeInitial; 
        cout << "timeInitial = "<< (double)timeInitial << endl;
        cout << "timeEcho = "<< (double)timeEcho << endl;
        //Get distance in cm
        float altitude = timeEcho / 58.2;
        cout << "Altitude "<< altitude << endl;

        //-------"Update PWM"-------
        gpioPWM(24,155);  //1
        gpioPWM(17,155);  //2
        gpioPWM(22,155);  //3
        gpioPWM(18,155);  //4
        delay(50);
    }

        return 0;

}
3
  • PWM shouldn't affect wiringPi or pigpio. You will need to post your code. What PWM are you talking about?
    – joan
    Commented Mar 5, 2016 at 10:00
  • @joan I have updated the post with a sample code that has the same issue Commented Mar 5, 2016 at 10:24
  • @joan The code is like a pseudocode for a pid control loop for a quadcopter Commented Mar 5, 2016 at 10:35

1 Answer 1

1

I do not see why that pigpio code would be affected by PWM. It would be affected by the system being busy - just like any other code would be.

For any serious timing purposes with pigpio you should be using callbacks. The callback will tell you when the GPIO changed state accurate to a few microseconds - regardless of the busyness of the system.

http://abyz.me.uk/rpi/pigpio/examples.html#pdif2_SRTED is an example of using callbacks with the pigpio daemon.

The following is an example of the sort of thing to do using the library directly. In this example the callback function is called sonarEcho, which simply times the difference between the echo going high then low.

#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);
   }
}
0

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.