The Parallax Feedback 360° servos can turn up to twice as fast as the continuous rotation servos that come in the cyber:bot kit. The cyber:bot board is also able to adjust speeds and distances using the new servo’s feedback signal. This makes it possible for the cyber:bot to go straight without any wheel speed adjustments, and also makes traveling specific distances possible.
The activities in this tutorial will guide you through replacing the cyber:bot robot’s continuous rotation servos with the Parallax Feedback 360° High Speed Servos. It will also guide you through testing the servos, and using their built-in speed and distance features.
You will need:
Complete these tutorials first:
You will be able to:
In this activity, you will remove the cyber:bot robot’s existing continuous rotation servos and replace them with Feedback 360° servos.
(1) Fully assembled cyber:bot robot. See Build your cyber:bot (Rev C Board) [6].
(2) Parallax Feedback 360° servos (#900-00360) [2]
(1) Parallax Screwdriver that comes with the cyber:bot (#700-00064)
(1) Plastic combination wrench that comes with the cyber:bot (#700-10025)
IMPORTANT: Do not throw away any of the parts you remove from the cyber:bot. You will be reattaching them later.
This script tests if the electrical connections between the Feedback 360° servos and the cyber:bot board are all correct.
cyberbot_feedback_360_diagnostic.hex [8]
These tests — and any wiring corrections you may need to do — will need to be repeated until you see the “The servos have passed all the tests!” message.
There are several different types of error messages. Find the one you see in the sections below, and follow the red checkmarks under it to correct the issue.
No feedback signal to P16.
No feedback signal to P17.
Problem with feedback signal(s).
If you see all three feedback messages:
If you only see two of the three messages listed above, use the Circuit section as a reference and try these:
If there’s no feedback signal to P16:
If there’s no feedback signal to P17:
Either yellow wires are swapped with each other
or servo cables are swapped with each other.
If you see this message:
The wheel closer to the PWR switch should be turning.
If you see this message:
It means that the yellow wires are swapped with each other, AND the servo cables are swapped with each other.
The servo connected to P18 does not seem to be turning.
The servo connected to P19 does not seem to be turning.
If you see this message:
The servo connected to P18 is turning too slowly.
The servo connected to P19 is turning too slowly.
If you see this message:
The P18 servo is turning unusually fast.
The P19 servo is turning unusually fast.
If you see this message:
print('The P18 servo is turning unusually fast.') print('The P19 servo is turning unusually fast.')
An encoder converts information from one format to another.
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, which is a download from the #900-00360 product page at www.parallax.com.)
Throughout this tutorial, you will see the term "ticks" when used to describe the cyber:bot'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 cyber:bot wheel.
With the Feedback 360° servos, scripts can control the speed of each wheel from a full speed of 2 turns/second forward to 2 turns/second backward.
After adding the feedback360 module to the micro:bit filesystem and importing it, the drive.speed method takes left and right wheel speeds in terms of 64ths of a turn/second. Positive values are for forward, and negative values are for reverse.
Let’s first repeat the familiar forward, backward, left, right script using Feedback 360° speed control. We’ll use a half speed of 64, which is about the same as the continuous rotation servo’s top speed of 130. Unlike the continuous rotation servos, the Feedback 360° servos should not need any left/right speed value adjustments to straighten out the cyber:bot’s forward/backward travel.
speeds_forward_left_right_backward.hex [10]
Both the cyberbot and feedback360 modules have to be added to the micro:bit file system for the script to work. In the maneuver tests you just finished, both scripts were included in the .hex file speeds_forward_left_right_backward.hex. Keep in mind that the feedback360 module is not included in .py files for the activities throughout the other cyber:bot tutorials, and would need to be added!
For a reminder on how to add ado that, see Add modules to your micro:bit [4]. Pro tip: you can always reopen a script that had the modules added and was as a .hex file. That way, you won’t have to add modules every time. You can just open a previous app and then give it a new name before you start changing it. For a refresher on this, see How to Save and Reopen a Script in Python Editor v2 [12].
Below the name comment, the script imports both the cyberbot and feedback360 modules.
# speeds_forward_left_right_backward from cyberbot import * from feedback360 import *
A call to drive.connect is required to start the Feedback 360° built into the cyber:bot board.
drive.connect()
The drive.speed(64, 64) call starts the Feedback 360° servos turning at 1 turn/second. Then, sleep(2000) makes sure the wheels continue to turn for 2 seconds.
drive.speed(64, 64) # Forward sleep(2000)
The drive.speed(-64, 64) call makes the left servo turn backwards and while the right servo continues to roll forward. The result is that the cyber:bot turn to the left by rotating in place. The sleep(1000) makes sure the wheels continue this maneuver for 2 seconds.
drive.speed(-64, 64) # Rotate left sleep(1000)
This next bit below is just the turn right version of the previous routine.
drive.speed(64, -64) # Rotate right sleep(1000)
Compare this to the first maneuver. Instead of positive values, it has negative values. The result is that both wheels reverse.
drive.speed(-64, -64) # Backward sleep(2000)
Setting the speeds to zero makes the servos stay still, bringing the cyber:bot to a stop.
drive.speed(0, 0)
Try changing the forward and backward speeds to +/- 96. This should make the cyber:bot roll 1.5x faster!
The drive.speed() speed is a "set-it-and-forget-it" method. It starts the wheels turning at the chosen speed, and then code execution immediately continues with the next statement. The wheels will keep turning at that speed until another drive.speed() call changes the wheel speeds.
Velocity is like speed, but it can be either positive (forward motion) or negative (backward motion). Speed itself is just velocity without the sign that indicates direction; velocity's absolute value.
In this system, it takes time for the wheels to accelerate to whatever the new speed settings are. So, it’s not like drive.speed(64, 64) instantly makes the wheels turn that fast. The wheels were not turning at 1 turn/second the whole time, but start off more slowly and ease into the full speed maneuver. Keep that in mind if you are trying to set up a distance = velocity x time equation. The wheel will not have turned as far in 2 seconds as you’d expect with the equation. However, in the next activity, you will use distance control statements, and the control system built into the cyber:bot board will calculate acceleration as part of the distance.
Your cyber:bot can perform a variety of turn styles with velocity control. Here are some examples:
This is the familiar drive.speed(64, 64). Both wheels are turning in equal velocities. The result is that the entire cyber:bot rotates about the center-point between the servo axes.
A pivot turn works by holding one wheel still and turning the other wheel forward or backward.
You can use drive.speed(64, 0) to pivot forward right on the right wheel as shown below. If you want the cyber:bot to pivot forward left instead, use drive.speed(0, 64). To pivot backward in either direction, use -64 instead of 64.
An arc is performed by turning both wheels forwards or both wheels backwards, just with one wheel slower than the other. The arc shown below turns the right wheel slower than the left. Examples include drive.speed(64, 32) for a tighter arc:
....and drive.speed(64, 46) for a wider arc. Notice that with tigher arcs, the speed difference is largeer, and with wide arcs, the speed difference is smaller.
The cyber:bot board’s Feedback 360° servo driver measures distance in 64ths of a turn. That’s equivalent to half way between two of the smallest spokes in the cyber:bot wheel. For simplicity, we’ll call 1/64th of a rotation a ‘tick’. Since the diameter of the cyber:bot wheel is 66.2 mm, we can use Ω x diameter to calculate that the circumference is 208 mm. Then, 1/64th of that is 3.25 mm, the distance the wheel travels when it rotates one tick.
The feedback360 module has a method named drive.goto(), which you supply with two distances in ticks, one for each wheel. In this example, drive.goto(64, 64) results in both wheels turning forward 64 ticks x 3.25 mm/tick = 28 mm, the circumference of the wheel. Converting to inches, that would be 208 mm x 1 in/ 25.4 mm ≈ 8.2 in. Using 32 ticks would get the cyber:bot about half that far, about 4.1 in.
In this activity, you will use drive.goto to make the cyber:bot travel certain distances, and incorporate calculations into your script to make the cyber:bot travel a specified distance in inches. You will use distance values that will make the cyber:bot turn in place, pivot, and arc.
This script will perform the forward, left, right, left, backward pattern, and the cyber:bot should return much closer to its starting point. In fact, with drive.goto, you can mark the spoke on each wheel that’s pointing straight up when the script starts, and it should be pointing up again when the script completes.
distances_forward_left_right_left_backward.hex [13]
Like the previous script, this one uses the Feedback 360° servos, so it has to import both the cyberbot and feedback360 modules. It also has to call drive.connect before calling any other drive methods. Unlike the previous script, the drive methods in this script are not the set-and-forget kind. Keep that in mind while reading!
# distances_forward_left_right_left_backward from cyberbot import * from feedback360 import * drive.connect()
Forward 196 ticks is a total of three revolutions for a distance of approximately 192 x 3.25 / 25.4 ≈ 24.6 inches. Unlike drive.speed, the drive.goto() method waits for the maneuver to be completed before it allows the next line to be executed. The sleep(1000) is just there to provide a delay to see that the cyber:bot stopped before moving on to the next maneuver.
drive.goto(192, 192) # Forward 3 turns sleep(1000)
With turning by distance, a full circle is about +/- 104 ticks. That makes +/-52 ticks a half turn and +/- 26 ticks a quarter turn. You might need to tun this for your cyber:bot since the distance between wheels determines the robots ‘turning radius’.
drive.goto(-26, 26) # 90 degrees left sleep(1000) drive.goto(52, -52) # 180 degrees right sleep(1000) drive.goto(-26, 26) # 90 degrees left sleep(1000)
This makes the cyber:bot go backwards 192 ticks = 3 turns. The sleep(1000) is there just in case you decide to add more maneuvers.
drive.goto(-192, -192) # Backward 3 turns sleep(1000)
Let’s say that your application needs the cyber:bot to pivot by 90° instead of rotating in place. For a pivot left, instead of drive.goto(-26, 26), your script would need drive.goto(0, 52). Note that to make the 90° turn, the right wheel has to make up for the left wheel by turning twice as far!
With the servos mounted on the inside of the chassis, the distance between the cyber:bot robot’s wheels is about 107.6 mm. To make the cyber:bot pivot (not rotate!) in a full circle, we can think about that 107.6 mm as the radius of a circle, the turning radius.
How much distance would the outer wheel have to travel to do a full circle? That would be:
c = 2 x π x r
...with a result of about 676 mm. The turning radius in ticks is just that number of mm divided by 3.25 mm, for 208 ticks. Also, it doesn’t matter whether it’s a pivot turn with drive.goto(0, 208) or a rotating turn with drive.goto(104, 104), the cyber:bot will still turn 360°.
Here is a function to convert inches of distance to ticks:
def in_to_ticks(inches): return int(inches * 25.4 / 3.25)
At this point, you might be wondering how to modify an existing script to make it work with Feedback 360° servos. For example, what if you wanted to update scripts from Touch Navigation for the cyber:bot [14] or maybe Cybersecurity: Radio Tilt Control [15]? In this activity, you will learn the simple steps for updating any cyber:bot application script to work with the Feedback 360° servos.
MEMORY WARNING! Your cyber:bot will need to use a micro:bit v2 or newer for most cyber:bot applications that use the F360° servos; the v1.5 micro:bit does not have enough memory.
Here is a summary and diagram of how to adjust an existing cyber:bot script so that it runs with the Feedback 360° servos. Starting with the feedback_360_template.hex [16], add from feedback360 import * and drive.connect() just below from cyberbot import *. Then, any time you see bot(18).servo_speed(vL) and bot(19).servo_speed(vR), use the vL and vR values in drive.speed(int(vL/2), -int(vR/2)). The term int(vL/2) means divide the original vL by 2 and round down. The term int(-vR/2) means divide the original vR by 2 and round down, and take its negative value. Important: replace None with 0.
In this activity you will follow this procedure, broken into five steps. Examples with both constant values (like 75), and variables (like vL and vR) will be used. It should encompass just about any script you might want to adapt to your new Feedback 360° servos.
A cyber:bot robot [17] with two Feedback 360° High Speed Servos [2] installed following the instructions in the Swap and Test the Servos [18] section.
Here are the steps you can follow to adapt just about any existing cyber:bot application script to Feedback 360° servos.
Step 1: Download and start with the feedback_360_template.hex, and enter the original script. Note: the template already has the cyberbot and feedback360 modules added by the procedure in Add modules to your micro:bit. (Remember to always right-click and chose Save As to download hex files.)
feedback_360_template.hex [16]
Step 2: Add two lines just below from cyberbot import *:
from feedback360 import * drive.connect()
Step 3: Take the vL and vR values from these two statements:
bot(18).servo_speed(vL) bot(19).servo_speed(vR)
…and add this statement immediately below them:
drive.speed(int(vL/2), -int(vR/2))
IMPORTANT! If you see None as either the vL or vR value, replace it with 0.
NOTE: The term int(vL/2) means "divide by 2 and round down."
Step 4: Use the # symbol to comment the bot(18).servo_speed(vL) and bot(19).servo_speed(vR) statements.
Step 5 (optional): After you have verified that your adjustments work properly, optionally remove all the bot(18/19).servo_speed… calls.
Let’s start with a simple app, like forward_three_seconds from Forward and Backward in the Navigation with the cyber:bot chapter. After following the four steps, the updated script might look like forward_three_seconds_for_fb360 (below).
feedback_360_template.hex [16]
# forward_three_seconds_for_fb360 from cyberbot import * from feedback360 import * # <-- add drive.connect() # <-- add # bot(18).servo_speed(75) # <-- comment Half speed forward # bot(19).servo_speed(-75) # <-- comment drive.speed(37, 37) # <-- add sleep(3000) # Wait three seconds # bot(18).servo_speed(None) # <-- comment Stop # bot(19).servo_speed(None) # <-- comment drive.speed(0, 0) # <-- add
Again, here is a repeat of the summary and diagram of how to adjust an existing cyber:bot script so that it runs with the Feedback 360° servos.
Starting with the feedback_360_template.hex, add from feedback360 import * and drive.connect() just below from cyberbot import *. Then, any time you see bot(18).servo_speed(vL) and bot(19).servo_speed(vR), use the vL and vR values in drive.speed(int(vL/2), -int(vR/2)). The term int(vL/2) means "divide the original vL by 2 and round down." The term int(-vR/2) means "divide the original vR by 2 and round down, and take its negative value." Important: replace None with 0.
Next, let’s break it into steps, starting with an existing script to convert from Forward and Backward in the Navigation with the cyber:bot chapter.
# forward_three_seconds.py from cyberbot import * bot(18).servo_speed(75) # Half speed forward bot(19).servo_speed(-75) sleep(3000) # Wait three seconds bot(18).servo_speed(None) # Stop bot(19).servo_speed(None)
Now, let’s take a look at how the four steps were applied to this script. Read each of the step summaries and examine how they are incorporated into the script.
Step 1 is to start with the feedback_360_template.hex file and add the existing script, and Step 2 is to add from feedback360 import * and drive.connect() immediately below from cyberbot import *. This adds the necessary feedback360 module, and initializes the servos.
# forward_three_seconds_for_fb360 from cyberbot import * from feedback360 import * # <-- add drive.connect() # <-- add
For Step 3, recall that the term int(vL/2) means "divide by 2 and round down." So, vL ÷ 2 = 37.5, and rounded down, the result is 37. Likewise, the result of -int(vR/2) is -(-75 ÷ 2) rounded down is 37 because the two negative signs cancel. These two results are used in adding drive.speed(37, 37). In Step 4, the bot(18).servo_speed(vL) and bot(19).servo_speed(vR) statements are commented with the # symbol.
# bot(18).servo_speed(75) # <-- comment Half speed... # bot(19).servo_speed(-75) # <-- comment drive.speed(37, 37) # <-- add
No changes here:
sleep(3000) # Wait three seconds
REMEMBER: To stop the cyber:bot, make sure to use 0 in place of None! So, in Step 3, add drive.speed(0, 0). Then, in Step 4, just use the # symbol to comment bot(18).servo_speed(None) and bot(19).servo_speed(None).
# bot(18).servo_speed(None) # <-- comment Stop # bot(19).servo_speed(None) # <-- comment drive.speed(0, 0) # <-- add
Here are some alternate versions of the script you can try. Following the optional Step 5, the final script would look more like this after the servo_speed calls are removed. Remember, comments do take up memory space on your micro:bit RAM, and if you run out you will see a MemmoryError.
# forward_three_seconds_for_fb360_final from cyberbot import * from feedback360 import * # <-- add drive.connect() # <-- add drive.speed(37, 37) # Forward top speed 37 x 3.25mm/s sleep(3000) # Wait three seconds drive.speed(0, 0) # <-- add
Experiment with the speeds to find ones you like. The values of 37 were chosen by taking half of the speed from the original script because the Feedback 360° servos are twice as fast! Your speeds can range between -128 and 128. This example uses 64, which is considerably faster. In fact, that matches the previous servos’ top speeds!
# forward_three_seconds_for_fb360_speed_scaled from cyberbot import * from feedback360 import * # <-- add drive.connect() # <-- add drive.speed(64, 64) # Forward top speed 48 x 3.25mm/s sleep(3000) # Wait three seconds drive.speed(0, 0) # Stop
Even before being updated, the cyber:bot scripts will actually run. Reason being, the Feedback 360° servos do respond to normal servo signals! Without changing anything, the Feedback 360 servos will also exhibit typical continuous rotation servo behaviors, like needing adjustments to speeds to straighten the cyber:bot robot’s path. In contrast, following the instructions below will incorporate the cyber:bot robot board’s feedback360 control system and automatically make the servos turn at the same speeds.
This example demonstrates how to update for servo_speed calls that use variables instead of constants. It will start with the script from the Tethered Terminal Control Script [19] page in Cybersecurity: Navigation Control from a Keyboard. The example with drive.speed(int( vL/2), -int(vR/2) ) will approximately match the wheel speeds to the previous servos. After verifying that it works, we will adjust it to rely on the full Feedback 360° speed range using drive.speed( vL, -vR ), and enter speeds in the -128 to 128 range into the terminal.
You will probably find that the USB cable doesn’t give the cyber:bot with Feedback 360° servos enough range at higher speeds. So, after learning the procedure here, you can also try your hand at updating the scripts from Terminal Control — Go Wireless! [20]
feedback_360_template.hex [16]
# terminal_controlled_bot_tethered_intro_for_fb360 from cyberbot import * from feedback360 import * # <-- add drive.connect() # <-- add sleep(1000) print("\nSpeeds are -100 to 100\n") while(True): text = input("Enter left speed: ") vL = int(text) text = input("Enter right speed: ") vR = int(text) text = input("Enter ms to run: ") ms = int(text) # bot(18).servo_speed(vL) # <-- comment # bot(19).servo_speed(-vR) # <-- comment drive.speed( int(vL/2), -int(-vR/2) ) # <-- add sleep(ms) # bot(18).servo_speed(None) # <-- comment # bot(19).servo_speed(None) # <-- comment drive.speed( 0, 0 ) # <-- add print()
Next, let’s modify the script so that it makes use of the Feedback 360 servos' entire speed range.
Links
[1] https://www.parallax.com/product/32700
[2] https://www.parallax.com/product/parallax-feedback-360-high-speed-servo/
[3] https://learn.parallax.com/tutorials/robot/cyberbot/writing-microbit-programs
[4] https://learn.parallax.com/tutorials/robot/cyberbot/add-modules-your-microbit
[5] https://learn.parallax.com/tutorials/robot/cyberbot/computer-microbit-talk
[6] https://learn.parallax.com/tutorials/robot/cyberbot/build-your-cyberbot-rev-c-board
[7] https://learn.parallax.com/tutorials/robot/cyberbot/navigation-cyberbot
[8] https://learn.parallax.com/sites/default/files/content/cyberbot/F360/cyberbot_feedback_360_diagnostic.hex
[9] https://python.microbit.org/v/2
[10] https://learn.parallax.com/sites/default/files/content/cyberbot/F360/speeds_forward_left_right_backward.hex
[11] http://python.microbit.org/v/2
[12] https://learn.parallax.com/tutorials/robot/cyberbot/how-save-and-reopen-script-python-editor-v2
[13] https://learn.parallax.com/sites/default/files/content/cyberbot/F360/distances_forward_left_right_left_backward.hex
[14] https://learn.parallax.com/tutorials/robot/cyberbot/touch-navigation-cyberbot
[15] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-radio-tilt-control
[16] https://learn.parallax.com/sites/default/files/content/cyberbot/F360/feedback_360_template.hex
[17] https://www.parallax.com/product/cyberbot-robot-kit-with-microbit/
[18] https://learn.parallax.com/tutorials/robot/cyberbot/upgrade-your-cyberbot-feedback-360-servos/swap-and-test-servos
[19] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-start-0
[20] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless