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!
It's time to test your Feedback 360° servos' feedback 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 WX 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 potential symptoms and causes:
Congratulations! It is time to calibrate your ActivityBot 360°.
Since 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 abdrive360.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 360° 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.
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 converts it to position information which is then sent to the Propeller I/O pin. (For more details, see the Feedback 360° Servo product guide [3].)
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. This name is a carry-over from an older style of external optical wheel encoders that watched each wheel spoke go by. 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.
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 360° 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.
Although it’s possible to go a certain distance by choosing a speed and calculating the time, there is an easier way. Fortunately, the abdrive360 library has 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 "abdrive360.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 until it receives different wheel instructions is helpful for that kind of application.
We can do this with the abdrive360 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 "abdrive360.h" // abdrive360 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 "abdrive360.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 "abdrive360.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] https://www.parallax.com/downloads/parallax-feedback-360%C2%B0-high-speed-servo-product-guide