How to measure distance with the Parallax PING sensor

From ROBOTC API Guide
Jump to: navigation, search
ArduinoArduino Tutorials and Guided ProjectsParallax BoeBot + Arduino Shield, Mobile Robotics Platform → How to measure distance with the Parallax PING sensor

Notepad.gif NOTE: This is a place holder for a video.
Please add the id for the YouTube video with description "BoeBot measuring distance to an object using a PING sensor"

Overview

For sensors that return a range of values, we usually just want to check if the returned value is greater than, equal to, or less than a predetermined value (called a 'threshold'). For example, let's assume we want to keep a robot with a PING sensor at least 5 inches away from any objects. In a situation such as this we would only want to change the behavior of the robot when it senses something that is less that or equal to 7 in (the 5 in minimum plus a 2 in factor of safety).

To help demonstrate this principal, we are going to program the robot to display the 3 possible states through two LEDs.

Measurement LED 1 LED 2
> threshold ON OFF
= threshold ON ON
< threshold OFF ON

Wiring the LEDs

To wire one LED we need a 470Ω resistor and the LED. Since we need want to wire 2 LEDs, we will need 2 LEDs and 2 470Ω resistors. We will plug LED 1 into pin 5, and LED 2 into pin 6. Remember, LEDs have polarity and must be plugged in properly in order to function.

virtual breadboard
breadboard photo

Programming

Configuring the pins

First we need to tell ROBOTC that we have a Parallax Boe Shield connected. Then we need to configure ROBOTC for the following connections

  • LED to Vcc on digital pin 5, named "led1"
  • LED to Vcc on digital pin 6, named "led2"
  • SONAR [Ping] (inch) on digital pin 3, named "ping"

Once that has been done you should have the following in your source code file

#pragma config(CircuitBoardType, typeCktBoardUNO)
#pragma config(PluginCircuitBoard, typeShieldParallaxBoeBot)
#pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0)
#pragma config(Sensor, dgtl3,  ping,           sensorSONAR_Ping_inch)
#pragma config(Sensor, dgtl5,  led1,           sensorDigitalOut)
#pragma config(Sensor, dgtl6,  led2,           sensorDigitalOut)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

Reading the Sensor

Before we can move on we need to know how to read the value of the sensor. Just like with the switch sensors and the LEDs, you use SensorValue[] command to read the value. In this case it will be used as shown below.

SensorValue[ping];

Greater Than? Less Than?

We know how to get the reading from the sensor, but how do we check if it is greater or less than the threshold? If we go back to the section about dimming the LEDs, you will find that we used "<" to run the loop 10 times. This operator (the less than operator) can be used on any value. this operator is part of a larger set of operators called comparators, which can all be used to compare values.

Operator name description syntax example
"==" Equal to returns true if the value to the left of the operator is equal to the value to the right of the operator. 1 == 1
">" Greater Than returns true if the value to the left of the operator is greater than the value to the right of the operator. 5 > 4
">=" Greater Than or Equal to returns true if the value to the left of the operator is greater than or equal to the value to the right of the operator. 5 >= 5
"<" Less Than returns true if the value to the left of the operator is less than the value to the right of the operator. 3 < 4
"<=" or "=<" Less Than or Equal to returns true if the value to the left of the operator is greater than the value to the right of the operator. 4 <= 4

Writing the code

So now that we know how to read the sensor value and compare it to our threshold, we can finally start to write the code. First, let's look at how we will tell the LEDs to light up depending on the measured value.

Since we have more than 2 possible conditions, we would need to nest multiple if-else statements inside of each other. Fortunately, It ispossible to use something called an else-if statement to stay in one level. The else-if statements function the same as if you were to put the condition inside of an if statement that is nessted in the else code block of an if-else statement.

if (5 == 10) 
 {
  //the 10 must be of a different base
 } 
else 
 {
 if (1 == 1) 
  {
    //everything is good
  } 
 else 
  {
    //something unexpected is happening
  }
}
is equal to
if (5 == 10) 
 {
  //the 10 must be of a different base
 }
