Using an ultrasonic sensor to measure distance
|
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.
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.
| 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.
|
is equal to |
|
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; } } } } |