0

I am using below code to get the distance from an ultrasonic sensor.

when the sensor is pointed to the wall with no change in its position, after some correct values some incorrect values will show up.

what might be the cause? how can i handle it?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <wiringPi.h>


#define NO_ECHO 0
#define MAX_DISTANCE 300 
#define PING_INTERVAL 100 
#define US_ROUNDTRIP_CM 57 

unsigned long ping(int8_t GPIO_Signal_Pin,float temp,int max_cm_distance)
{
    unsigned long _max_time;    //max time to wait for echo
    float _sound_speed; //sound speed based on the current temprature
    unsigned long _start_time;  //ping start time
    unsigned long _end_time;    //ping end time
    unsigned int _maxEchoTime;  //
    unsigned long _time;    //ping time
    unsigned long _distance;    //calculated distance

    _maxEchoTime = max_cm_distance * US_ROUNDTRIP_CM;
    _sound_speed = 331.4 + (0.6 * temp); // sound speed relevant to the temprature

    pinMode(GPIO_Signal_Pin,OUTPUT); //Set the signal pin to output

    digitalWrite(GPIO_Signal_Pin, LOW); //Make sure the module is not outputting
    delay(4); //4ms delay to allow the module to settle

    digitalWrite(GPIO_Signal_Pin,HIGH); //Send a 10us pulse to trigger
    delayMicroseconds (10);
    digitalWrite(GPIO_Signal_Pin,LOW);

    pinMode(GPIO_Signal_Pin,INPUT); //Set the signal pin to input

    _max_time = micros() + _maxEchoTime;

    while (digitalRead(GPIO_Signal_Pin) == 0)
    { 
        if (micros() < _max_time)
            continue; 
        else 
        {
            return NO_ECHO; 
            }
        }

    _start_time = micros();

    while (digitalRead(GPIO_Signal_Pin) == 1)
    { 
        continue;
        }

    _end_time = micros();

    _time = (_end_time - _start_time);      

    _distance =  ((_sound_speed * _time)/2)/10000;

    return _distance;
}

int main()
{
    /*Set up the Pi for GPIO*/
    wiringPiSetup ();

    unsigned long _pingTimer; // Holds the times when the next ping should happen
    _pingTimer = millis() + 75; // First ping starts at 75ms

    while(1)
    {
        if (millis() >= _pingTimer) { // Is it sensor's time to ping?
            _pingTimer += PING_INTERVAL;
            printf("Distance: %luCM\n", ping(0,22,300));
            printf("********************************\n\n");
            fflush( stdout );
        }
    }
}

Outpout:

Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 188CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 10CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 210CM
Distance: 262CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 245CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 137CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 174CM
Distance: 170CM
Distance: 191CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 211CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 248CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 263CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 265CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
Distance: 170CM
Distance: 171CM
  • 1
    Which sensor? That might matter. – Brick Aug 30 '17 at 12:08
  • do not use leading underscores in your variable names. The compiler uses such leading underscores (as does certain elements of the C language) – user3629249 Aug 30 '17 at 22:44
  • regarding: _sound_speed = 331.4 + (0.6 * temp); This is taking a float', multiplying it by a double, adding a double` and converting back to float. Suggest using: _sound_speed = 331.4f + (0.6f * temp); Notice the trailing f on each of the literals – user3629249 Aug 30 '17 at 22:50
  • the posted code seems to be confused about the timing of the pulses, some times saying 100msec intervals and some times saying 75msec intervals. – user3629249 Aug 30 '17 at 22:57
  • @user3629249 the first ping will happen in 75 ms others will be by 100 ms. – Mahdi Aug 31 '17 at 17:52
2

One possible problem, Linux is not an RTOS

It seems you're programming a RPi, which is most likely running some form of Linux kernel. Since the Linux kernel is not a Real Time Operating System, it is possible that your process which counts the time is preempted by another task running on your machine (like dealing with Ethernet packets, updating the display, ...). So counting time elapsed using the CPU is not really reliable.

Other sources of problems Since you're interfacing with the real world, this time with ultrasounds, you will face some inaccuracies. For instance, your ultrasound sensor can trigger if there is some sound around it, for instance a radio or a door slamming.

Since you cannot make the world perfect, you're forced to play with it, and therefore, you should not trust a single measure.

Solutions

  • If the problem is unlikely, compare two (or more) consecutive measures and ignore them if they are two dissimilar.
  • You could also discard a measure if you know the speed of the object and the distance do not match the speed.
  • You can also discard outliers.
  • i suppose i need to store multiple values and do some logical analysis and select the most probable value. i will try your solution and feed back – Mahdi Sep 1 '17 at 5:47
  • as advised by compared three consecutive values and checking it, can detect and ignore the flickers. – Mahdi Sep 3 '17 at 15:16
2

You are running under the Linux operating system which will every now and then swap out your program at an inconvenient time. That will corrupt the timings if a reading has just been triggered.

You could give your program real-time priority which would probably help.

For details see

man sched_setscheduler

You would probably get better results if you use pigpio callbacks which do not suffer this problem as the timing is handled by the Pi hardware.

A Python example.

Other examples including C.

  • i will try pigpio, but not sure if it supports one pin both for trigger and echo or not! – Mahdi Sep 1 '17 at 5:30
  • @Mahdi No, the examples do not. They would need updating to use a pigpio script to make that work efficiently, and that requires moderate to good programming skills. – joan Sep 1 '17 at 6:45
0

this code, from the OPs posted code:

while(1)
{
    if (millis() >= _pingTimer) { // Is it sensor's time to ping?
        _pingTimer += PING_INTERVAL;
        printf("Distance: %luCM\n", ping(0,22,300));
        printf("********************************\n\n");
        fflush( stdout );
    }
}

will NOT give the desired intervals between pings.

Suggest something similar to:

while(1)
{
    while(millis() >= _pingTimer);  // wait for interval between pings to expire

    // set end time for next interval
    _pingTimer += PING_INTERVAL;  // 100msec increment

    printf("Distance: %luCM\n", ping(0,22,300));
    printf("********************************\n\n");
}

There is also the consideration of the minimum distance above the floor. If the sensor is too close to the floor, for the distances being measured, then echo's from the floor can trigger the sensor.

  • the sensor is pointing to the wall, the distance is not too close, i also tried using WHILE instead of IF, no difference. – Mahdi Sep 1 '17 at 5:46
  • So the sensor is pointed at the wall. HOW FAR IS THE SENSOR ABOVE THE FLOOR? The sound/ping has (a lot) of scatter, So the sensor will receive echo's from surrounding objects, like the floor – user3629249 Sep 1 '17 at 15:43
  • Notice the suggested code sits in a inner 'while()' loop doing nothing until the desired interval between 'ping' events has expired (which the OPs code did not wait) then immediately updates the time for the next 'ping' event, then performs 'this' ping event. – user3629249 Sep 1 '17 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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