Now that you can measure centimeter distances with the PING))) sensor, and know which kinds of objects it can sense, let’s put it to work in navigation.
All your code has to do is make the robot go forward until it receives a distance measurement from the PING))) sensor that’s less than some pre-defined value, say 20 cm. Then, slow down to a stop. After that, turn in place until the measured distance is more than 20 cm. At that point, it’ll be safe to go forward again. To make the ActivityBot's navigation a little more interesting, your code can also use random numbers to decide which direction to turn.
Before actually roaming, it’s important to test a smaller program to make sure your ActivityBot will stop in front of an obstacle, and turn away from it. This example program makes the ActivityBot go forward while the PING))) measured distance is greater than 20 cm. If the distance measures less than or equal to 20 cm, the robot ramps down to a stop. Then, it turns in place until it measures more than 20 cm, which means the robot turned until the object is no longer visible.
This program doesn’t use distance = ping_cm(8). Instead, it just takes the value ping_cm(8) returns, and uses it in decisions. So, it doesn’t need to declare a distance variable; however, it does still need a variable for storing a random number to decide which way to turn. So before the main function, there's a declaration for a variable named turn.
The program starts with drive_setRampStep(10), which sets the number of ticks per second that the speed is allowed to change for every 50th of a second. Since the function call passes 10, it means the speed can only change by 10 ticks per second, every 50th of a second. Next, drive_ramp(128, 128) ramps up to full speed, in steps of 10 ticks per second. With a ramp step of 10, it takes 13 50ths of a second = 0.26 seconds to ramp up to full speed. All the steps are by 10, except for the last one, which is from 120 to 128.
/* Detect and Turn from Obstacle.c Detect obstacles in the ActivityBot's path, and turn a random direction to avoid them. */ #include "simpletools.h" // Include simpletools header #include "abdrive.h" // Include abdrive header #include "ping.h" // Include ping header int turn; // Navigation variable int main() // main function { drive_setRampStep(10); // 10 ticks/sec / 20 ms drive_ramp(128, 128); // Forward 2 RPS // While disatance greater than or equal // to 20 cm, wait 5 ms & recheck. while(ping_cm(8) >= 20) pause(5); // Wait until object in range drive_ramp(0, 0); // Then stop // Turn in a random direction turn = rand() % 2; // Random val, odd = 1, even = 0 if(turn == 1) // If turn is odd drive_speed(64, -64); // rotate right else // else (if turn is even) drive_speed(-64, 64); // rotate left // Keep turning while object is in view while(ping_cm(8) < 20); // Turn till object leaves view drive_ramp(0, 0); // Stop & let program end }
Next, the program enters a one-line loop: while(ping_cm() >= 20) pause(5). This translates to "check to see if the ping_cm function returned a value equal to or greater than 20 (no object is detected within 20 cm), and if this is true, pause for 5 ms and then check again." As long as ping_cm returns greater than 20, the while loop keeps looping, the ActivityBot continues to drive straight forward.
If a ping_cm function call returns a value of 20 or less (an object is detected within 20 cm), then the while condition is no longer true and the loop stops repeating. This allows the code to move on to drive_ramp(0, 0). This slows the ActivityBot down to a stop, which also takes about 0.26 seconds.
After stopping, the ActivityBot has to decide which direction to turn to avoid the object. This example uses the math library’s rand function (included by simpletools) to randomly choose between left and right. The rand function returns a pseudo random value somewhere in the 0 to 2,147,483,648 range. Each time the code calls rand, it returns a new value in its pseudo-random sequence. The statement turn = rand() % 2 divides 2 into the random number, takes the remainder (which will be a 1 or 0), and copies it to the turn variable.
This turn variable’s random 1 or 0 is used to decide which direction to turn. If turn gets a random one, if(turn == 1) drive_speed(64, -64) statement makes the ActivityBot rotate right. If instead turn gets a random zero, drive_speed(-64, 64) makes it rotate left. After that, while(ping_cm(8) < 20) keeps repeating while the object is still in view. As soon as the ActivityBot has turned far enough, it stops.
If all that worked, most of the code in the main function can be put in a while(1) loop to make the ActivityBot go looking for new obstacles.
Library List — This application uses functions from four libraries, simpletools (pause), abdrive (anything starting with drive), ping (ping_cm) , and math (rand). The math library is not declared here because simpletools already includes it, but you could just as easily add #include <math.h> to the list. It would be enclosed in < > symbols instead of quotes by convention since it’s part of Propeller GCC and not part of the Propeller C Tutorial's custom libraries (like simpletools, abdrive, and ping).
This program just needs a while(1) loop to make it move on in search of the next obstacle and continue to repeat what it just did. The only thing that doesn’t need to be part of the while loop is the last drive_ramp(0, 0).
Here are three challenges for you.