This section shows you how to make your ActivityBot move. It covers:
From here forward, we will be talking about the robot's right and left sides, and its front and back. These terms are from the perspective of a tiny person sitting on the white breadboard, with a hand on each post and feet dangling past the edge of the board.
Now you are ready to roll!
Only for FEEDBACK 360° SERVOS
If you are using external encoders, go to External Encoder Test [3] instead.
It's time to test your Feedback 360° servos' encoder signal connections, to make sure they are proper working order. If all is well, the example program below will cause the built-in LED on the Activity Board to blink on and off when you gently turn a wheel by hand.
/* Test Feedback Connections.c */ #include "simpletools.h" // Library - simpletools #include "abdrive360.h" // Library - abdrive360 int left; // Current/previous angles int right; int leftPrev; int rightPrev; int main() // Main function { drive_getTicks(&left, &right); // Get current encoder ticks leftPrev = left; // Set previous values rightPrev = right; while (1) // Main loop { drive_getTicks(&left, &right); // Get current encoder ticks if (left != leftPrev) // If left different from previous { toggle(26); // Toggle P26 LED light } if (right != rightPrev) // If right different from previous { toggle(27); // Toggle P27 LED light } leftPrev = left; // Save previous values rightPrev = right; } }
Here are some symptoms and causes:
Congratulations! It is time to calibrate your ActivityBot.
Only for FEEDBACK 360° SERVOS!
If you are using external encoders, go to External Encoder Calibration [5] instead.
If your ActivityBot is using Feedback 360° servos, calibration is optional, but it will improve the accuracy of driving maneuvers. This is a one-time calibration that the AB360.h library can use for measuring and correcting distances and speeds, using information from the servo's feedback connection.
The calibration code takes about a minute to collect all of its data. You will need a smooth, and obstacle-free, floor area. While the calibration program is running, the ActivityBot will pivot forward and backward, using only one wheel at a time. It will let you know when its done by turning off its P26 and P27 lights (below the breadboard). The video shows an ActivityBot correctly performing the calibration.
IMPORTANT! USE FRESH BATTERIES FOR THIS STEP!
/* ActivityBot 360 Calibrate.c */ #include "simpletools.h" #include "abcalibrate360.h" int main() { cal_servoPins(12, 13); cal_encoderPins(14, 15); high(26); high(27); cal_activityBot(); low(26); low(27); }
What if it Didn't Work?
If your robot didn't move when you started the calibration program, or it started going backwards first instead of forwards, or if it started and stopped right away or just twitched, double-check your electrical connections. You may have a servo cable or feedback signal wire plugged in wrong.
What if I need to re-start or repeat the calibration?
To re-start the calibration process, just push the reset button any time while the P26 and P27 lights are on.
To repeat the calibration process once it has fully completed, you will need to use BlocklyProp to re-load the program. That is because the program modifies itself at the end so that it cannot run a second time. This keeps your ActivityBot from trying to re-calibrate the next time you turn power on to load a new program.
This example program turns on the P26 and P27 LEDs with high(26) and high(27). It then calls the abcalibrate360 library’s cal_activityBot function, which takes the robot through the sequence of motions you just observed. While performing the maneuvers, the cal_activityBot function gathers data that corresponds to the various drive levels it applies to the servos. It stores this data n EEPROM so that every ActivityBot navigation program can use it to fine-tune the drive level needed for going a given speed. When the cal_activityBot function is done, the program turns off the P26 and P27 lights with low(26) and low(27).
Encoders - An encoder converts information from one format to another. The ActivityBot's encoders convert wheel rotation or position into digital information that the Propeller microcontroller can use.
Encoder Ticks are not insects - Throughout this tutorial, you will see the term "ticks" when used to describe the ActivityBot's wheels turning. In this context, a tick means 1/64th of a wheel revolution. When the wheel makes one complete revolution, it has turned 64 ticks. We use ticks per second to note how fast the wheels are turning. Ticks can also refer to distance traveled, when considering the circumference of the ActivityBot wheel.
Feedback 360° Servo's Internal Encoders - Each Feedback 360° servo has a tiny magnet inside that is attached to the motor shaft. Also inside the servo's case is a Hall-effect sensor, which can detect changes in the position of the magnetic field as the motor shaft rotates. A tiny processor monitors the Hall-effect sensor and sends position information to the Propeller I/O pin. (For more details, see the Feedback 360° Servo product guide [7].)
There's a block that can check the ActivityBot's calibration data and tell you if there are any mistakes or problems with the ActivityBot's servo, encoder and battery connections. If this test says the calibration was successful, your ActivityBot will be ready to run navigation programs. If not, it will tell you what problem(s) it detected. After finding it and fixing it, make sure to run both the calibration and this test again. Your ActivityBot won't be ready for navigation until it has been calibrated AND passes this test!
/* ActivityBot360 Display Calibration Results.c */ #include "simpletools.h" #include "abcalibrate360.h" int main() { cal_displayResults(); }
If the terminal output says "...calibration completed successfully...", you can skip to the Your Turn section because the servos, encoders, and power are all connected correctly. So, your ActivityBot is ready to run navigation programs.
Now that your ActivityBot has been calibrated, it is time to run a simple test program to make it drive straight forward. The test code below makes both wheels turn forward at 64 encoder ticks per second for 4 seconds. This should make your ActivityBot roll forward about 1 meter (3 ft.)
/* Forward then Stop.c */ #include "simpletools.h" #include "abdrive360.h" int main() { drive_speed(64, 64); pause(4000); drive_speed(0, 0); }
Your robot should travel forward for about 1 meter (3 ft.) in a straight line. You may see slight shifts as the robot adjusts its course based on encoder feedback.
First, the lines #include "simpletools.h"and #include "abdrive360.h" make the functions of these two libraries available to the program. ALL of the programs for your ActivityBot 360 will need abdrive360.h specifically. abdrive.h will not work.
Then, inside main, the function drive_speed(64, 64) starts the ActivityBot wheels rotating at a rate of 64 ticks per second. Once you send your ActivityBot a drive_speed instruction, its servos will turn at the specified rate until it receives another drive... instruction, even while other functions are being executed. For example, the function pause(4000) elapses while the ActivityBot drives forward at that rate for 4 seconds. Finally, drive_speed(0, 0) makes the wheels stop turning.
Only for External Encoders!
If you are using Feedback 360° servos, go to Feedback 360° Servo Test [9] instead.
This short test program makes sure each encoder sensor can see the spokes in the wheel right next to it. If the encoder is working properly, a built-in LED on the board will light up each time it detects a spoke, and go off when the hole between the spokes passes by.
/* Test Encoder Connections */ #include "simpletools.h" int main() { low(26); low(27); while(1) { set_output(26, input(14)); set_output(27, input(15)); } }
Here are some symptoms and causes:
Congratulations! It is time to calibrate your ActivityBot.
Only for External Encoders!
If you are using Feedback 360° servos, go to Feedback 360° Encoder Calibration [4] instead.
Before running any other example programs, your ActivityBot needs to be calibrated. This is a one-time calibration that the abdrive library needs for measuring and correcting disances and speeds, using information from the ActivityBot encoders.
The calibration collects requested speed vs. measured speed data and stores it in a part of the ActivityBoard’s EEPROM memory, where it can retain data even after you turn the power off. That way, the calibration data is available every time you turn the robot back on.
When your program asks for a certain wheel speed, the abdrive library will use the calibration data from EEPROM to start driving the motors at speeds close to what your program asks for. That way, abdrive doesn’t have to make large corrections, just small ones, which improves overall accuracy.
The calibration program takes less than 2 minutes to collect all of its data. You will need a smooth and obstacle-free floor area that’s roughly one meter square. While the calibration program is running, the ActivityBot will go in circles at various speeds, using only one wheel at a time. It will let you know when its done by turning off its P26 and P27 lights (below the breadboard). The above video shows an ActivityBot correctly performing the calibration.
IMPORTANT! USE FRESH BATTERIES FOR THIS STEP!
IMPORTANT! Your ActivityBot Library needs to be installed in the correct location BEFORE attempting to run this, or any other, ActivityBot program.
The ActivityBot library folder should be in ...Documents\SimpleIDE\Learn\Simple Libraries\Robotics. If you install the library folder yourself, unzip the library folder and then make sure to close and then re-open SimpleIDE before continuing on to allow the software to cache the library location.
Return to Software and Programming [1] for the library download and additional instructions, if necessary.
What if it Didn't Work?
If your robot didn't move when you started the calibration program, started going backwards first instead of forwards, started and stopped right away, or just twitched instead of moving, go to the Troubleshooting [13]page for help.
Re-starting the Calibration Program
If you need to re-start the calibration process, you can push the reset button any time while the P26 and P27 lights are on. Once the calibration process is complete, the program image gets modified so that it cannot run a second time. This keeps it from trying to re-calibrate the next time you turn power on to load a new program. If you want to re-run the calibration, you will need to use SimpleIDE to load ActivityBot Calibrate into EEPROM again.
This example program turns on the P26 and P27 LEDs with high(26) and high(27). It then calls the abcalibrate library’s cal_activityBot function, which takes the robot through the sequence of motions you just observed. While performing the maneuvers, the cal_activityBot function builds a list of wheel speeds that correspond to the various drive levels it applies to the servos. It stores those values in EEPROM so that every ActivityBot navigation program can use them to find out what drive level is needed for going a given speed. When the cal_activityBot function is done, the program turns off the P26 and P27 lights with low(26) and low(27).
/* ActivityBot Calibrate.c Calibrate the ActivityBot's servos and encoders */ #include "simpletools.h" #include "abcalibrate.h" int main() { cal_servoPins(12, 13); cal_encoderPins(14, 15); high(26); high(27); cal_activityBot(); low(26); low(27); }
Encoder Ticks - Each ActivityBot encoder shines infrared light at the ring of 32 spokes in the wheel next to it. If the light passes between the spokes, the encoder sends the Propeller a high signal. If it bounces off a spoke and reflects back to the encoder’s light sensor, it sends a low signal to the Propeller. Each time the signal changes from high to low, or low to high, the Propeller chip counts it as an encoder tick.
Sensing Direction — The Propeller chip knows what direction the servos turn based on the signal it uses to make the servo move. All it needs from the encoder is to know how fast it’s turning. It does this by counting encoder ticks over a period of time. The libraries keep track of all this for you, so your programs just need to tell the robot robot how far or how fast to go.
Interpolation — The cal_activityBot function builds a table of data points for motor drive level and the actual speed the wheels turned. Navigation programs will use those data points to figure out how hard to drive a wheel to get a certain speed. If the speed the program asks for is between two data points, the navigation library will figure out the best drive value between two of the known values. For example, if the table has data points for 60 and 80 encoder ticks per second, and your program asks for 70 ticks per second, the navigation library will use a motor drive level that’s half way between the 60 and 80 ticks per second levels. This process is called interpolation and the data set is called a linear interpolation table.
You can check to see if the calibration was successful, and if not, see a message that may help diagnose the problem.
You can use the program below to view it.
/* ActivityBot Display Calibration Results.c */ #include "simpletools.h" #include "abdrive.h" int main() { drive_calibrationResults(); }
The Terminal will display a message either confirming that your calibration was successful, or a suggestion for troubleshooting your connections if calibration failed.
The function drive_displayInterpolation will display the actual lists of values that are stored in EEPROM. This interpolation table data can be very helpful for troubleshooting [13] if your robot does not drive as expected after calibration.
Now that your ActivityBot has been calibrated, it is time to run a simple test program to make it drive straight forward. The test code below makes both wheels turn forward at 64 encoder ticks per second for 4 seconds. This should make your ActivityBot roll forward about 1 meter (3 ft.).
/* Forward then Stop.c */ #include "simpletools.h" #include "abdrive.h" int main() { drive_speed(64, 64); pause(4000); drive_speed(0, 0); }
Your robot should travel forward for about 1 meter (3 ft.) in a straight line. You may see slight shifts as the robot adjusts its course based on encoder feedback.
First, the lines #include "simpletools.h"and #include "abdrive.h" make the functions of these two libraries available to the program. ALL of the programs for your ActivityBot with external encoders will need abdrive.h specifically. abdrive360.h will not work.
Then, inside main, the function drive_speed(64, 64) starts the ActivityBot wheels rotating at a rate of 64 ticks per second. Once you send your ActivityBot a drive_speed instruction, its servos will turn at the specified rate until it receives another drive... instruction, even while other functions are being executed. For example, the function pause(4000) elapses while the ActivityBot drives forward at that rate for 4 seconds. Finally, drive_speed(0, 0) makes the wheels stop turning.
Although it’s possible to go a certain distance by choosing a speed and calculating the time, there is an easier way. Fortunately, the abdrive and abdrive360 libraries have a function that takes care of all that. It’s called drive_goto, and you can use it to tell the ActivityBot how far each wheel should turn in terms of 3.25 mm increments.
Recall that the term “tick” indicates 1/64th of a wheel rotation. If the wheel turns 64 ticks, it makes one complete revolution. That would make the robot travel the distance of its wheel circumference, which is 208 mm. So, if the wheel turns 1/64th of a turn—that’s a tick’s worth—it will travel 3.25 mm.
If you know how far you want your ActivityBot to roll, just divide the distance by 3.25 mm (or 0.325 cm or 0.00325 m) to find out how many ticks your program needs to tell the ActivityBot to travel.
ticks = distance mm ÷ 3.25 mm/tick
The ActivityBot’s turning radius is typically 105.8 mm.
If you hold the right wheel still and make the left wheel turn, it will have to turn 2 × π × r. In this case, the r is the turning radius, so that’s 2 × π × 105.8 mm ≈ 664.76 mm. If you want the ActivityBot to make a ¼ turn, that would be 664.76 mm ÷ 4 ≈ 166.2 mm. How many wheel ticks is that? 166.2 mm ÷ 3.25 mm/tick ≈ 51.14 ticks ≈ 51 ticks.
TIP: If you make one wheel go forward 26 ticks, and the other go backwards 25 ticks, that’s still a total of 51 ticks for ¼ of a turn.
This test code makes the ActivityBot go forward 256 ticks, and then turn and face 90-degrees to the right.
The program makes the ActivityBot go forward by 256 ticks (four wheel turns). Then, drive_goto(26, -25) makes the ActivityBot execute a 90-degree right turn.
#include "simpletools.h" #include "abdrive.h" int main() { drive_goto(256, 256); pause(200); drive_goto(26, -25); }
Overshoots — If the drive_goto function overshoots, it backs up to the correct number of ticks.
Expand the program to make the ActivityBot retrace its path back to where it started, after going forward and turning right. There are two ways you could accomplish this:
Simple waypoint navigation challenges involve programming your robot to drive a pre-determined course. An example course is shown below. To run this course, you would need to program your ActivityBot for the following manueuvers (this will take a bit of math):
Sometimes your ActivityBot might need to go a certain direction until it runs into an obstacle. Setting the robot to go a certain speed, instead of a certain distance, is helpful for that kind of application.
We can do this with the abdrive library's drive_speed function. It sets each drive servo to a certain speed, in encoder ticks per second. Since there are 64 ticks in a wheel turn, if you set a wheel speed to 64 ticks per second, that’s one full turn per second. Use positive values for forward, and negative values for reverse.
We’ll also try a drive_ramp function that lets the ActivityBot speed up and slow down gradually. This prevents its wheels from losing traction, and helps keep the robot from tipping forward from abrupt stops.
This example sets the robot to go straight ahead at 64 ticks/second until it has gone more than 200 ticks forward. Then it executes a 45-degree right turn with the left wheel turning 32 ticks per second. After that, it continues for another 200+ ticks at 128 ticks per second.
The program sets out by setting both servos to turn at 64 ticks per second with drive_speed(64, 64). Since 64 ticks per second is one full wheel revolution per second, and since a pause(2000) follows it, we know the wheels should both turn at 64 ticks per second for two seconds. In terms of distance, that should be 64 ticks/second x 2 seconds = 128 ticks. Keep in mind that this may not be precise because the robot will have some momentum when it gets to drive_speed(0, 0). Also keep in mind that if you do want a more precise distance traveled, just use the drive_goto function.
#include "simpletools.h" // simpletools library #include "abdrive.h" // abdrive library int main() { drive_speed(64, 64); // Forward 64 tps for 2 s pause(2000); drive_speed(0, 0); drive_speed(26, 0); // Turn 26 tps for 1 s pause(1000); drive_speed(0, 0); drive_speed(128, 128); // Forward 128 tps for 1 s pause(1000); drive_speed(0, 0); }
Next, drive_speed(26, 0) makes the left wheel turn at about 26 ticks per second, while the right wheel stays still. Since it’s going for 1 second, the left wheel should turn about 26 ticks for a 45-degree turn. drive_speed(0, 0) stops it after the 1 second. The last maneuver should go about the same distance as the first maneuver, but it’s going twice as fast (128 ticks per second instead of 64) for half the time (1 second instead of 2 seconds).
Velocity is speed, but it can be either positive (like forward) or negative (like backward). Speed itself is just velocity without the sign. So, if you are going backwards at a speed of 5 km/hr, you could also call that a velocity of -5 km/hr.
Here is an equation you can use to calculate distance (s) given velocity (v) and time (t).
s = v × t
Example: A car goes 40 km/hr, how many km does it travel in 0.25 hours? Answer: s = v × t = 40 km/hr × 0.25 hr = 10 km.
Applied to the ActivityBot, if a wheel goes 64 ticks per second for 2 seconds, that’s v = 64 ticks per second and t = 2 seconds. So:
s = 64 ticks/second × 2 seconds = 128 ticks.
For a distance in centimeters, remember that a tick is 0.325 cm, so the wheel travels:
s = 128 ticks × 0.325 cm/tick = 41.6 cm.
If you divide both sides of s = v × t by v, you get:
t = s ÷ v
…and that’s really useful for picking a time to go a certain direction if you know the speed and distance you want the ActivityBot to go.
Example: The ActivityBot needs to go 192 ticks forward at a rate of 64 ticks per second.
If you noticed some sudden starts and stops in the previous example programs, these can be cushioned with drive_ramp. This function gradually speeds up or slows down the wheels.
You can also use drive_speed to make the ActivityBot travel in curves.
#include "simpletools.h" #include "abdrive.h" int main() { drive_speed(80, 60); pause(2000); drive_speed(0, 0); }
If your program ever needs to know how many ticks each wheel has traveled, you can use the drive_getTicks function. Here is an example that records the number of ticks traveled before and after the Try This program that curved to the right. Use Run with Terminal, and leave your robot plugged in. (Try setting the robot on a stand or hold it above the desk so that it doesn't go to far while attached to the USB cable.)
Your challenge is to add two more maneuvers and display the distance traveled for each maneuver.
Hint: You can calculate distance for each maneuver by using something like: distanceLeft = distLeft[1] - distLeft[0];
#include "simpletools.h" #include "abdrive.h" int distLeft[4], distRight[4]; int main() { drive_getTicks(&distLeft[0], &distRight[0]); print("distLeft[0] = %d, distRight[0] = %d\n", distLeft[0], distRight[0]); drive_speed(80, 60); pause(2000); drive_speed(0, 0); drive_getTicks(&distLeft[1], &distRight[1]); print("distLeft[1] = %d, distRight[1] = %d\n", distLeft[1], distRight[1]); }
Links
[1] https://learn.parallax.com/activitybot/software-and-programming
[2] https://learn.parallax.com/propeller-c-set-simpleide/update-your-learn-folder
[3] http://learn.parallax.com/node/880
[4] http://learn.parallax.com/node/1715
[5] http://learn.parallax.com/729
[6] http://learn.parallax.com/tutorials/robot/activitybot/blocklyprop-robotics-activitybot/electrical-connections
[7] https://www.parallax.com/downloads/parallax-feedback-360%C2%B0-high-speed-servo-product-guide
[8] http://learn.parallax.com/node/731
[9] http://learn.parallax.com/node/1714
[10] https://learn.parallax.com/activitybot/troubleshooting#encoder
[11] http://learn.parallax.com/node/729
[12] https://learn.parallax.com/activitybot/electrical-connections
[13] https://learn.parallax.com/activitybot/troubleshooting