This project demonstrates how a cyber:bot can roam around and avoid objects on the right, front and left of the chassis using the Ping))) Ultrasonic Sensor and Mounting Bracket Kit. A Ping))) Ultrasonic Sensor mounted on a servo can measure distances at any interval across a 180 degree radius. This technique can be used to travel down a narrow hallway or maze, staying centered in the corridor. You may also program the cyber:bot to never get stuck since it can easily detect obstacles on the sides.
Cyber:bots are made to be modified! What if your cyber:bot could be outfitted with wheel traction devices to travel on snow, ice, and pine needles? We hot-glued some screws to the perimeter of the wheel to test this concept. The video and short instructions are the last page of this tutorial.
Any hardware (screws, locknuts, etc) we use either comes from our cyber:bot kit, the Ping))) Ultrasonic Sensor + Mounting Bracket kit, or can be easily found at any local hardware store. We typically use #4-40 screw sizes.
It’s a good idea to add a “strain relief” with a zip tie or small wire to each end of the cable. One could secure the Ping)))’s cable to the header block and another may be used to keep the cable pointed upward so it doesn’t interfere with components on the breadboard. Make sure the cable doesn’t rub against anything when the servo moves.
The Ping))) Ultrasonic Distance Sensor lets your cyber:bot detect obstacles by measuring the distance to them.
Much like a bat, the Ping))) sensor emits an ultrasonic chirp, then listens for the chirp's echo. The time between these two events is used to calculate the distance to an object. While most objects will return an echo, be aware that size, material, and angle all make a difference, as shown in the image below.
The Ping))) sensor measures the echo return time in terms of microseconds. Then, it uses the fact that sound travels at 0.03448 cm/µs at room temperature. That’s 3.448 hundredths of a centimeter per millionth of a second at a temperature of (22.2 ºC). Just as a car travels distance = speed x time, so does sound, with an equation of s = ct, where s is the distance, c is the speed of sound and t is the time.
Did you know that the speed of sound in air actually changes with air temperature? This Learn reference article explains more about why this happens [3]. Temperature extremes can actually make a slight, but notable, difference in Ping))) sensor measurements.
This project has several subsystems that we’ll test independently before we program to work together. First, we need to check the Ping))) Ultrasonic Sensor to see that it is wired properly and produces accurate measurements. This is what you will need to do:
# Ping_Test_with_Plotter.py from cyberbot import * from ping import * bot(22).tone(2000, 300) while True: distance = ping(16).distance('cm') print ((distance,)) sleep(25)
Once the Ping))) is working you could easily add code for the piezospeaker and create a theremin. A theremin is an electronic musical instrument where the tone is changed by the movement of your hand between two antennas. You will substitute the Ping))) Ultrasonic Sensor for the antennas.
# Ping_Theremin.py from cyberbot import * from ping import * bot(22).tone(2000, 300) while True: distance = ping(16).distance('cm') print ((distance,)) bot(22).tone((distance*50),50)
The next subsystem to test is the Ping))) bracket’s servo. The Parallax Standard Servo is able to sweep 180 degrees, positioning the Ping))) at near-exact angles along the way so the micro:bit can take distance measurements on the sides and front of the cyber:bot.
The Ping_Servo_Test.py code programs the micro:bit to position the bracket’s servo through the entire range of motion, testing only the servo motor. If you find that your servo turns beyond the range shown in the picture above to look behind the cyber:bot, remove the screw which holds the Ping))) Mounting Bracket in place and reattach.
# Ping_Servo_Test.py from cyberbot import * from ping import * # angles for L/R sweep scan theta = [0, 30, 60, 90, 120, 150, 180, 165, 135, 105, 75, 45, 15] # Offset from CW limit to actual 0 degree theta is 12 degrees offset = 12 index = 0 bot(22).tone(2000, 300) while True: for index in range(0, 13): bot(17).servo_angle (theta[index] + offset) angle = theta[index] - 90 display.scroll (angle)
The Ping_Servo_Test.py code example creates a list of values named theta, which represent the position the micro:bit will use to control the servo. The value of 0 degrees is far right and 180 degrees is far left. However, to make the next program easier to read and useful for navigation, we will create a variable named angle which calculates the straight-ahead value as 0 degrees, far right as -90 degrees and far left as 90 degrees from this line of code:
angle = theta[index] - 90
The angle value is simply 90 degrees less than the servo position controlled by the micro:bit. The image shows how this adjustment makes it so that an angle of 0 degrees is straight ahead. Anything on the left is a positive angle, and anything on the right is negative. This comes in handy for navigation programming because your code can check if the object’s angle is greater or less than zero to decide which direction to turn.
With the Ping))) and servo subsystems working correctly, we can combine them with motor control to make the cyber:bot roam. This program has several places where you can easily customize it for better performance in your own environment.
# Ping_Servo_Roaming.py from cyberbot import * from ping import * # angles for L/R sweep scan theta = [0, 30, 60, 90, 120, 150, 180, 165, 135, 105, 75, 45, 15] # Offset from CW limit to actual 0 degree theta is 12 degrees offset = 12 speed = 0 distance = 300 wL = 64 wR = 64 index = 0 bot(22).tone(2000, 300) def turn_away(index): angle = theta[index] - 90 if angle > 0: wL = 64 wR = -64 else: wL = -64 wR = 64 bot(18).servo_speed(wL) bot(19).servo_speed(-wR) sleep(500) while True: bot(17).servo_angle ( theta[index] + offset ) sleep(150) distance = ping(16).distance('cm') #print("theta = %d, distance = %d" % (theta[index], distance)) if distance >= 25: wL = 64 wR = 64 else: turn_away(index) bot(18).servo_speed(wL) bot(19).servo_speed(-wR) index += 1 if index > 12: index = 0 #print("\r\r")
You can easily modify the Ping_Servo_Roaming.py code for different behaviors based on your environment. For example, the turn_away(index) definition simply tests whether the close object is on the left or right of the robot:
def turn_away(index): angle = theta[index] - 90 #print("angle = %d" % angle) if angle > 0: wL = 64 wR = -64 else: wL = -64 wR = 64
More angle conditions could be evaluated by adding multiple elif statements and appropriate motor speeds. For example, if the object is on the left, it may only be necessary to make a slight correction with a right turn, rather than pivoting in place as shown above. An object detected in front of the cyber:bot may mean turn around, rather than turn away. These are all customizations you can make.
Also, consider the distance at which objects are considered “close” together with the cyber:bot’s speed:
if distance >= 25: wL = 64 wR = 64 else: turn_away(index)
The detection distance and speed need to work together. Driving fast with a short detection distance is a sure way to hit the wall!
Try different combinations of wL, wR, and threshold values for distance.
The cyber:bot wheels are available as pairs from the Parallax store. Since narrow wheels won’t work on dirt, snow or ice I made some modifications to them. Using hot glue and 1-inch long screws, I created a traction control system. This modification can easily be done within an hour.
The instructions for creating a pair of traction control wheels are:
The tests worked well! The cyber:bot had more flotation and traction on the snow though the wheels picked up ice and dirt along the way. A four-wheel, skid-steer robot would be more effective with these wheels. See the video highlights below!
Warning! Try this at your own risk! Always wear eye protection when working with hot glue guns. If you are trying snowy conditions, make sure your cyber:bot body and electrical components don’t get wet.
Links
[1] https://www.parallax.com/product/32700
[2] https://www.parallax.com/product/910-28015a
[3] https://learn.parallax.com/support/reference/speed-sound-air-vs-temperature