Using an ultrasonic sensor to measure distance

From ROBOTC API Guide
< Tutorials‎ | Arduino Projects/Mobile Robotics/VEX
Revision as of 19:57, 8 August 2012 by Dwest (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
ArduinoArduino Tutorials and Guided ProjectsVEX + Arduino, Mobile Robotics Platform → Using an ultrasonic sensor to measure distance

Notepad.gif TODO: insert video

Overview

For sensors like the VEX Ultrasonic sensor that return a range of values, we often simply want to check if the returned value is more than, equal to, or less than some value called a threshold. For example say that we have the sensor set up and are driving around, but we need to stay at least 5 inches (127 mm) away from any obstacles. In such a situation, we would only be changing the behavior of the robot when it senses something that is less that or equal to 7 inches (the 5 as 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 of the sensor (i.e less than threshold, equal to threshold, or greater than threshold). We'll use LED's to visually display the program state:

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

We are going to add 2 LEDs in the same manner we did in the flashing LEDs section.

Wiring the LEDs

Again, to wire up an LED we need a 470Ω resistor and an LED. In this case, since we want to wire up 2 LEDs, we will need 2 LEDs and 2 resistors. We will plug LED 1 into pin 5, and LED 2 into pin 6.

Virtual breadboard.
A view of the wiring.

Configuring RobotC

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

  • Digital Out on digital pin 5, named "led1"
  • Digital Out on digital pin 6, named "led2"
  • SONAR [SRP-04] (inch) on digital pin 7, named "ultrasonic".
    • RobotC will automatically assign the output pin to pin 8.

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

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

Programming

Reading the Sensor

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

SensorValue[ultrasonic];

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.

Notepad.gif TODO: add link to the details of the comparators.

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

Now that we know how to read the sensor value and compare it to our threshold, we can 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 is possible 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 nested 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 strange 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 strange is happening
}

First let's create the code to decide what to run. Since we have 3 solid states, we need 3 if statements (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[ultrasonic] > threshold) {
  //led1 on and led2 off
} else if (SensorValue[ultrasonic] == threshold) {
  //both leds on
} else if (SensorValue[ultrasonic] < threshold) {
  //led1 off and led2 on
} else {
  //something happened
  //we don't know what to do so
  //let's just turn off the LEDs
}

Now that we have the decision code done, we need to add the action code. So now we just need to add the code to turn on and off the leds.

if (SensorValue[ultrasonic] > threshold) {
  //led1 on and led2 off
  SensorValue[led1] = 1;
  SensorValue[led2] = 0;
} else if (SensorValue[ultrasonic] == threshold) {
  //both leds on
  SensorValue[led1] = 1;
  SensorValue[led2] = 1;
} else if (SensorValue[ultrasonic] < threshold) {
  //led1 off and led2 on
  SensorValue[led1] = 0;
  SensorValue[led2] = 1;
} else {
  //something happened
  //we don't know what to do so
  //let's just turn off the 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.

You will also notice that occasionally, you will receive a random -1 value from the sensor. That means that there was some error with that particular reading. We need to filter these values out, so we also need to put all this code in another 'if' statement.

task main()
{
  while (true)
  {
    //Make sure the value is not an error.
    if (SensorValue[ultrasonic] > 0)
    {
      if (SensorValue[ultrasonic] > threshold) {
        //led1 on and led2 off
        SensorValue[led1] = 1;
        SensorValue[led2] = 0;
      } else if (SensorValue[ultrasonic] == threshold) {
        //both leds on
        SensorValue[led1] = 1;
        SensorValue[led2] = 1;
      } else if (SensorValue[ultrasonic] < threshold) {
        //led1 off and led2 on
        SensorValue[led1] = 0;
        SensorValue[led2] = 1;
      } else {
        //something happened
        //we don't know what to do so
        //let's just turn off the 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(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0)
#pragma config(Sensor, dgtl5,  led1,           sensorDigitalOut)
#pragma config(Sensor, dgtl6,  led2,           sensorDigitalOut)
#pragma config(Sensor, dgtl7,  ultrasonic,     sensorSONAR_TwoPins_inch)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 
task main()
{
  while (true)
  {
    //Make sure the value is not an error.
    if (SensorValue[ultrasonic] > 0)
    {
      if (SensorValue[ultrasonic] > 7) {
        //led1 on and led2 off
        SensorValue[led1] = 1;
        SensorValue[led2] = 0;
      } else if (SensorValue[ultrasonic] == 7) {
        //both leds on
        SensorValue[led1] = 1;
        SensorValue[led2] = 1;
      } else if (SensorValue[ultrasonic] < 7) {
        //led1 off and led2 on
        SensorValue[led1] = 0;
        SensorValue[led2] = 1;
      } else {
        //something happened
        //we don't know what to do so
        //let's just turn off the leds
        SensorValue[led1] = 0;
        SensorValue[led2] = 0;
      }
    }
  }
}