else if (1 == 1) 
 {
  //everything is good
 } 
else 
 {
  //something unexpected is happening
 }

First we'll create the code to decide what to run. Since we have 3 states, we need 3 if statements (which can be of the else-if form). Using else-if statements to make the code a little cleaner, we end up with the following.

if (SensorValue[ping] > threshold) 
{
  //led1 on and led2 off
} 
else if (SensorValue[ping] == threshold) 
{
  //both leds on
} 
else if (SensorValue[ping] < threshold) 
{
  //led1 off and led2 on
} 
else 
{
  //Something unexpected happened
  //Turn off both LEDs
}

Now that we have the decision code done, we need to add the action code. We just need to add the code to turn the LEDs on and off.

if (SensorValue[ping] > threshold) 
{
  //led1 on and led2 off
  SensorValue[led1] = 1;
  SensorValue[led2] = 0;
} 
else if (SensorValue[ping] == threshold) 
{
  //both leds on
  SensorValue[led1] = 1;
  SensorValue[led2] = 1;
} 
else if (SensorValue[ping] < threshold) 
{
  //led1 off and led2 on
  SensorValue[led1] = 0;
  SensorValue[led2] = 1;
}
else 
{
  //Something unexpected happened
  //Turn off both LEDs
  SensorValue[led1] = 0;
  SensorValue[led2] = 0;
}

If we place this as is in to a task main and run it, it would only last for a fraction of a second. Since we want to be able to see the changes, we need to place it in a endless while loop.

#pragma config(CircuitBoardType, typeCktBoardUNO)
#pragma config(PluginCircuitBoard, typeShieldParallaxBoeBot)
#pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0)
#pragma config(Sensor, dgtl3,  ping,           sensorSONAR_Ping_inch)
#pragma config(Sensor, dgtl5,  led1,           sensorDigitalOut)
#pragma config(Sensor, dgtl6,  led2,           sensorDigitalOut)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 
 
task main()
{
  while (true)
  {
    if (SensorValue[ping] > threshold) 
    {
      //led1 on and led2 off
      SensorValue[led1] = 1;
      SensorValue[led2] = 0;
    } 
    else if (SensorValue[ping] == threshold)  
    {
      //both leds on
      SensorValue[led1] = 1;
      SensorValue[led2] = 1;
    } 
    else if (SensorValue[ping] < threshold)  
    {
      //led1 off and led2 on
      SensorValue[led1] = 0;
      SensorValue[led2] = 1;
    } 
    else 
    {
      //Something unexpected happened
      //Turn off both LEDs
      SensorValue[led1] = 0;
      SensorValue[led2] = 0;
    }
  }
}

Since we know that the threshold that we are looking for is 7 inches, and the sensor is configured for inches, we can just replace "threshold" with 7.

#pragma config(CircuitBoardType, typeCktBoardUNO)
#pragma config(PluginCircuitBoard, typeShieldParallaxBoeBot)
#pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0)
#pragma config(Sensor, dgtl3,  ping,           sensorSONAR_Ping_inch)
#pragma config(Sensor, dgtl5,  led1,           sensorDigitalOut)
#pragma config(Sensor, dgtl6,  led2,           sensorDigitalOut)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 
 
task main()
{
  while (true)
  {
    if (SensorValue[ping] > 7) 
    {
      //led1 on and led2 off
      SensorValue[led1] = 1;
      SensorValue[led2] = 0;
    } 
    else if (SensorValue[ping] == 7) 
    {
      //both leds on
      SensorValue[led1] = 1;
      SensorValue[led2] = 1;
    } 
    else if (SensorValue[ping] < 7) 
    {
      //led1 off and led2 on
      SensorValue[led1] = 0;
      SensorValue[led2] = 1;
    } 
    else 
     {
      //Something unexpected happened
      //Turn off both LEDs
      SensorValue[led1] = 0;
      SensorValue[led2] = 0;
    }
  }
}