Using the Sharp IR Sensor to Detect the Distance to Objects and Avoid Them
|
Configuration
Now that we know how the sensor works and have it wired, it is time to program it in ROBOTC. But first we need to tell ROBOTC how the robot is configured:
- DFRobot Motor Shield
- Motor_5 as a reversed Internal H.Bridge named "rightServo"
- Motor_6 as a reversed Internal H.Bridge named "leftServo"
- Analog pin 2 as an analog input named "sharpIR"
#pragma config(CircuitBoardType, typeCktBoardUNO) #pragma config(PluginCircuitBoard, typeShieldDFRobotMotor) #pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0) #pragma config(Sensor, anlg2, sharpIR, sensorAnalog) #pragma config(Motor, motor_5, rightServo, tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl5, dgtl4) #pragma config(Motor, motor_6, leftServo, tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl6, dgtl7) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// |
Reading the Sensors
To get the reading from the detector you use SensorValue[] just like with any other sensor.
The readings tend to be higher as the sensor approaches an object, and lower as it moves farther away. Note however that there is a value drop off right as the sensor gets close to contact with the object. This is an important flaw in the sensor that should be kept in mind during programming.
As you can see here, the values max out between 2-3" and then rapidly drop as the sensor comes into contact with the object.
Here is a sample of recorded values (approximate) for the sensor at various distances
| Distance (in mm) | Distance (in In.) | Value |
|---|---|---|
| 0 | 0" | 172 |
| 25 | 1" | 245 |
| 50 | 2" | 376 |
| 75 | 3" | 520 |
| 100 | 4" | 500 |
| 150 | 6" | 333 |
| 200 | 8" | 265 |
| 250 | 10" | 217 |
| 300 | 12" | 179 |
| >400 | >12" | 172 |
It's also very important to note that if the Sharp IR sensor is at an angle to an obstacle, it will read a value that is farther away than it actually is, since the laser is going farther than the shortest distance from the sensor to the object's side.
Making the Program
We will be modifying an existing program to use the Sharp IR sensor, starting with the code for avoiding obstacles using the Lego Ultrasonic sensor.
task main() { while (true) { if (SensorValue[ping] <= threshold) { //there is something within the threshold range motor[leftServo] = -90 motor[rightServo] = 90; wait1Msec(400); } else { //nothing in the threshold range motor[leftServo] = 90; motor[rightServo] = 90; } } } |
Since the Sharp IR sensor also returns a range of values, all we really need to do is change any reference to the ultrasonic sensor to reference the Sharp IR sensor instead. We will also need to adjust the threshold.
#pragma config(CircuitBoardType, typeCktBoardUNO) #pragma config(PluginCircuitBoard, typeShieldDFRobotMotor) #pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0) #pragma config(Sensor, anlg2, sharpIR, sensorAnalog) #pragma config(Motor, motor_5, rightServo, tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl5, dgtl4) #pragma config(Motor, motor_6, leftServo, tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl6, dgtl7) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { int threshold=300;//The value for the distance you want to keep from the wall. Values under 200 are not advised. while (true) { if (SensorValue[sharpIR] >= threshold) { //there is something closer than the threshold value motor[leftServo] = -90; motor[rightServo] = 90; wait1Msec(400); } else { //nothing in the threshold range motor[leftServo] = 90; motor[rightServo] = 90; } } } |
As you see in the video, however, this program runs into problems sometimes because unlike the ultrasonic sensor which sends out sound in all directions, the IR sensor only shoots its IR beam straight ahead. So, when it gets at a very shallow angle to an object, the object interferes with its turning because the robot is practically touching it before the IR sensor picks it up. An easy fix for this is to add in a "back up" segment into the part of the if() statement that turns the robot. This way, the robot gets clear of the object and can turn freely.
#pragma config(CircuitBoardType, typeCktBoardUNO) #pragma config(PluginCircuitBoard, typeShieldDFRobotMotor) #pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0) #pragma config(Sensor, anlg2, sharpIR, sensorAnalog) #pragma config(Motor, motor_5, rightServo, tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl5, dgtl4) #pragma config(Motor, motor_6, leftServo, tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl6, dgtl7) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { int threshold=300; while (true) { if (SensorValue[sharpIR] >= threshold) //The value for the distance you want to keep from the wall. Values under 200 are not advised. { //there is something closer than the threshold value //Back up motor[leftServo] = -100; motor[rightServo] = -100; wait1Msec(500); //turn out of the way motor[leftServo] = -100; motor[rightServo] = 100; wait1Msec(500); } else { //nothing in the threshold range // move forward motor[leftServo] = 100; motor[rightServo] = 100; } } } |
This second program works even better than the first, and has the robot quickly and easily turning to avoid obstacles.
