BlocklyProp Robotics with the ActivityBot (Legacy Version)

This tutorial is the Legacy version, that supports the original ActivityBot with external encoders (#32500) and the ActivityBot 360° with Feedback 360° servos (#32600). If you or your classroom has only ActivtityBot 360° robots, go to BocklyProp with the ActivityBot 360° [1]instead.

Dive into robotics, graphical programming, and electronics with the ActivityBot robot and BlocklyProp graphical programming! This tutorial will show you how.

What It Is About

This tutorial set will show you how to:

Assemble your robot and wire up its motors and encoders.

Make BlocklyProp graphical programs to control your robot.

Build DIY sensor circuits on your robot enabling it to navigate on its own.

Along the way, you will learn some robotics, engineering, electronics, and programming concepts that you can apply to your inventions.

After You Finish

Once you have completed the entirety of these ActivityBot tutorials, you will be able to make your robot navigate on its own with different kinds of sensors. You will be ready to create new challenges for your robot and to add a variety of sensors and accessories to help with those challenges.

Build the ActivityBot

If your Propeller ActivityBot belongs to a school, it may have been put together already.

Original ActivityBot Robot Kit (#32500)

ActivityBot 360° Robot Kit (#32600)

This kit has Parallax Feedback 360° High-Speed Servos. This servo has a white-red-black 3-wire cable along with a separate yellow wire for sending feedback signals. It does not use external encoders, as these servos have encoder sensors built right inside the case. Look for instructions mentioning "Feedback 360° servos."

Other Hardware

You will use these pieces during the hardware assembly.

Save for Later

You will not need these pieces for the hardware assembly, so you can set them aside and save them for later activities.

Step 1 - Prepare External Encoders

Prepare the External Encoders

These parts are bagged together as the ActivityBot Encoder Kit. Save the resistors; you will need them later for Electrical Connections.

Parts needed for this step:

(2) sharp infrared sensor (#350-00038)

(2) cable for encoders (#805-28107)

(2) encoder bracket (#721-00031)

Assemble the right and left encoders to be mirror images of each other.

Place an encoder sensor on each encoder plate, with the cable socket facing the hook end.

Secure each sensor to its plate with a black 1/4" screw. It will not need a nut to secure it - the plastic plate will hold it in place.

Push the white plug end of an encoder cable into each sensor's socket. It should only insert one way; make sure it seats in all the way.

Step 2 - Prepare Tires

Preparing the Wheels and Tires

For all ActivityBot robot kits.

Parts needed for this step:

(2) ActivityBot Encoder Wheels (#721-00021)

(2) O-ring tires (#710-00200)

Stretch a tire over each wheel, and settle it into the groove between the lines of tread nubs.

Step 3 - Prepare Chassis

Chassis Preparation

For all ActivityBot Robots.

Parts needed for this step:

Chassis (#700-00022)

Grommet (#700-00025)

(2) 1/4" pan-head screws (#700-00028)

(2) 1-inch long round standoffs (#700-00060)

Push the rubber grommet through the round hole in the chassis. A groove in the grommet should fit over the edge of the metal, leaving a ring visible on both sides.

Attach a 1-inch standoff to each outer-most hole in the front of the robot chassis. Use a 1/4-inch pan-head metal screw (these have a little dome on top with an x for the Philips-tip screwdriver). Insert the screw from underneath and twist the standoff on to it from the top.

Prepared chassis:

Step 4 - Prepare Servos

Prepare the Servos for Mounting

For all ActivityBot robots, whether you have High-Speed Servos with X-shaped horns (#900-00025) or Feedback 360° servos with O-shaped horns (#900-00360).

Using the screwdriver that came with the kit, carefully remove the black screw from the center of each servo horn.

SAVE THE SCREWS! You will need them again later.

Pull each servo horn straight up and off of its servo spline, and set the horns aside.

Step 5 - Mount Right Servo

Mounting the Right servo in the Chassis

For all ActivityBot robots, but read carefully. Directions are slightly different for robots with external encoders.

Mount the Right External Encoder

Position the right encoder assembly over the right servo on the outside of the chassis. The cable should point backward toward the grommet hole.

Secure the right encoder using two 3/8" screws and lock-nuts. Each screw will thread through the encoder, the chassis, and then the servo mounting tab. It helps to use the closed end of the small wrench to hold the nuts in place.

Mount the Left External Encoder

Position the left encoder assembly over the left servo on the outside of the chassis. The cable should point backward toward the grommet hole.

Secure the left encoder using two 3/8" screws and lock-nuts. Each screw will thread through the encoder, the chassis, and then the servo mounting tab. It helps to use the closed end of the small wrench to hold the nuts in place.

Step 9 - Mount Battery Pack

Mounting the Battery Pack

For All ActivityBot robots.

Parts needed for this step:

(1) battery pack, 5-cell AA (#753-00007)

(2) white nylon flat-head slotted screws (#710-00046)

(2) 1-inch round aluminum standoffs (#700-00060

Thread all the servo cables through the grommet hole to the top of the chassis to keep them out of the way.

Insert the battery pack inside the chassis with its plug end toward the grommet hole.

The fit will be tight. You may need to insert one side and then push on the other side to snap it into place.

Find two WHITE NYLON flat-head screws.

Insert these screws into the holes inside of the battery pack that is closest to the corners, and out through the chassis.

GENTLY twist a 1-inch metal standoff into each screw to hold it in place. Make it just snug but do not over-tighten or you may strip the screws.

Thread the battery pack cable through the grommet hole to the top of the chassis.

Step 10 - Mount Tail Wheel

Mounting the Tail Wheel Ball

For all ActivityBot robots.

Parts needed for this step:

(1) Cotter pin (#700-00023)

(1) tail wheel ball (#700-00009)

needle-nose pliers - optional, not included

CAUTION - the ends of the cotter pin may be sharp! If you have needle-nose pliers, you can bend the cotter pin ends into a circle to tuck away the points. But be aware that this makes the cotter pin more difficult to remove in the future if you ever want to do that.

Position the tail wheel ball in the arch in the back of the chassis so that its holes line up with the holes in the little tabs.

Insert the cotter pin through the chassis mounting tab hole, through the tail wheel ball, and then through the other tab.

Bend the ends of the cotter pins outwards to secure it in place.

Step 11 - Mount Drive Wheels

Attach the Prepared Wheels to the Servos

This step is for all ActivityBot robots.

Parts needed for this step:

(2) black servo screws you saved from an earlier step

(2) prepared wheels with tires

Gently push the center of a wheel onto each servo shaft spline.

Secure each wheel to its servo with a black servo screw.

When you finish, you can turn your robot right-side up.

Step 12 - Mount the Activity Board

Mounting the Propeller Activity Board WX

For all ActivityBot robot kits.

Parts needed for this step:

Propeller Activity Board WX (#32912) or original (#32910)

(2) 1/4-inch pan-head screws (##700-00028)

(2) 7/8-inch pan-head screws (#710-00007)

(2) white nylon washers (#700-00015)

(2) 1/2-inch round alumninum spacers (#713-00007)

Rest the Propeller Activity Board over the robot chassis on top of the four standoffs, aligning its corner mounting holes with the standoffs.

The white breadboard should be near the front of the ActivityBot, NOT over the tail wheel ball at the rear.

Put a 1/4-inch screw through the each of the board's rear mounting holes, and secure to the rear standoffs.

Slip a white nylon washer over two of the 7/8-inch screws.

Slip a 1/2-inch metal spacer over each of those same 7/8-inch screws.

Secure the Activity Boards' two front mounting holes to the front standoffs with those same 7/8-inch screws.

Electrical Connections

Gather the Parts

For this construction step, you will need:

Assembled robot

(2) 20 k-ohm resistors (red-black-orange) ONLY if your robot has the external encoders.

(5) 1.5 V AA batteries - don't put them in yet!

Needle-nose pliers - optional, but helpful

Masking tape

Pen

Make sure to use (5) 1.5 V AA batteries!
The ActivityBot's High-Speed Continuous Rotation Servos or Feedback 360° servos need 6 to 8 volts. Its five cell holder is designed for five alkaline cells because 5 x 1.5 V = 7.5 V. It's true that new and unused 1.5 V alkaline batteries can at times have a small amount of excess voltage. Therefore, five of these batteries can add up to 8.2 V, however, exceeding by only 0.2 V will not harm the servos in any way.
The output of an alternate DC (direct current) voltage supply should be measured to make sure it has the correct supply range before using it to avoid potentially damaging the servos.

Label the Cables

Put a masking tape label on the end of each encoder cable and servo cable, near the 3-pin socket.

Trace each cable back to its origin to see where it is connected.

Label each cable Right or Left, Encoder or Servo.

Prepare the Servo Ports

Each pair of 3-pin servo ports along the top of the Propeller Activity Board (original or WX version) has a shunt jumper on power-select pins to its immediate left.

Important! Make sure there is no USB cable or battery pack cable plugged into the board - moving jumpers with power connected could damage your board.

Unplug the USB cable and battery pack if you have either of them plugged into the board.

Move the shunt jumpers into the configuration shown below. Tip: If your jumpers do not have a little tab on them, needle-nose pliers will help.

P12 & P13: VIN
P14 & P15: 5V
P16 & P17, 5V

Plug In the Cables

The servos and the external encoders have 3-wire cables: white = signal, red = power, black = ground. When plugging these cables into servo headers, be sure to align white wires with the P12 & P13 labels along the edge of the PCB, and the black wires along the row labeled GND (see the picture below).

The Feedback 360° servo also has a single yellow encoder feedback signal wire, which plugs into a separate servo header's I/O pin.

Plug the servo's white-red-black cables into these servo ports
P12: Left Servo
P13: Right Servo

Plug the encoders into these servo ports, making sure the white or yellow signal line connects to the port's I/O pin, right by the P14 & P15 labels near the edge of the PCB.
P14: Left Encoder
P15: Right Encoder

ONLY IF YOU ARE USING EXTERNAL ENCODERS, use 20 k-ohm resistors to connect the P14 and P15 sockets to the left of the white breadboard to the 3.3 V power sockets just above the breadboard.

Insert the Batteries

Congratulations, construction is complete!

Keep following the links below to set up your software and start programming.

Software and Programming Check

It's time to program your ActivityBot! If you have done the prerequisite tutorials listed on the first page of this online book, then you already have a BlocklyProp account and some experience with programming your Propeller Activity Board. If not, you must get that done before moving forward. Here are the prerequisite tutorials:

BlocklyProp Programming Tool

BlocklyProp is a graphical online programming tool for the Propeller microcontroller.

BlocklyProp Functions and Multicore

This tutorial shows you how to build functions - reusable chunks of code - with blocks. Then, it explains what multicore means, and how to launch these functions into different Propeller chip cores so they can run at the same time. It's a powerful tool for robotics - one that is beneficial to understand before you go further.

Circuit Training

It's tempting to dive right into robot navigation. We understand! But, as with any vehicle, it's wise to get familiar with the controls before attempting to drive.

In this section you will:

Take a look at your Propeller Activity Board's features

Take a closer look at the power switch and breadboard

Try blinking the built-in light-emitting diodes

Add a piezo speaker to your board and make it beep

Know your Board

Take a quick tour of the Propeller Activity Board (original or WX version) to get acquainted (or re-acquainted) with its features. You've already connected cables to the servo ports and have plugged the battery pack into the power jack. You've been programming it a bit already, so you have been using the USB port.

Check the label on your board, and read more about its features below.

Propeller Activity Board WX (#32912)

Rev B/C

Rev A

Propeller Activity Board (Original, #32910)

Next, let's take a closer look at two features in particular: the power switch and the breadboard. These features are found on both versions of the Activity Board.

Follow the links below to continue with the ActivityBot tutorial.

Power & Connect Circuits

The 3-Position Power Switch

All versions of the Propeller Activity Board have a 3-position power switch:

Position 0 — for building and modifying circuits. Position 0 turns off power to the circuits on the board. (If you plug your board into a USB port, you might see little lights near the USB connector, since it is receiving power from your computer).

Position 1 — for programming and breadboard circuits. Position 1 connects power to most of the board, including the black sockets along the three edges of the white breadboard where you build circuits. It does NOT connect power to the 3-pin servo ports labeled P12-P17 that are above the white breadboard. Put the switch in Position 1 before loading a navigation program that will make the robot's wheels turn, and then load the program into EEPROM. This will keep the robot from driving off the table as soon as the program is loaded.

Position 2 — for making the ActivityBot move. Position 2 powers all the circuits on the board, including the 3-pin servo ports labeled P12-P17. After loading a navigation program into EEPROM, you can put the robot on the floor, hold the reset button down, and put the switch in position 2. When you let go of the reset button, the program will start running and the robot will drive in the (hopefully) safe place you placed it.

The Breadboard

The breadboard lets you build your own circuits with common electronic components. It's a great way to learn about electricity, and to experiment with making your own inventions. Building experimental circuits to design your own projects is called prototyping, and it is a real-world engineering skill.

The Propeller Activity Board's breadboard is surrounded on three sides by black sockets. These make it convenient to connect circuits on the breadboard to power, ground, and the Propeller I/O pins. There are also sockets to connect to a digital-to-analog converter and an analog-to-digital converter.

If you have never built circuits on a breadboard before, watch this video about breadboards and how to build circuits on them. History can be pretty interesting!

Follow the links below to continue with the ActivityBot tutorial.

Blink Lights

Your Activity Board has two built-in light-emitting diodes (LEDs) near the bottom-right corner of the board. They are already electrically connected to Propeller I/O pins P26 and P27. These LEDs are helpful when developing applications that use sensors. The idea is to build a program that turns on an LED when a sensor is activated. Then you, the roboticist, can get a quick visual cue that the sensor is actually detecting something.

I/O Pins

The Propeller microcontroller has 32 input/output pins, or I/O pins, labeled P0 through P31. The Propeller can interact with other circuits connected to these I/O pins, through programs that use these labels. A Propeller I/O pin can do three things:

Connect a circuit to 3.3 V supply, as shown below left. This is known as setting the pin to "output high."

Connect a circuit to 0 V, that is, ground, as shown below right. This is setting the pin to "output low."

Just monitor a circuit to see if it is already connected to 0 V, or 3.3 V. This is called setting the pin to an "input"

We'll experiment with the "O" (output) feature of an I/O pin by programming the Propeller to turn a light on and off. The light circuit, which includes a small LED and resistor, is already built into the Propeller Activity Board (original or WX) or the Propeller Board of Education.

Built-in LEDs

Locate the small LED light on your board. It's a small part just above the P26 label in the lower-right corner of the Propeller Board of Education.

Test Code

In BlocklyProp, you can turn an LED on or off with a single block: the Pin states category's make PIN block.

Log into your BlocklyProp account, connect your board to your computer, and make sure the BlocklyProp Client is running.

Start a new project for your board, and build the project shown above in the workspace.

Save your project, and click the Run Once button.

Verify that the P26 light turns on for half a second, then off for half a second, over and over again.

How it Works

The first make PIN block sets the Propeller chip's P26 I/O pin to output-high, which connects the pin to its 3.3 V supply. The pin applies 3.3 V of electrical pressure to the LED circuit, causing electric current to pass through it and the light to turn on. After that, pause(500) makes the program do nothing for 500 ms, which keeps the light on for half of a second.

Next, low(26) sets P26 to output-low, which connects the pin to its 0 V ground supply voltage instead. This takes away the electrical pressure, so the current stops flowing through the circuit and the light turns off. Another pause(500) makes the light stay off for half of a second.

Did You Know?

The picture below is called a timing diagram. It is a graph with voltage on the vertical axis, and time on the horizontal axis. Timing diagrams are often used to describe the electrical interaction between microcontrollers and circuits or other devices. This timing diagram shows the output of I/O pin P26 from the test code above.

Try This

You can make the light blink faster or slower by changing the value in the pause block. You can also make the on-time different from the off-time by using different values in the two pause blocks.

Modify the program so the LED blinks twice as fast, as shown by the example code and timing diagram below. What happened to the pause values?

Modify the program so the LED is on three times as long as it is off. What happened to the pause values?

Your Turn

Try controlling the P27 light along with the P26 light, according to the timing diagrams below.

Add blocks to your program so that the P27 light turns on and off at about the same time as the P26 light.

Modify the program so that whenever the P26 light is on, the P27 light is off, and vice versa.

Make a Beep

The first breadboard circuit we'll build for the ActivityBot is a simple piezo speaker. Many devices in our daily lives use beeps to communicate with us, such as microwave ovens, car locks, smoke detectors, forklifts driving in reverse—can you think of more examples? Likewise, it is useful to equip your ActivityBot to communicate with you via sound.

Circuit

Inside the piezo speaker is a thin piece of material called a piezoelectric element that deforms when voltage is applied to it, and returns to its original shape afterwards. When voltage is switched on/off rapidly, the vibration emits a tone. The faster the switching frequency, the higher the tone produced. A Propeller I/O pin can provide this rapidly toggling voltage at specific rates.

Parts

(1) Piezo speaker (#900-00001)
(2) Jumper wires

Build the piezo speaker circuit in the exact position on your ActivityBot's breadboard, as shown below. This will leave room to add a variety of sensor circuits later on.

Make sure the piezo speaker pin under the (+) sign on the case goes into the same breadboard row as the jumper wire connected to the P4 socket.

Make sure the other speaker pin is in a different row, with a jumper wire connected to GND.

Test Code

The Audio > Frequency out block can make piezospeaker beep.

Log into your BlocklyProp account, and make a new project for your board.

From the Audio menu, select the Frequency out block.

Set the block's fields as shown below.

Click Run Once (Load to RAM), and verify that the speaker made a one-second beep.

How it Works

The Frequency out block has three fields to set. PIN specifies the Propeller I/O pin connected to the piezospeaker, 4 in our circuit. The duration field sets how long the beep will last, 1000 ms (1 second) in this example. The frequency (Hz) field sets the pitch of the beep, 3000 Hz in this example. To generate this frequency, the Propeller sets P4 to an output and rapidy toggles it between 0 V to 3.3 V, causing the piezoelectric element inside the speaker to vibrate 3000 times per second. The result is a high-pitched tone.

Did You Know?

Know when you are low — A brownout indicator signals to you, the roboticist, when your ActivityBot's batteries are running low. If the battery voltage drops too low, the Propeller microcontroller will reset and restart the program. This can look like a programming or circuit error if you don't know it is happening! So, you will see this block at the beginning of any ActivityBot example program that is meant to make the robot move. A low-battery beep will help you troubleshoot your ActivityBot projects by ruling out low battery power as the culprit.

What is a brownout? - You may be familiar with the word blackout; a blackout is when power dies comepletely, like when the power goes out in your home. A brownout means that there is still power, just not enough to make everything work.

Try This

The Frequency out block's duration (ms) and frequency (Hz) fields can accept use variable blocks and even Operators > Numbers category blocks, as well as the default number value blocks. Sometimes it is fun or useful to have a tone vary in correlation to some sensor's input values, so you can know what the ActivityBot is sensing. For now let's just play with the idea using a variable that's counting loops in a repeat item block.

Modify your project to match the one below, and save it.

Click Run Once (Load to RAM), and you should hear 10 increasingly higher-pitched tones.

Your Turn

Modify your project so that the duration of each tone changes each time through the loop, becoming shorter as the frequency increases.

Navigation Basics

This section shows you how to make your ActivityBot move. It covers:

Testing your servo/encoder system

Testing and tuning the system for optimal performance

How to drive a specific speed

How to drive a specific distance

Get Oriented

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.

Readying your Robot

Directions for testing your electrical connections are different for Feedback 360° servos and external encoders.

To get started, follow the links below for your particular robot.

Feedback 360° Servo Test

Only for FEEDBACK 360° SERVOS
If you are using external encoders, go to External Encoder Test[16] instead.

It's time to test your Feedback 360° servos' encoder signal connections, to make sure they are in 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.

Log into your BlocklyProp account, and run the BlocklyProp Client on your computer.

Create a new project, named Test Encoders.

Build the project shown below. Be sure to set the Robot initialize block's drop-down menu to ActivityBot 360°.

Turn the robot's power switch (PWR) to Position 2.

Click the Load and Run button.

With your hand, gently twist the ActivityBot's left wheel. This movement should make the P26 LED turn on and off as you rotate the wheel.

Repeat for the right wheel. Turning the right wheel should make the P27 LED turn on and off.

If It Doesn't Work

Here are some symptoms and causes:

P26 light stays off while turning the left wheel.

The left feedback signal wire may be plugged into the wrong pin on the P14 servo port.

The left feedback signal wire may be plugged into the P15 servo port instead.

The left servo's 3-pin cable might be plugged in backward.

The shunt jumper might be missing or incorrectly set on the voltage selector pins next to the P12/P13 servo port.

P27 light stays off while turning the right wheel.

The right feedback signal wire may be plugged into the wrong pin on the P15 servo port.

The right feedback signal wire may be plugged into the P14 servo port instead.

The right servo's 3-pin cable might be plugged in backward.

The shunt jumper might be missing or incorrectly set on the voltage selector pins next to the P12/P13 servo port.

If Both Encoders Work

Feedback 360° Encoder Calibration

Only for FEEDBACK 360° SERVOS!
If you are using external encoders, go to External Encoder Calibration[18] instead.
If your ActivityBot is using Feedback 360° servos, calibration is optional, but it will improve the accuracy of driving maneuvers. This one-time calibration aids the Robot blocks in measuring and correcting distances and speeds, using information from the servo's feedback connection.

Circuit

Test Code

The calibration code takes about one 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 it's done by turning off its P26 and P27 lights (below the breadboard). This video shows an ActivityBot correctly performing the calibration.

IMPORTANT! USE FRESH BATTERIES FOR THIS STEP!

Log into your BlocklyProp account, and run and connect the BlocklyProp client on your computer.

Set the ActivityBot's power switch to 1, and connect it to your computer via the USB cable.

Start a new project for the Activity Board.

From the ROBOT block menu, place the ActivityBot calibrate block in the workspace, and choose ActivityBot 360° from the drop-down menu.

Click the Load and Run button. (Important: this program needs to be in EEPROM.)

When the program is finished loading, the P26 and P27 lights will turn on. When they come on, turn off the robot's power (slide power switch to 0).

Disconnect the ActivityBot from its programming cable and set it in a 1-meter square (3 ft. x 3 ft.), obstacle-free, smooth floor area.

Set the power switch to 2 and move back to give it room to spin in place and slowly roam while it gathers wheel speed data.

Leave it alone until the P26 and P27 lights turn off. After that, calibration is complete, and you can turn the power off again.

IMPORTANT: Complete the Try This section on this page before doing anything else with your ActivityBot.

What if it didn't work?
If your robot did not move when you started the calibration program, or it started going backward first instead of forward, or if it started and stopped right away or just twitched, then double-check your electrical connections. You may have a servo cable or feedback signal wire plugged in incorrectly.

What if I need to restart or repeat the calibration?
To restart the calibration process, 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 reload the program. That is because the program modifies itself at the end so that it cannot run a second time, which keeps your ActivityBot from trying to recalibrate the next time you turn power on to load a new program.

How it Works

Notice that the ActivityBot calibrate block does not have any sockets or plugs for connecting it to other blocks. It is meant to be used by itself without any other blocks in a program, and it takes care of the entire calibration process automatically.

The ActivityBot calibrate block collects requested speed vs. measured speed data and stores it in a part of the Activity Board’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.

Later, when your project includes Robot blocks that set a certain wheel speed, the underlying code will use the calibration data from EEPROM to start driving the motors at speeds close to what your program asks. That way the code doesn’t have to make large corrections, just small ones, which improves overall accuracy.

Did You Know?

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 tickmeans 1/64th of a wheel revolution. When the wheel makes one complete revolution, it has rotated 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[20].)

Try This

There is 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, then it will tell you what problem(s) it detects. After finding and fixing the problem, make sure to run both the calibration and this test again. Your ActivityBot will not be ready for navigation until it is calibrated AND it passes this test!

Set the ActivityBot's power switch to 0, and reconnect the USB cable.

Replace the ActivityBot calibrate block with the ActivityBot display calibrationblock, and set the drop-down menu to ActivityBot 360°.

Set the power switch back to 1, then click the Load and run (save to EEPROM)button.

Check the Terminal output.

If the Terminal output says "...calibration completed successfully", then 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.

If the results in the Terminal say "...one or more problems were detected", it means that there is probably a mistake in the servo, encoder, or power connections.

Make a note of the details that the Terminal reported. Then, find those details on the Troubleshooting[21] page, and follow the instructions it provides for solving the problem.

When you find and fix the first problem, rerun the calibration program above. Then, rerun this test. Repeat until you get the "...calibration completed successfully" message.

Your Turn

Now that you have successfully calibrated your ActivityBot, it is time to run a simple test program to make it drive straight forward. The test code below makes both wheels rotate forward at 64 encoder ticks per second for 5 seconds, which should make your ActivityBot roll forward about 1 meter (3 ft.).

Build the project shown below.

Be sure to set the drop-down menu in the first block to ActivityBot 360°.

Reconnect your ActivityBot to your computer with the USB cable, and set the power switch to 1.

Set the COM port, then click the Load and run (save to EEPROM) button.

After the program loads, set the power switch to 0 and disconnect the USB cable.

While holding the reset button down, set the power switch to 2, and set the robot down on a hard, smooth floor.

Release the reset button, and monitor the robot’s travel.

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.

How it Works

The first block is Robot initialize, with the drop-down menu set to ActivityBot 360°. Place this block at the beginning of all projects that use other Robot set or Robot drive blocks, even if the example shown is set to ActivityBot.

Next is aRobot drive speed block with the number value 64 attached to both its left and right sockets. This makes both the left wheel and right wheel rotate forward at a rate of 64 ticks per second. The pause 5000 block allows the ActivityBot to drive forward at this rate for 5000 ms (5 seconds). After that, a secondRobot drive speedblock stops the right and left wheels with the number values 0, 0. We will explore this next.

External Encoder Test

It's time to test your robot's external encoder signal connections to make sure they are in proper working order. This test is essential before trying any navigation programs. Each external encoder sensor can see the spokes in the wheel right next to it. If the external encoder is working correctly, a built-in LED on the Activity Board will turn on each time it detects a spoke, and turn off when the hole between the spokes passes by.

Log into your BlocklyProp account, and run the BlocklyProp Client on your computer.

Create a new project, named Test Encoders.

Build the project shown below.

Turn the robot's power switch to position 2.

Click the Load and run (save to EEPROM) button.

With your hand, gently twist the ActivityBot's left wheel, which should make the P26 LED turn on and off as you rotate the wheel.

Repeat for the right wheel. Turning the right wheel should make the P27 LED turn on and off.

If It Doesn't Work...

Here are some symptoms and causes:

P26 light stays off while turning the left wheel.

The left encoder cable may be plugged into the P14 servo port backward.

The 20 k-ohm resistor (red-black-orange) may not be making contact at either the P14 or 3.3 V socket.

The left encoder may be mounted with the sensor facing the chassis instead of facing the wheel spokes.

The shunt jumper may be missing from the power selector pins next to the P14 & P15 servo ports.

P27 light stays off while turning the right wheel.

The right encoder cable may be plugged into the P15 servo port backward.

The 20 k-ohm resistor (red-black-orange) may not be making contact at either the P15 or 3.3 V socket.

The right encoder may be mounted with the sensor facing the chassis instead of facing the wheel spokes.

The shunt jumper may be missing from the power selector pins next to the P14 & P15 servo ports.

The encoder cables are swapped! Switch the encoder cables plugged into P14 and P15.

P26 or P27 light stays on while turning a wheel.

Resistor connecting P14 or P15 socket to 3.3 V socket is too small. It should be 20 k-ohm (red-black-orange-gold). This resistor came in the bag with the encoder parts, not with the rest of the resistors in the kit.

The encoder's light stays on all of the time, or most of the time but occasionally flickers off.

The encoder might be mounted so that the sensor faces inward toward the chassis instead of outward toward the wheel spokes. Un-mount and swap them, so they face outward.

You may need to adjust the bracket position. For kits made before October 2013, the encoder bracket may be mounted just out of alignment, so it sees the rim below the spokes instead of the spaces in between the spokes. If there is a gap between the bottom of the servo case and the lower edge of the chassis mounting hole, this is likely the problem. It is easily corrected by loosening the servo screws slightly, then retightening while at the same time pulling the encoder bracket and servo away from each other.

Both P26 and P27 stay on at all times during the test

The jumper for P14 & P15 may be faulty, or not making the proper connection. Make sure it is pressed all the way on to the pins, and that it is not cracked, loose, or otherwise damaged.

WARNING: If any of your jumpers are damaged, contact technical support (support@parallax.com) and do not apply power to the affected headers!

If Both Encoders Work

Congratulations! It is time to calibrate your ActivityBot.

Follow the links below to continue.

External Encoder Calibration

If your ActivityBot has external encoders, you MUST calibrate it before running any other example programs. This one-time calibration is necessary for the Robot blocks to measure and correct distances and speeds, using information from the ActivityBot encoders.

Circuit

If you have not already completed the Electrical Connections[19] tutorial, do that first and then return here.

Test Code

The calibration code takes less than 2 minutes to collect all of its data. You will need a smooth and obstacle-free, floor area that is roughly 1-meter square (3 ft. x 3 ft.). 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 it's done by turning off its P26 and P27 lights (below the breadboard). The video below shows an ActivityBot correctly performing the calibration.

IMPORTANT! USE FRESH BATTERIES FOR THIS STEP!

Log into your BlocklyProp account, and run and connect the BlocklyProp client on your computer.

Set the ActivityBot's power switch to 1, and connect it to your computer via the USB cable.

Start a new Propeller C project for the Activity Board.

From the ROBOT block menu, place the ActivityBot calibrate block in the workspace.

Click the Load and run (save to EEPROM) button. (Important: this program needs to be in EEPROM.)

When the program is finished loading, the P26 and P27 lights will turn on. When they come on, turn off the robot's power by sliding the power switch to 0.

Disconnect the ActivityBot from its programming cable and set it in a 1-meter square (3 ft. x 3 ft.), obstacle-free, smooth floor area.

Set the power switch to 2 and move back to give it room to spin in place and slowly roam while it gathers wheel speed data.

Leave it alone until the P26 and P27 lights turn off (about 2 minutes). After that, calibration is complete, and you can turn the power off again.

IMPORTANT: Complete the Try This section on this page before doing anything else with your ActivityBot.

What if it didn't work?
If your robot did not move when you started the calibration program, or it started going backward first instead of forward, or if it started and stopped right away or just twitched, go to the Troubleshooting[21] page for help.

What if I need to restart or repeat the calibration?
To restart the calibration process, 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 reload 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 recalibrate the next time you turn power on to load a new program.

How it Works

Notice that the ActivityBot calibrate block does not have any sockets or plugs for connecting it to other blocks. It is meant to be used by itself without any other blocks in a program, and it takes care of the entire calibration process automatically.

The ActivityBot calibrate block collects requested speed vs. measured speed data and stores it in a part of the Activity Board’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.

Later, when your project includes Robot blocks that set a certain wheel speed, the underlying code will use the calibration data from EEPROM to start driving the motors at speeds close to what your program asks. That way, the code doesn’t have to make large corrections, just small ones, which improves overall accuracy.

Did You Know?

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 used to describe the ActivityBot's wheels turning. In this context, a tickmeans 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.

ActivityBot External Encoders — Each ActivityBot external encoder shines infrared light at the ring of 32 spokes in the wheel next to it. If the light passes between these spokes, then the encoder sends the Propeller a high signal. If it bounces off a spoke and reflects back onto the encoder’s light sensor, then 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. You may also see the term encoder increment.

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. BlocklyProp blocks keep track of all this for you, so your programs need to tell the robot only how far or how fast to go.

Interpolation — The calibration code builds a table of data points for motor drive level and the actual speed the wheels turned, and stores it in the Activity Board's EEPROM memory. Other Robot blocks will use those data points to figure out how hard to drive a wheel to get a certain speed. If the speed the block asks for is between two data points, then the underlying C libraries will calculate the best drive value between the two of them. For example, if the table has data points for 60 and 80 encoder ticks per second, and your block asks for 70 ticks per second, the underlying libraries will use a motor drive level that’s halfway between the 60 and 80 ticks per second levels. This process is called interpolation, and the data set is called a linear interpolation table.

Try This

There is 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, then it will tell you what problem(s) it has 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 is both calibrated AND passes this test!

Set the ActivityBot's power switch to 0, and reconnect the USB cable.

Create a new project and drag an ActivityBot display calibrationblock into the workspace.

Set the power switch back to 1, then click the Load and run (save to EEPROM) button.

Check the Terminal output.

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.

If the results in the Terminal say "...one or more problems were detected", it means that there is probably a mistake in the servo, encoder, or power connections.
(If this is the case, your ActivityBot IS NOT READY to run navigation programs yet.)

Make a note of the details the Terminal reported. Then, find those details on the Troubleshooting[21] page, and follow the instructions it provides for solving the problem.

When you find and fix the first problem, you will need to rerun the calibration program (above). Then, rerun this test. Repeat until you get the "...calibration completed successfully" message.

Your Turn

Now that your ActivityBot is 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 5 seconds. This code should make your ActivityBot roll forward about 1 meter (3 ft.).

Build the project shown below.

Reconnect your ActivityBot to your computer with the USB cable, and set the power switch to 1.

Set the COM port, then click the Load and run (save to EEPROM) button.

After the program is loaded, set the power switch to 0 and disconnect the USB cable.

While holding the reset button down, set the power switch to 2, and place the robot down on a hard, smooth floor.

Release the reset button, and monitor the robot’s travel.

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.

How it Works

The first block is Robot initialize, with the drop-down menu set to ActivityBot. Place this block at the beginning of all projects that use Robot set... or Robot drive... blocks. Next is aRobot drive speedblock with the number value 64 attached to both its left and right sockets, making both the left wheel and right wheel rotate forward at a rate of 64 ticks per second. The pause 5000 block lets the ActivityBot drive forward at this rate for 5000 ms (5 seconds). After that, a secondRobot drive speedblock stops the right and left wheels with the number values 0, 0. We will explore this more on the next page.

What if it Didn't Work? If your robot did not move, or went backward, or moved in a series of short, jerky arcs instead of heading forward, see the Troubleshooting[21] page.

Driving Distances

The Robot drive distance block tells the ActivityBot how far each wheel should turn. It is intended for projects where the goal is to drive specific distances and turn specific angles. You can use positive values for forward distances and negative values for backward ones. The default distance unit for Robot drive distance is 3.25 mm ticks. Inches and centimeters are also options in the drop-down menu. The example below shows how to make the ActivityBot roll forward 208 mm by setting the left and right distances for 64 ticks. We've used this value because 64 x 3.25 mm = 208 mm.

The direction the Robot drive distance block will make the ActivityBot move is:

Forward with positive distance values

Backward with negative distance values

Turn right with a positive left distance value and a negative right distance value

Turn left with a negative left distance value and a positive right distance value

Here are some examples – look carefully at the sign (+/-) of each value:

An easy way to remember turns is to make the wheel on the side you want the ActivityBot to turn to go backward (negative value).

Encoder Ticks and the ActivityBot Wheel

The ActivityBot's wheel circumference is 208 mm, so a full turn makes the wheel travel that far. A single tick is equal to 1/64th of a full turn, and 1/64th of 208 mm works out to 3.25 mm.

If you know how far you want your ActivityBot to roll, you could 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

Encoder Ticks and Turning Radius

The ActivityBot’s pivot turning radius is the distance between the wheels. Ideally, it's 105.8 mm, but that will vary slightly with the shape of each aluminum chassis and also with how the servos are mounted. The left wheel will have to turn 2 × π × r to make the ActivityBot pivot by a full circle while holding the right wheel still. 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 1/4 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. That's the distance one wheel has to drive to make the ActivityBot make a 90-degree turn while the other stays still. If you make one wheel go forward 26 ticks, and the other goes backward 25 ticks, that’s still a total of 51 ticks for 1/4 of a turn. The difference is that the ActivityBot will rotate in place instead of pivoting around one of its wheels.

Keep in mind that the turning radius will be slightly different for each ActivityBot, so you may have to tune the number of ticks for a 1/4 turn. For example, your ActivityBot's turning radius might need 50, 52, or 53 ticks to get as close as possible to a 1/4 turn.

Test Code

This test code makes the ActivityBot go forward 128 ticks, and then make a 51-tick, 1/4 turn, to face 90- degrees to the right.

In your BlocklyProp account, make a new Propeller Activity Board WX program and name it Drive Distance Ticks.

Build the project shown below, and save it.

Be sure to set the Robot initialize block's drop-down menu to your robot: ActivityBot or ActivityBot 360°.

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold, and release the reset button as you set the power switch to 2.

Verify that the ActivityBot goes forward two full wheel turns, stops, and faces right.

How it Works

First comes the comment block noting the project name. Next, the frequency out block for the piezospeaker on P4 acts as a low-battery brown-out indicator.

After the required Robot ActivityBot initialize block, there are two Robot drive distance in ticks blocks.

The first Robot drive distance block moves both wheels forward with left 128 and right 128. Since 128 is enough ticks for two full wheel revolutions, the forward distance traveled is 3.25 x 128 = 416 mm, or about 16 inches.

The second Robot drive distance block uses left 26 and right -25 to move the wheels in opposite directions. As explained above, that is a combined 51 ticks, causing the ActivityBot to rotate in place to make the ActivityBot turn 90 degrees to the right.

Did You Know?

Drive the distance, no distractions — The Robot drive distance block must complete the wheel turns for its target distance before it stops the motors. Only then will it allow the cog's code execution to continue to the next block. This behavior is called blocking, meaning that it makes the cog wait until it is complete before allowing the program the cog is running to continue. It's a lot like pause and frequency out, except that we know precisely how long each of those blocks will take. With Robot drive distance, we don't necessarily know the exact amount of time a given maneuver will take.

Different from the Robot drive speed block — The Robot drive speed block is introduced on another page. Unlike the Robot drive distance block, the Robot drive speed block is non-blocking. It sets the speed and then immediately moves to the next block as it maintains the wheel speeds you have set.

Unit Options — The Robot drive distance block's inches and centimeters options work only with the wheels that come with the ActivityBot robot. If you use wheels with a different circumference, the distance traveled per tick will change.

Line, arc, pivot, rotate in place — The values you use affects the path the ActivityBot takes. Use the same values for a straight line. For example 64, 64 makes the ActivityBot go forward. -64, -64 makes it go backward. Use different values for arcs, like 128, 64. To pivot on one wheel, set one of the two values to 0. To make the ActivityBot rotate in place, use positive values, like 26, -26.

Try This - Shapes

Let's try making the ActivityBot navigate some basic shapes:

Square

By repeating the forward and 90-degree turn maneuver 4 times, the program can make the ActivityBot draw a square.

In BlocklyProp, make a new Propeller Activity Board WX program, and name it Drive Distance Ticks Try This.

Get a repeat forever block from the CONTROL menu.

Change its dropdown from forever to x times.

Get a number block from the VALUES menu, and set it to 4.

Use the number block to set the repeat x times block to repeat 4 times.

Insert your repeat 4 times block just below Robot initialize.

Move the two Robot drive distance blocks into the repeat 4 x times loop.

Be sure to set the Robot initialize block's drop-down menu to your robot: ActivityBot or ActivityBot 360°.

Set the power switch to 1, and then use Load and run (save code to EEPROM) to load the program.

Set the power switch to 0. Take your ActivityBot to a test area, then set the power switch to 1.

Does it draw a square? You might need to adjust the -26 and 25 values to tune the 90-degree turns.

For a larger square, try increasing the 128 values to 150. Or, for a smaller one, reduce to 100.

Triangle

Repeat x times need to change from 4 to 3, and -26 and 25 values need to change to make 120 degree turns instead of 90-degree turns.

Start by changing the (-26 and 25) to -34 and 34

Change repeat 4 x times to repeat 3 x times.

Test to see how close your ActivityBot got to a triangle.

Adjust the turns (-34 and 34) to fine tune. Larger values for a greater turn at each corner, smaller ones for less turn.

Arc and Circle

Here is some arc code.

Try it as-is first.

Also, try values of 256 and 128 instead. What happened?

Test, and then increase the values until it closes a circle.

​

Your Turn

Make a waypoint maze and write a program to navigate from start to finish. Use the speed and acceleration values that work best for your particular robot. Masking tape corridors work well for this.

An example course is shown below. To run this particular course, the ActivityBot must perform the following maneuvers:

From START, go straight 41.6 cm forward to X.

Turn 45 degrees right, and 41.6 cm to the next X.

Turn 90-degrees left, and go 31.2 cm to finish X.

Driving Speeds

Unlike the Robot drive distance block, which is cause for fixed courses and maneuvers, the Robot drive speed block lends itself to navigation with sensors. The simplest way to use it is to attach a number value block to its left and right fields. Each number indicates how fast each wheel should turn in units of ticks per second. Remember, each tick is 1/64th of a wheel turn and moves the ActivityBot's wheel by 3.25 mm. After setting the wheel speeds, the Robot drive speed block allows the cog to execute whatever block comes next immediately. So, if you want your ActivityBot to keep going at a specific speed for a certain amount of time, add a pause (ms) block between Robot drive speed and the next block that sets wheel speeds.

Here are some other tips to remember:

Positive numbers make the ActivityBot wheels move forward.

Negative numbers make the ActivityBot wheels move backward.

0 makes a wheel stay still.

A positive number on one side and negative on the other makes the ActivityBot turn toward the wheel that's negative (going backward).

​

Wheel direction in the rest of this tutorial refers ONLY to turning forward with positive speed values, or backward with negative speed values. It does NOT refer to clockwise or counterclockwise rotation of the individual wheel cause its case. A positive value will cause a wheel to turn in the ActivityBot's forward direction. A negative value will make it turn in the ActivityBot's backward direction.

Speed Control Example

This short example makes the ActivityBot go straight forward at medium speed (64 ticks/s) for 3 seconds. After that, it makes the ActivityBot go backward faster (-96 ticks/s) for 2 s. After that, it stops.

In your BlocklyProp account, make a new Activity Board WX project named Forward Backward Stop.

Build the project shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360° before you save your project.

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold and release the reset button as you set the power switch to 2.

Your ActivityBot should drive forward for 3 seconds, then backward more quickly for 2 seconds.

Did you expect the ActivityBot to return to its exact starting position? It stands to reason since 64 x 3 = 192 and -96 x 2 = -192. In a perfect world, that would be 192 ticks forward followed by 192 ticks backward. In reality, it takes time to speed up during the 3 seconds. During the next 2 seconds, the ActivityBot has to slow down, then speed back up in reverse. So, its reverse distance traveled will be a little less. As was stated previously, when the goal is to travel a certain distance, you should use the Robot drive distance block. It accounts for speeding up, cruising speed, and slowing down. The Robot drive speed block only works to maintain wheel speeds.

How it Works

The comment block holds the project's name. Next, the frequency out block makes a beep on the P4 piezospeaker to let you know the program has started running. The Robot ActivityBot initialize block is required before using other robot navigation blocks. These three blocks will appear together at the top of most programs that make the ActivityBot move.

The next five blocks define the ActivityBot's maneuvers.

The Robot drive speed left 64 right 64 block makes both wheels go forward at 64 ticks (one full turn) per second.

The Robot drive speed left -96 right -96 block makes both wheels go backward at a speed of 96 ticks (1 1/2 turns) per second.

The pause (ms) 2000 block makes the program wait for 2000 ms (two seconds). Meanwhile, the wheels slow down, stop, then speed up to and hold -96 ticks per second velocity.

The Robot drive stop block stops the wheels from turning. Without this block, the ActivityBot would keep backing up indefinitely, even after it comes to the pause block. The Robot drive stop block has the same effect as Robot drive speed left 0 right 0.

Did You Know?

Enforcing the speed limit — No matter what values you attach to Robot drive speedleft and right, the C code underlying BlocklyProp will use a maximum value of +/- 128. For most applications, +/- 96 is a better maximum value. If you want to lower the maximum value, you can put a Robot set max speed block at the top of your project, which can be useful if you attach variables or equations for the left and right speed values.

Just keep on rolling — Robot drive speed is a "set-it-and-forget-it" block. It starts the wheels turning at the chosen speed, and then code execution immediately continues with the next block that follows. The wheels will keep turning at that speed until another Robot drive block changes or stops them.

Speed vs. velocity — 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.

Little things add up— A small variation between what you want your ActivityBot to do and what it does may go unnoticed once or twice, such as going just beyond a target distance or stopping short of a rotation angle. But when these small differences happen one after another, their accumulated effect can be noticeable. Sometimes referred to as error propagation, it is an important concept in robotics, programming, and engineering. And, you may run into it sooner than you think!

Try This

Later, your ActivityBot will have to do things such as executing turns until its obstacle sensor gives the all clear. In that kind of situation, the Robot drive speed block will set the servo speeds to make the ActivityBot turn in place. Since Robot drive speed is "set-it-and-forget-it," the program can immediately move on to blocks that monitor sensors. After the sensor detects an opening, the program can go back to a Robot drive speed block that makes the ActivityBot drive forward again.

So, let's try making the ActivityBot turn in place after going forward by using left 52 and right -52 in the second Robot drive speed block. The left 52 will cause the left wheel to slow slightly, from 64 to 52 ticks per second. The right -52 will cause the left wheel turn backward at 52 ticks per second, making the robot turn right. In this example, we are using a pause (ms) 500 block to make the robot turn in place for a fixed amount of time. Just keep in mind that later, this turning in place time will be determined other things, for example when a sensor detects an opening.

Save a copy of your project and name it Drive Speeds - Try This.

Modify the code by changing the second Robot drive speed block's left value to 52 and its right value to -52.

Change the second pause from 2000 to 500.

Save, load, and test-drive the modified project. Your ActivityBot should go forward for 3 seconds and then turn right.

Try changing the pause (ms) 500 block to pause (ms) 1000. Approximately how much further did the robot turn?

Change the second pause (ms) back to 500, and then change Robot drive speed left 52 right -52 to Robot drive speed left 104 right -104.

What do you think will happen if you use Robot drive speed left -52 right 52? Try it and see.

Your Turn

Without any stops and pauses, the ActivityBot's motions seem to blend. If you ever need motions to be more distinct while using the Robot drive speed block, you can add a Robot drive stop and a short pause (ms) block after each maneuver.

Doing this will give the ActivityBot time to stop after going forward for 3 seconds, and before making the turn.

Can you see the difference?

Another example of something your ActivityBot might do with sensors is to go down a corridor, check for openings to the left and right, and then return. You can make the ActivityBot do this by combining portions of the two example programs on this page.

Modify the program that makes the ActivityBot go:
- Straight ahead for 3 seconds
- Face left
- Face right
- Face forward
- Reverse to about the same start position

Taking Turns

The example program on the previous page moved the ActivityBot's wheels at the same speed but opposite directions - one forward and one backward - to make the robot turn. Other wheel speed/direction combinations perform other kinds of turning maneuvers. Turning maneuvers can be grouped into three general categories:

Rotation turns

Wheel speeds are equal, but velocity is opposite to make the ActivityBot turn about its center. This rotation is great for making the robot face a new direction in a tight place and without changing its position. Imagine a pen going through the center of the ActivityBot's "axle." A rotating turn would not draw any curved lines; it would just rotate on this point making the dot darker! You could think of this as an arc with a radius of zero.

Pivot turns

One wheel turns forward or backward while the other stays still. Now the center of the circle is the wheel that is not moving, and the ActivityBot pivots about this point. An imaginary pen through the center of the robot would draw a circle with a radius equal to half of the ActivityBot's wheelbase of about 106 mm.

Arcs

With arcs, both wheels are turning but at different speeds. They may be moving in the same or opposite directions.

Opposite-direction tight arcs: If the wheels are going in opposite directions, the arc created by our imaginary centroid-pen would have a radius between zero (if the speeds were almost the same like a rotating turn) and 53 mm (if one wheel speed is set to almost zero, like a pivot turn).

Same-direction wide arcs: If the wheels are turning different speeds but the same direction. Going back to the imaginary centroid-pen, the radius of such arcs can be anything from about 53 mm to theoretically infinite. The closer the speeds are to each other, the larger the arc radius will be. (Of course, if the speeds are equal, the trajectory is straight.)

Example Code

This program progresses through the four types of turns described above. The ActivityBot will come to a stop and beep between each type of turn so you can more easily see the relationship between the blocks and the maneuvers.

In your BlocklyProp account, create a new project and name it Taking Turns.

Build the project shown below, and save it.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360°.

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save code to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold and release the reset button as you set the power switch to 2.

How it Works

After the required Robot initialize block, the rest of the code is divided into four sections of five blocks each.

A frequency out block to signal a new maneuver is starting. The frequency (Hz) value is lower each time so you can tell them apart.

A comment block noting the type of turn in that maneuver.

A Robot drive speed block, with the left and right wheel speeds set to perform that particular maneuver.

A pause (ms) 2000 block, which lets each maneuver last for two seconds.

A Robot drive stop block, to end the current maneuver before moving on to the next section.

Did You Know?

Variable Speeds — The Robot drive speed block will accept any block for its left or right fields that resolves into a number value, such as variables and equations. Using a variable for a driving speed can allow the maneuvers to change during runtime without additional blocks. Remember also that the block's underlying C code libraries automatically limit the range to +/- 128, and that you can limit the range further with the Robot set max speed block.

Try This

The following example project keeps one wheel's speed steady while gradually reducing the other with a variable. Can you predict what the maneuver will be like?

Create a new project and name it Taking Turns Try This.

Build the project shown below, and save it.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360°.

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save code to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold and release the reset button as you set the power switch to 2.

Did your ActivityBot do what you predicted?

Your Turn

To thoroughly understand turning maneuvers, make copies of the Taking Turns project under new names, and try the following variations:

Perform all four types of maneuvers turning left instead of turning right.

Perform all four types of maneuvers with the robot moving backward (though, which way is backward for the first one?)

Make each of the four maneuvers drive the ActivityBot for one complete rotation or complete circle. How do the pause times compare to each other?

Modify the last one to increase one wheel speed from 64 to 128. What do you have to do to the pause times to make the ActivityBot complete just one rotation or circle for each maneuver?

Acceleration and Speed Limits

Acceleration is a measurement of how quickly something speeds up or slows down. The ActivityBot's acceleration can be adjusted, which will be important in some robotic applications. For example, if your ActivityBot is bringing you a drink, you could make the acceleration gradual to prevent spills. Another example: if your ActivityBot is in a race, it might be more important to make it speed up as quickly as possible.

The ActivityBot robot's acceleration can be adjusted with the Robot set acceleration for block, which has settings for both distance and speed. The acceleration setting for distance maneuvers is typically slower to help improve accuracy. The acceleration setting for speed is usually a little faster to give the robot more peppy responses in sensor navigation.

You can also configure the speed limits for speed and distance maneuvers. The default speed limit for Robot drive distance maneuvers is 64 ticks per second. That's the cruising speed the ActivityBot reaches while on its way to its distance goal. For transporting a drink, it might be safer to pick a slower cruising speed. In a timed dead reckoning navigation contest, you might want to experiment with higher cruising speeds. The default speed limit for Robot drive speed is 128 ticks per second. Even though your code can change the speed at any time, there are some cases when sensors and variables might work together to ask for some unreasonably high speeds. Limiting the speed can prevent some "runaway" conditions.

Test Code

This example sets the acceleration and cruising speed for Robot drive distance blocks to high values and then makes the ActivityBot travel 265 ticks forward. Then, it sets acceleration to a low value, cuts the cruising speed in half, and backs up the same distance. As you watch the ActivityBot, pay close attention to two things: (1) acceleration - how quickly it speeds up and slows down, and (2) cruising speed - the top speed it runs at for most of the trip.

In your BlocklyProp account, make a new Propeller Activity Board WX program and name it: Set Drive Distance Acceleration and Speeds.

Build the project shown below, and save it.

Be sure to set the Robot to initialize block's drop-down menu to your robot: ActivityBot or ActivityBot 360°.

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save code to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold and release the reset button as you set the power switch to 2.

Watch and verify that the ActivityBot has a high cruising speed on the way out and a lower one on the way back. That is the effect of the Robot set speed (+/-) for distance blocks.

Also watch and verify that the ActivityBot abruptly sped up and slowed down on the way out, and gradually on the way back. That is the effect of the Robot set acceleration for distance blocks.

How it Works

The first block in the program is a comment noting the project name. The second block is frequency out, which makes a piezospeaker tone. If that tone plays in the middle of the program instead of at the beginning, it could indicate that the batteries are low. The third block is the required ActivityBot initialize. Make sure you set this one to match your particular robot - ActivityBot or ActivityBot 360. These first three blocks are used in all example programs that make the ActivityBot move.

Next, Robot set acceleration for distance blocks to 600 ticks/s2 uses a higher acceleration setting to make the ActivityBot speed up and slow down abruptly. The Robot set speed (+/-) for distance blocks 128 sets the top speed. That will be the Robot drive distance block's cruising speed, which is 2 full revolutions per second. After these settings, the first Robot drive distance block makes the ActivityBot go 256 ticks forward. The high acceleration setting causes the ActivityBot to speed up and slow down abruptly, while the high Robot set speed for distance setting directs the ActivityBot to use a high cruising speed to travel the distance.

When your robot completes the first maneuver, the next set of Robot set acceleration and Robot set max speed blocks has lower values. Then, a Robot drive distance block tells the ActivityBot to back up the same distance it just went forward. You will see that with the new acceleration setting, the ActivityBot gradually speeds up and slows down. With the new speed setting, the cruising speed is slower.

Did You Know?

Step on the accelerator — Acceleration is the change in velocity over time. When the robot speeds up or slows down, that's acceleration. Keeping the ActivityBot's motions from being too jerky with sudden starts and stops, the Robot drive speed block gradually starts and stops maneuvers by accelerating and decelerating at a default rate of 600 ticks per second squared. You can change this default rate with the Robot set acceleration block. Be aware though, that it takes time for the robot to accelerate and decelerate, so changing this setting can change distance traveled. Also, be aware that, for individual robots, some combinations of speed and acceleration work better together than others.

Acceleration rules for Robot drive distance — The default acceleration is 200 ticks/s2 when using the Robot drive distance block. To change this default, use the Robot set acceleration for distance block. As above, be aware that increasing the acceleration may reduce distance accuracy. We recommend 200 ticks/s2 for speeds at 64 ticks per second or below, but feel free to experiment with higher values. Of course, results may vary with driving surface and whether your ActivityBot is carrying anything. So, test and tune!

Try This

Setting the acceleration and speed limit for Robot drive speed blocks is about the same as it is for distance. The main difference is that the Robot set max speed block can override a speed you set with the Robot drive speed block. The second Robot drive speed block in this example program tries to set the speed to left -128 and right -128. However, the Robot set max speed block immediately before it prevents the ActivityBot from ever going faster than 64 ticks per second.

Be sure to set the Robot initialize block's drop-down menu to your robot: ActivityBot or ActivityBot 360°.

​

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save code to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold and release the reset button as you set the power switch to 2.

Verify that the ActivityBot's acceleration is abrupt during the forward maneuver and gradual during the backward one.

Can you see how the ActivityBot backs up at half speed (-64 ticks/second) even though the speed block is asking for full speed (-128 ticks per second)?

Your Turn

Let's examine how the program can still think it is telling the ActivityBot to go a certain speed even though the Robot set max speed block has clamped the actual speed to a lower value. The terminal will show the speeds that it's telling the ActivityBot to go, and you can watch and see which speed it reaches.

Run it as-is, and verify that your ActivityBot moves forward at all 7 speeds.

How do you think it will behave if you change the Robot set max speed block to 64? Try it and see.

Navigate with Touch

Detect Obstacles by Bumping into Them

Whisker sensors allow your robot to detect obstacles by bumping into them. When the robot's whisker bumps into an object, it makes an electrical connection between the whisker and a circuit on the breadboard. In this lesson, you will program your robot’s Propeller microcontroller to detect those contacts and make the robot avoid obstacles.

Watch the YouTube video above to see navigation with whiskers in action.

Follow the link below to get started.

Build the Whisker Switches

Parts List

(2) Whisker wires

(2) 3-pin headers

(2) 10 kΩ resistors (brown-black-orange)

(2) 220 Ω resistors (red-red-brown)

Adding the Whiskers

Loosen the two screws that attach the front of your board to the chassis standoffs.

Hook a whisker wire onto each screw, positioned as shown in the diagram below.

Make sure to set one whisker above the nylon washer, and the other below, as shown here.

Gently re-tighten the screws, making sure the edge of the wire is parallel to the edge of the breadboard.

Build the Circuit

The next picture shows whisker wiring. Along with the whisker circuits, it has the same piezospeaker we've been using.

Build the circuit as in the picture.

Make sure to leave some space between the whiskers and the 3-pin headers.

Also, make sure that the 10 kΩ resistors (brown-black-orange) are the ones that connect 3.3 V sockets to the rows with the 3-pin headers.

Likewise, the 220 Ω (red-red-brown) resistors should connect P8 and P7 to the 3-pin header rows.

*P14/P15 resistors are needed only for ActivityBot kits using External Encoders (#32500).

Test the Whisker Switches

It is essential to test the whisker switches before programming your robot to navigate with them. That way, you can be sure the whiskers are sending the right messages. Otherwise, they might be telling the Propeller that they detect something even though they didn't, or vice-versa.

Without pressing any whiskers, the Terminal should display Left = 1 and Right = 1. If either of the numbers is 0, or if either of them flickers between 1 and 0, there is probably a circuit error.

If you have a circuit error, go back and double check to make sure all of your connections are correct.

Next, let's check to make sure the Propeller chip detects when the right whisker is pressed or makes contact with an obstacle.

Press the right whisker so that it makes contact with the 3-pin header's front post (see 2 in the picture).

Verify that the Terminal displays Left = 1 Right = 0, which indicates that the right whisker is pressed.

If the Terminal displays anything other than a steady Left = 1 Right = 0 while you have the right whisker pressed, then find and fix your circuit error.

Repeat for the left whisker. You will want to see Left = 0 Right = 1 in the Terminal. Make sure it displays that way. If it doesn't, then again find and fix any circuit errors.

If you press and hold both whiskers against posts, the Terminal should display Left = 0 Right = 0. Try that too.

How it Works

The project starts with a Terminal clear screen block, followed by our "reset indicator" (frequency out) block that beeps the piezospeaker.

After that, the program enters a repeat forever loop. Inside the loop, the first task is to check the state of each I/O pin connected to a whisker circuit - P7 and P8. The value of each state is stored with a Set variable block, wL for the left whisker connected to P7, and wR or the whisker on P8.

The Propeller I/O pin reads a 1—a "high" signal when the circuit is inactive, that is when the whisker is not being pressed. When the circuit is active as the whisker is being pressed, the Propeller I/O pin reads a 0—a "low" signal.

The next four blocks display the whisker states. A Terminal print text block followed by a Terminal print number block to show each variable and its value. These blocks are followed by a pause (ms) 150, which slows down the loop just enough to let you see the data in the Terminal. A Terminal clear screen block comes last which allows fresh data to be displayed on the next trip through the loop.

Did You Know?

Each robot whisker forms a normally-open switch in an active-low circuit with a 10 kΩ pull-up resistor. In its normal, unpressed, inactive state (left), the whisker switch is open - the whisker wire does not touch the 3-pin header post - keeping GND (0 V) out of the circuit. There is no path from GND to P8. So, all we have is 3.3 V on one end of a pair of resistors, and P8 set to input on the other end, sensing 3.3 V and so reporting a high signal (1).

In its active state (left), the pressed whisker switch closes when the wire touches the 3-pin header post. Now P8, through the 220 Ω resistor, 3-pin header, whisker, mounting post, and the mounting hole in the Activity Board, is connected to GND (0 V). P8 set to input senses 0 V, and so reports a low signal (0).

The 10 kΩ resistor in this circuit is called a pull-up resistor. It pulls the voltage at P8 up to 3.3 V when the whisker is not pressed. A pull-up or pull-down resistor applies a voltage that is opposite of the voltage the I/O pin will detect when the switch/button contact is made. Without it, the I/O pin set to input will be more like an antenna, allowing nearby electric fields to affect whether it detects 1 or 0, possibly supplying false data to your project.

Try This

Right now, the Terminal provides visible feedback when each whisker is pressed. That's not very useful for a robot that you want to disconnect from the computer! Let's use the Propeller Activity Board's built-in P26 and P27 LED circuits as whisker indicator lights.

Save a copy of your Test ActivityBot whiskers project under a new name.

Remove the first Terminal clear screen block.

Replace the repeat forever loop with the one below.

Run the project and verify that the P26 LED lights up only when the left whisker is pressed.

Your Turn

Modify your project to make the P27 LED light up only when the right whisker is pressed.

Whisker-Wheel Response

Now let's try a program that makes the robot back up while you push and hold a whisker up against its breadboard post.

Log into your BlocklyProp account and create a new project named Whisker Wheel Response.

Set the Activity Board's power switch to 1, and build the program shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360°.

Save the project, then click the Load and run (save to EEPROM) button.

Disconnect your robot from the USB cable and place it on the floor.

Set the power switch to 2.

Press and hold one of the whiskers against its contact post. The robot should back up as long as you keep the whisker pressed.

How it Works

The first two blocks may look familiar now and are going to be at the start of all the navigation programs from here on out. First, the frequency out block makes a 3000 Hz, 1-second beep on the piezospeaker connected to P4. Remember, that's the brownout indicator that lets you know if the program restarts due to low batteries. The second is the Robot ActivityBot initialize block, which must be at the top of the program come before any other Robot drive... blocks.

The rest of the code is inside a repeat forever loop. Two variables are declared next, each with a check PIN block attached. The variable left wheel stores the input state of the left whisker circuit connected to P7, and right wheel stores the input state of the right whisker circuit connected to P8. Remember, these whisker circuits provide active low outputs. If a whisker is pressed, the I/O pin connected to that circuit will sense 0 volts so that the check PIN block would provide a 0. If a whisker is NOT pressed, check PIN would provide a 1.

First thing in the loop, an If...do...else block checks to see if either whisker is pressed. The attached if condition blocks could be read as "if left wheel equals zero or right wheel equals zero, do..." The condition is built using a boolean comparison block set to or. Inside that are two compare value blocks, each individually checks whether a variable (left wheel or right wheel) equals zero.

If either whisker is pressed, the if condition is true, and the block enclosed by if...do gets executed. In this case, that's the Robot drive speed, with both wheels turning at -64 ticks per second causing the ActivitBot to back up.

If neither whisker variable stores a 0, the program execution skips the block enclosed by if...do and moves on to the block enclosed by else...if. There, a Robot drive speed left 0 right 0 block makes both wheels stop turning.

Did You Know?

Check early, check often! — Notice there is no pause block in the repeat forever loop above which allows the loop to execute very rapidly, monitoring the sensors and therefore updating which drive speed block is in use frequently. This allows the robot to quickly respond to sensor input with the appropriate motion. It's something to keep in mind when navigating with sensors.

...and don't block me! — Any code inside a loop that is blocking - code that does not let any other process proceed until complete - will slow down that loop. Examples of "blocks that block" are pause (ms) and frequency out. But, you can use this to your advantage by placing pauseor frequency out right after robot drive speed to control how long the robot performs an evasive maneuver inside of a larger loop.

Try This

Here is a modified loop for your main function. It replaces the if...else statements with code that allows you to push one whisker at a time to make it turn away to one side or the other, or both whiskers to make it move straight backward.

Save a copy of your project and name something like Whisker Wheel Try This.

Update the repeat forever loop so that it matches the one above.

Put the robot's power switch in position 1.

Click Save, then click Load and run (save to EEPROM).

Disconnect the cable and put the power switch in position 2.

Press and hold each whisker one at a time, then press and hold both at once.

Your ActivityBot should turn to the side away from whichever whisker is pressed. If you press both whiskers at once, it should back up.

Your Turn

Right now, if you press both of your robot's whiskers at the same time, it will awkwardly wiggle as it backs up with pivoting turns. Can you fix that?

Save another copy of your project and name it something like Whisker Wheel Your Turn.

Modify the project so that your AcitivtyBot backs up smoothly when you press both whiskers, but still turns to the side away from whichever whisker is pressed individually.

Roaming with Whiskers

Now that you've learned how to make the robot react to its whiskers it's time to expand on that. Let's free your ActivityBot to roam around on its own, and navigate away from obstacles using its whiskers.

To roam, the ActivityBot needs to go forward until it bumps into something. When that happens, it needs to back up, turn away from the obstacle, and then go forward again.

While the robot is going forward, it should repeatedly check its whiskers with minimal delays between checks. That way, it can know right away when it has encountered an obstacle.

Roaming with Whiskers Example Code

Log into your BlocklyProp account, and run and connect the BlocklyProp client on your computer.

Start a new project for the Activity Board.

Build and save the project shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360°.

Connect your ActivityBot to your computer, and put the power switch in position 1.

Click Load and run (save code to EEPROM).

Disconnect the cable and set the robot on the ground in an area with a few obstacles high enough for the whiskers to bump.

Press and hold the Reset button while you move the power switch to 2.

Observe its roaming behavior.

How it Works

After the frequency out block that serves as a brownout indicator, and the required Robot ActivityBot initialize block, the rest of the code is inside a single repeat forever loop.

First comes a Robot drive speed block that sets left and right wheels to 64 ticks per second, which is approximately 50% of the ActivityBot's top controlled speed. After that, check PIN blocks store the input states of the whisker circuits in the variables left whisker and right whisker. Immediately after that, the if...do...else...if block evaluates those variables to see if there is a detected obstacle. Since there are no pauses between these blocks, the ActivityBot can respond very quickly to sensor input.

The if...do...else...if block first checks to see if the left whisker equals zero, which indicates the left whisker circuit is closed by hitting an obstacle. If this is true, Robot drive speed -64, -64 makes the ActivityBot drive backward while the pause (ms) 600 block executes. Then the next Robot drive speed block uses left 64 and right -64 to turn the wheels in opposite directions at the same speed. This setting makes the ActivityBot rotate right, away from the side which detected the obstacle. The rotation maneuver lasts as long as it takes for pause (ms) 300 to execute.

But, if left whisker = 0 is false, those maneuvers are skipped and the else...if condition checks to see if right whisker = 0 is true. If it is, then an obstacle on the right has been detected, and the code executes the Robot drive speed and pause (ms) blocks right below, this time backing up and using left -64 and right 64 to rotate left, away from the obstacle on the right.

If neither variable is equal to zero, then no evasive actions inside the if...do...else...if loop is executed. The code will return to the top of the repeat forever loop, where Robot drive speed 64, 64 propels the ActivityBot forward a bit more before checking the whisker states all over again.

Did You Know?

Iteration — According to Merriam Webster[24], one definition of iteration is "a procedure in which repetition of a sequence of operations yields results successively closer to a desired result." Iterative testing and tuning is an integral part of developing robotics applications.

Try This

The example program uses the default Robot drive speed value of 64 (and also -64). That's at 50% of the speed the ActivityBot can go when using encoders. Since there is no Robot set acceleration used, the default value of 600 ticks per second squared is in use. These moderate default values work together well. They are an excellent choice while developing a basic sensor navigation routine, so the ActivityBot doesn't zip away unexpectedly. Now that your whisker system is working let's speed things up a little at a time and tune the maneuvers along the way.

Save a copy of your project as Whiskers Roaming Try This.

Try increasing the numbers (and decreasing the negative numbers) attached to the Robot drive speed blocks to +/-96 to make the ActivityBot navigate faster.

Save the project, load it to EEPROM, and test-drive the modified code.

How far does the ActivityBot back up after detecting an object? And then how many degrees does it rotate?

Try adjusting and test-driving values in the pause (ms) blocks until your ActivityBot does not back up unnecessarily far, and still rotates just 90 degrees.

Adjust and test-drive pause (ms) block values until the ActivityBot is navigating at top speed, but still backs up about the original distance and rotates just 90 degrees after detecting an object.

Your Turn

You have probably noticed that as you increased the ActivityBot's speed, its response seems increasingly sluggish. At top speed, the ActivityBot might even hit the wall before it responds to the whisker switches and backs up. It may have also knocked the 3-pin header out of its sockets a bit, preventing further whisker-switch contact. What do you think is causing that?

Add a Robot set acceleration block under the Robot initialize block.

Try reducing the acceleration setting and re-test.

Try reducing the speed, and re-test.

Experiment with different drive speeds and acceleration settings until the ActivityBot can respond to whisker presses without hitting the obstacle, but doesn't move so abruptly that it does a nose-wheelie.

Make a note of the best speed and acceleration combinations for your particular robot.

Navigate with Ultrasound

Testing for Echo

The Ping))) Ultrasonic Distance Sensor allows your ActivityBot to detect obstacles and measure the distance to them. Even though the PING))) sensor looks a bit like eyes, it is more like a mouth and an ear.

Much like a bat, the PING))) sensor emits an ultrasonic chirp when triggered, then listens for the chirp's echo and signals its return. The Propeller microcontroller can mark the time between triggering the PING))) sensor and getting a return signal. This echo return time can then be used to calculate the distance to an object.

This ability makes different ActivityBot navigation strategies possible, such as avoiding obstacles while roaming, or maintaining a set distance to an object that is moving.

Before You Start:

Watch the video above, if you can.

Follow the links below to get started.

Build and Test the Ping))) Sensor Circuit

In this activity, we will measure the distance to a variety of objects to get familiar with what the PING))) does, and does not, detect. The PING))) sensor needs power, ground, and one signal connection for the Propeller to get distance measurements.

Build the PING))) Sensor Circuit

Make sure to use a 2.2 kΩ resistor between the PING))) sensor’s SIG pin and the Propeller I/O pin (P8 in this case).

P14/P15 resistors are needed only for original ActivityBot kits using External Encoders (#32500[26]).

PING))) Sensor and Servo Ports—Do not connect to VIN. If you want to connect the PING))) sensor to a servo port (such as P16 or P17) with a 3-pin extension cable, be sure to set the port's power jumper to 5V first, or you could damage your sensor.
Each servo port includes a 3.9 k-ohm resistor in series with its Propeller I/O pin, so you would not need to include the 2.2 k-ohm resistor shown in the schematic for the breadboard circuit.

About the PING))) Sensor

The PING))) sensor emits a very high-pitched chirp and then listens for an echo, much like a bat. By measuring the echo's return time, and using the speed of sound in the air, the Propeller microcontroller can determine the distance between the PING))) sensor and an object reflecting the chirp sound, up to 3.3 meters away. This is how your ActivityBot can navigate using sound.

Echo based navigation only works with objects that can reflect the sensor's chirps effectively. Small objects, or objects too far away, don't reflect enough sound. Soft items, such as curtains and stuffed animals, may muffle the sound and not bounce back an echo. Walls approached at a glancing angle will reflect the sound further away instead of back at the PING))) sensor. Hard-surfaced cylinders, ball-shaped obstacles, and walls faced directly reflect sound well.

Air temperature can affect the accuracy of the PING))) sensor's distance measurements. Check out our reference article[27] about the speed of sound vs. air temperature to learn more about why this happens.

Test the PING))) Sensor

This program displays the PING))) distance measurements in the BlocklyProp Terminal. You can use it to test how well the PING))) sensor can detect various objects and walls at various angles. This will give you an idea of what your ActivityBot can and cannot do with this sensor.

Build the program shown above.

To set up the Ping distance block, first choose the unit, inches or cm (centimeters), for the value that the block provides.

Then, set the PIN to the Propeller I/O pin that is connected to the sensor.

Be sure to indicate your unit choice in the Terminal print text block.

Save your project.

Click the Run Once button, and, when the Terminal opens, you should see your text and a distance displayed.

Try measuring the distance to your hand, a cup, and a ball. All should be easy to detect.

Try measuring the distance to something soft, like a stuffed animal or a crumpled piece of fabric. Can the PING))) sensor detect an echo from it?

Try measuring a wall’s distance head-on.

Try measuring the distance to a wall, approaching at various angles. How far from 90 degrees can the PING))) sensor still see the object?

How it Works

The PING))) sensor gets a brief high/low signal called a start pulse from the Propeller chip to start the measurement. The sensor then makes its ultrasonic click and sets its SIG pin high. When the echo comes back, it sets its SIG pin low. The Propeller chip then can measure the duration of the PING))) sensor SIG pin's high signal, which corresponds to the echo return time.

The Ping distance block takes care of the math for converting the echo return time measurement to distance. In this program, the Ping distance block is plugged into a Terminal print number block, to display the measured value. The Terminal print number block comes just after a Terminal print text block, to add a label and measurement units for the displayed value. These two blocks are in a repeat forever block, along with a pause (ms) and Terminal clear screen block. The pause (ms) block slows down the repeat loop enough to get a smooth display, and the Terminal clear screen block keeps the value updated.

Did You Know?

Sound is measured in hertz (Hz). The PING))) sensor emits chirps at 40 kHz, well above human hearing. Most young humans can hear frequencies between 20 Hz and 20 kHz, while some bats can hear frequencies up to 100 kHz. So, while you cannot audibly hear the PING))) sensor's chirps, a bat most likely could.

Even though the PING))) sensor uses a sound that is a higher frequency than a human can hear, lower frequency sounds can bounce off of objects, too. Watch this video about an incredible person who is blind, but can "see" using echolocation: BBC Earth: Blind man uses echolocation like a dolphin[28]. Although he was able to develop that sense himself, sensors like the PING))) can be used to help others with disabilities. Read this article showing a product that could help others: CNN: sonar sticks[29]. Can you think of other ways sensors can be used to help?

Try This

Since there is a piezospeaker on the board, let's use tones instead of the Terminal to express the distance measured by the PING))) sensor. The next program saves the block's value in a variable and then uses math to scale the measured distance to a frequency range played on the piezospeaker.

Create a new project and name it something like PingPiezo.

Build the project shown below.

Use the Load and Run (Save to EEPROM) button to program the ActivityBot.

Disconnect the ActivityBot from the computer and point it toward a wall straight on, about 10 feet away. Then walk towards the wall. Can you hear the beep get higher pitched the closer you get to the wall?

Your Turn

Take a closer look at the project above. Can you see how the Distance variable controls the Hz variable, with the help of two operators and two constants?

What is the highest frequency the piezospeaker will play using this code? What is the lowest?

Make a copy of the project that uses inches instead of centimeters to take the Ping))) distance measurement, but still plays frequencies across a similar range.

Roaming with Ultrasound

Now that you can measure centimeter distances with the PING))) sensor, and know which kinds of objects it can sense, let’s combine the sensor's input with the servo motor's output.

Our goal is for the ActivityBot to roam and avoid objects using sound with the PING))) sensor. In one way, this is an improvement over whisker-switch navigation, because the ActivityBot does not have to bump into objects to detect them.

But, there is a key difference: there were two whisker switches. With whiskers, the ActivityBot could tell whether an obstacle was on the left or the right, and then turn away in the opposite direction. The PING))) sensor returns a distance value but does not indicate whether the obstacle is more to the left or the right.

Let's start with test code that makes the ActivityBot turn right or left at random when an object comes within 20 cm. Once that is working and tuned, then you'll add blocks for roaming.

Test the Random Turn Maneuver

This example program makes the ActivityBot stay still until the PING))) measured distance is 20 cm or less. Then, it turns in place until it measures more than 20 cm, which means the robot turned until the object is no longer visible.

In your BlocklyProp account, create a new project named Ping Detect and Turn.

Build the project shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360° before you save it.

Connect your robot to your computer and set the power switch to 1.

Click the Load and run (save code to EEPROM) button.

Disconnect your robot from its programming cable, put it on the ground, and set the power switch to 2.

Hold your hand in front of the ActivityBot about 30 cm (~ 1 ft) away, then slowly move it closer. The ActvityBot should turn away from your hand.

Try it several times so you can see that the direction it turns is random.

Try holding an open book or binder in front of the ActivityBot. Notice the ActivityBot it will rotate longer until it is clear of the wider obstacle.

How it Works

Since this code makes the robot drive, it begins with a frequency out block for the brownout indicator piezospeaker on P4. Next comes the required Robot ActivityBot initialize block. The Robot set acceleration block is set to a moderate 600 ticks/s2 to start.

The rest of the code is in a repeat forever loop. It begins with a repeat while loop. The while condition is a compare values block, checking to see if the value provided by the Ping distance block is greater than or equal to 20. If the answer is true, the code executes the pause 5 (ms) block and then checks the PING))) sensor again. This action will keep repeating, effectively putting code execution on standby until the while condition is no longer true.

When that happens, code execution drops down to the next block. The set variable block makes turn equal to a random number from 1 to 2. That's the BlocklyProp way of flipping a coin to decide which way the ActivityBot should turn. The "coin flip" is checked in the if...do...else...if block. If turn = 1 is true, then the block Robot drive speed left 64, right -64 gets executed, and the ActivityBot turns right. If turn = 1 is not true, then the block next to else is executed, and Robot drive speed left -64, right 64 makes the ActivityBot turn left.

The if...then...else...if block is followed by another repeat while loop. This time, the while condition checks if the Ping distance measurement is less than 20. The code execution stays in standby mode as long as this is true. Staying in standby mode allows the ActivityBot to continue its rotation maneuver until the PING))) sensor reports a measurement greater than 20, meaning that it has turned past the obstacle. Then, code execution continues to the Robot drive stop block which makes the ActivityBot quit turning.

Finally, the code execution returns to the top of the repeat forever loop, where it once again will sit still and check the PING))) distance every 5 ms until an object comes closer than 20 cm.

Did You Know?

Redundant subsystems - Whiskers switches rely on touch, and the PING))) sensor relies on ultrasound. As you may have noticed, each one has advantages and disadvantages. In real-world control systems, different types of sensors that depend on various physical properties are often used together, which can help make the system more reliable under a wider variety of conditions. Where risk is low, redundant sub-systems can seem silly, like wearing a belt with a pair of suspenders. But where risk is high, redundant subsystems are critically important. Can you think of any examples?

Try This – Roaming with PING)))

By adding just two blocks, the example code above can free the ActivityBot to roam. Right now, the ActivityBot stays still unless it detects an object within 20 cm. All that is needed is a block that allows it to drive forward unless an object is detected within 20 cm. If an object is detected that close, it must stop driving forward before performing the turn-away maneuver.

Save a copy of the project as Ping Roaming Turn Random.

Add a Robot drive speed block just above the first Repeat while block.

Add a Robot drive stop block just below that first Repeat while block.

Save your code, connect your robot to your computer and set the power switch to 1.

Load the code to EEPROM, disconnect your robot, and put it on the floor.

Hold down the reset button while you set the power switch to 2, then let go and watch your ActivityBot roam!

Your Turn

Build a maze out of boards or boxes that you can easily move around. Make the walls about 15 cm high and 45 cm apart.

Try letting your ActivityBot roam in the maze.

Tune your ActivityBot so it can better navigate the maze. That may mean slowing it down, tuning the acceleration, and reducing the PING))) distance that triggers the turns.

Try narrowing the maze corridors as much as you can but still leaving it wide enough for your ActivityBot to navigate.

The simplest initial approach to exploring a maze is to take a right turn at each wall. (Not necessarily the best approach, but certainly the simplest.) Modify the code so that it only turns right when it encounters an obstacle, and see how it goes!

Maintain Distance with Ultrasound

Instead of finding and avoiding obstacles, this next project makes the ActivityBot follow a target. The same sensor system, using different code. The code checks for the desired distance, and if the object is further away than that, the ActivityBot moves forward. If the object is closer than the desired distance, the AcitivityBot moves backward. If the object’s distance is equal to the desired distance, the ActivityBot will maintain its position.

Following Objects

This example makes the ActivityBot try to keep a 32 cm distance between itself and an object in front of it. With no object detected, the robot will go forward until it finds one, then maintain that 32 cm distance. If you pull the object away from the ActivityBot, it will go forward again to catch up. Likewise, if you push the object toward it, it will back up to restore that 32 cm distance.

In your BlocklyProp account, create a new project named Push Ping.

Build the project shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360° before you save it.

Connect the ActivtiyBot to your computer and set the power switch to 1.

Set the COM port, and click Load and run (save code to EEPROM).

Disconnect the ActivityBot from your computer, then hold down the reset button while setting the power switch to 2.

Set the ActivityBot on the floor and put your hand in front of it, keeping still. Your ActivityBot should move to 32 cm from your hand and maintain that distance.

Try moving your hand toward and away from the ActivityBot. It should respond to maintain that 32 cm distance.

How it Works

The program declares five variables: distance, setPoint, errorVal, kp, and speed.

Distance stores the measured distance to an object in front of the ActivityBot.

setPoint stores the distance the ActivityBot should try to maintain between itself and an object it detects in front of it.

errorVal stores the difference between the measured distance and the desired setPoint distance.

kp stores a proportionality constant; errorVal can be multiplied by kp for a speed that will help maintain the setPoint distance.

Speed stores the result of kp x errorVal.

The program starts off with the familiar comment block for the project title and frequency out block for the brownout indicator piezospeaker on P4.

After the required Robot ActivityBot initialize, two more blocks contribute to the robot's behavior. Robot set acceleration is set to 400 ticks/s2 which will help cushion sudden changes in speed. Robot drive max speed 96 makes sure that the Robot drive speed block caps its left and right inputs at +/-96, even if the attached speed variable exceeds 96 during runtime.

Two set variable blocks with number values attached come next: setPoint = 32 and kp = -10. These values do not change during runtime.

The rest of the code is inside a repeat forever block. This routine makes the ActivityBot maintain a distance between itself and the target object by repeating four steps very rapidly:

Get the measured distance with the block Ping)))distance in cm PIN 8.

Calculate the difference between the desired and measured distance with errorVal = setPoint – distance.

Calculate the speed needed to correct any differences between the desired and measured distance with speed = kp x errorVal.

Drive both wheels at the calculated speed (which is capped at a the Robot drive max speed 96).

Did You Know?

An automated system that maintains a desired physical output level is called a control system. In the case of our ActivityBot, maintained level is the distance between itself and the object in front of it. Many control systems use a feedback loop to maintain the level, and our ActivityBot is a prime example of this. The measured distance is fed back into the system and compared against the set point for calculating the next speed, and this happens over and over again in a process called a control loop.

Engineers use drawings like this block diagram to think through a control loop’s design and also to convey how it works to technicians and other engineers. If the set point (distance the ActivityBot tries to maintain) is 32 and the measured distance is 38, there is an error value. This error value is the set point – measured distance. That’s 32 – 38 = -6. This error is multiplied by a proportionality constant (kp) for an output that’s the speed to correct the error this time through the loop. That’s speed = kp x error value, or 60 = -10 x -6.

The circle is called a summing junction (for addition or subtraction), and the rectangular blocks designate operations that can vary. In this example, the top one is a proportional control block that multiplies error by a proportionality constant. The System block represents things we do not necessarily have control over, like if you move the object toward or away from the ActivityBot. Other common control blocks that were not used in this example are Integral, which allows corrections to build up over loop repetitions, and Derivative, which responds to sudden system changes.

Try This

It’s instructive to watch the relationship between errorVal and speed as the value of distance changes. We can use the Terminal to do this.

IMPORTANT: Set the ActivityBot's power switch to 1 so its wheels cannot move before you connect it to your computer.

Place your hand in front of the ActivityBot and watch the values in the Terminal window change.

Can you move your hand far enough so that the speed is greater than 96? Close enough so that it is less than -96? This shows the utility of the Robot max speed block.

Can you hold your hand in just the right place so that speed = 0? What are errorVal and distance equal to then?

This modified project is for looking at data, not for navigation! Go back to Push Ping, or comment out the Terminal and pause blocks, if you want to return to the navigation activity.

Your Turn

There are lots of values to experiment with here. For example, if you change the setPoint variable from 32 to 20, the ActivityBot will try to maintain a distance of 20 cm between itself and an object in front of it. The value of kp can be increased to make it go faster to correct with smaller error distances, or slower to correct over larger error distances.

Adjust the values of setPoint and kp to see what happens to the performance.

Make notes of what you tried and how the ActivityBot responded. What values of setPoint and kp seem optimal to you?

If you decrease the Robot set acceleration value, it will cushion the changes but could cause it to respond so slowly that it runs into the object. If you increase it, it will respond more abruptly. Too large, and it could change direction so fast that it could eject the Ping))) sensor from the breadboard.

Adjust the Robot set acceleration value downward to smooth out motions, or upward to make them more abrupt.

Keep experimenting with values as you search for the performance that seems best to you.

Again, make notes of what you tried and how the ActivityBot’s performance responded.

Would increasing the Robot drive max speed help the ActivityBot keep up with a retreating object? Could decreasing Robot drive max speed too much hamper its response?

Experiment with the Robot drive max speed setting to see the effect of increasing and decreasing it.

Navigate with Visible Light

Light sensors are used in all kinds of robotics, industrial, and commercial applications. Next, let's teach your ActivityBot to navigate by visible light. Using a pair of small light sensors, called phototransistors, your ActivityBot can measure and compare the light levels on its right and its left. It can then turn toward the brighter side as it navigates. This way, the ActivityBot can be programmed to follow a flashlight, or find its way out of a dark room to a bright doorway.

Follow the links below to get started.

Build the Light Sensor Circuits

Phototransistors are a common type of analog light sensor – the kind that might help a porch light automatically turn on at night. Think of the phototransistor as a light-controlled current valve. When light strikes the base of the device (B), more current will conduct into its collector lead (C) and flow out of its emitter lead (E).

Now, it's time to build and test two phototransistor circuits to give your ActivityBot phototransistor "eyes." Leave the piezo speaker circuit in place.

Parts

Build the Light Sensor Circuits

Make sure the phototransistor's shorter leads and flat spots are connected to ground, as shown in the wiring diagram below.

Use the 0.01 µF capacitors, labeled "103." The capacitors in your ActivityBot kit are not polar; it does not matter which way you plug them in.

Point the phototransistors upwards and outwards, about 90° from each other, and about 45° from vertical.

*P14/P15 resistors are only needed for ActivityBot kits using External Encoders (#32500[26]).

Test the Light Sensor Circuits

This test will display raw light sensor readings in the Terminal window. You will need a flashlight or lamp that is brighter than the overall light level in the room.

The phototransistor circuits are designed to work well indoors, with fluorescent or incandescent lighting. Make sure to avoid direct sunlight and direct halogen lights; they flood the phototransistors with too much infrared light.

In your robotics area, close window blinds to block direct sunlight, and point any halogen lamps upward so that the light reflects off the ceiling.

Log into your BlocklyProp account and create a new project.

Build the project Test ActivityBot Light Sensors, above.

Put the Activity Board's power switch in position 1.

Click the Run Once button.

Hold your hand over one phototransistor, and then the other, while watching the values change in the Terminal.

The values shown above were taken in a room with overhead fluorescent lighting. Notice how covering the left phototransistor causes the lightLeft measurement to be larger.

Mismatched Measurements
It is unlikely that your two phototransistor measurements will match exactly. Each sensor will vary slightly as a natural part of the manufacturing process, and the brightness levels are rarely precisely even in any environment. However, if one gives a measurement about 100 times larger than the other when exposed to the same level of light, that phototransistor is probably plugged in backward. In this case, check your circuit and try again.

How it Works

Take a peek back at the circuit schematic, for P9. Think of the 0.01 µF capacitor in the circuit as a tiny battery, and the phototransistor as a light-controlled current valve.

The first block in the repeat forever loop is make PIN 9 high. This block supplies current to the capacitor battery, which only takes a pause 1 (ms) to charge.Immediately after that, the block RC discharge PIN 9 changes I/O pin P9 from output-high to input. As an input, P9 will switch from sensing a high signal to a low signal as the capacitor battery drains its current through the phototransistor valve. The Propeller is measuring how long it takes for this logic transition to happen, and the RC block stores this discharge time in the lightLeft variable block.

The next three blocks in the repeat forever loop go through the same process with the P5 phototransistor circuit and storing another discharge time measurement in the lightRight variable.

When bright light is shining on a phototransistor, its valve is wide open and current drains through it very quickly, so the measured discharge time is small. When the phototransistor is covered up, its valve opens only a little, and the current will drain more slowly, resulting in a higher discharge time value. The remaining blocks in the loop display the discharge time of both variables in the Terminal. The Terminal screen capture above was taken when the left phototransistor was covered up, so the value of lightLeft is larger than the value of lightRight.

Did You Know?

QT is short for Charge Transfer: In this activity, each photoresistor is being used in a charge transfer or QT circuit. This circuit lets the robot sense a much wider range of light levels than an analog-to-digital conversion circuit you might typically see with this sensor. This QT circuit is a simple option for using a variety of analog sensors with a digital I/O pin.

Visible and Invisible Light: Light travels in waves so small that the distance between adjacent peaks is measured in nanometers (nm), which are billionths of meters. The figure below shows the wavelengths for colors of light we are familiar with, along with some the human eye cannot detect, such as ultraviolet and infrared. The phototransistor in your ActivityBot kit detects visible light but is most sensitive to 850 nm wavelengths, which is in the infrared range.

Your Turn

Just for fun, let's see if the phototransistor can detect different colors.

Zoom in on the color wavelength graph above.

Hold your robot up to the screen, placing one phototransistor very close to the color bar.

What color gives the highest reading? What colors give the lowest?

From your observation, do you think a clear phototransistor alone, like this one, could be used as a color sensor? Why or why not?

Make the Measurements Useful

For ActivityBot navigation, the raw sensor values aren't directly useful. What matters is the difference between the light levels detected by each sensor so that the ActivityBot can turn to the side of the one sensing brighter light. It is also nice to have values that will fall into a predictable range that can add or subtract them from the speeds sent to drive the servo motors.

Accomplishing this takes just a few steps - after building the equation you need, you'll then figure out how best to use blocks that follow this equation.

The concept is simple - of all of the light detected by both sensors, which portion of it is coming from the right sensor (and if you need to, you can tell which portion is coming from the right sensor). First, divide one sensor measurement into the sum of both. The result will always be in the 0 to 1 range. This technique is an example of a normalized differential measurement. Here’s what it looks like as an equation:

A range from 0 to 1 still isn't useful - especially in Blockly, since we can't use decimal or fractional numbers. The goal is to have a range from -100 to +100 (a range with 200 possible values). Multiplying the normalized differential measurementby 200 will give a result between 0 and 200. Subtracting 100 from that result will provide a range from -100 to +100. If the phototransistors sense the same level of light, regardless of how bright or dim, the final whole number will be zero. This is an example of a zero-justified normalized differential measurement, let's call it "ndiff" for short. Now our equation looks like this:

We have to be careful in BlocklyProp. Because all math is done with integers, it is possible to create an equation that always results in zero.

Preserving values in integer math
A good habit is to make your value bigger before you make it smaller. If you can use decimals or fractional values, it doesn't matter if you divide then multiply or multiply then divide. When doing integer math, it DOES matter. If we do the multiplication first, we can preserve the value of our result:

To turn this into blocks, you'll create a few different quantities. The top part of the fraction (the numerator) becomes:

The bottom part of the fraction (the denominator) becomes:

Which means nDiff is:

The example code below will display the lightRight and lightLeft measurements, and also show the value of nDiff as an asterisk. This makes it easier to visualize how the ActivityBot navigation program uses the sensor values to aim for a new trajectory towards the brighter light.

Graphical Test Code

In your BlocklyProp account, create a new project named Light Sensor Test Graphical.

Build the project shown below, and save it.

Click the Run Once (Load to RAM) button.

Rotate the ActivityBot towards and away from a light source to see the position of the asterisk change.

When the Terminal opens, you should see something like this:

How it Works

The graphical display was generated using Terminal print number and character value blocks.

This program builds on Test Light Sensors from the previous page. Two more variables are declared in addition to lightLeft and lightRight: nDiff and position. nDiff holds the result of the fancy-named equation, and positionis used to print a graphical display that represents the value of nDiff.

After calculating nDiff, its result needs to be turned into a position in the terminal. nDiff can be any number from -100 to +100, and we need positions from 0 to 50 (that's about how many characters wide the Terminal window is).

To get from (-100 to +100) to (0 to 50), we first add 100 (bringing it to 0 to 200), then divide by 4 (bringing it to 0 to 50).

Then, using a repeat x times block, we use the Terminal print number and character value blocks to print enough spaces to push out the asterisk (*) we are planning to print it where it needs to be on the Terminal screen.

Did You Know?

Integer math, nesting, and order of operations all matter. Just like with normal mathematical operations in real life, multiplication and division operations are performed before addition and subtraction. However, you may have already learned that Blockly evaluates each block from "inside-out," and you have to plan accordingly to get the correct result.

Dealing with integer math can be tricky, too. Most modern microcontrollers can do floating-point math, including the Propeller Multicore microcontroller. BlocklyProp doesn't support it, however, because the blocks themselves are not able to tell what kind of number - integer or floating-point - your variable might be. In addition, floating-point operations are slower and take up more memory than integer operations.

Once you know a few tricks, it's easy to overcome this limitation.

Try This

There may be times where you want to turn the value of a sensor into a percentage. To change a sensor's value to a percentage, we have to know what it's minimum and maximum values are. The difference in those values is the sensor's range. Then, you can use the following formula to convert the sensor's value to a percentage:

In real life, because multiplication and division have the same operator precedence, either of these calculation steps will get you the same result:

Subtract sensorMinimum from sensorValue, next divide that by sensorRange, then multiply that by 100.

Subtract sensorMinimum from sensorValue, next multiply that by 100, then divide that by sensorRange.

To see what difference your order of operations can have on the result in integer math, try the following example:

Close the Test Light Sensor Graphical project.

Click New Project, name it something like Integer Math Operator Order.

Enter the code shown below, click Run Once (Load to RAM).

Click in the Terminal window and try typing in different values.

Compare the results. What's happening?

Here's why this happens:

What percentage of 200 is 150? To find out, you might take 150 divided by 200 and get 0.75, then multiply that by 100 to get 75.

But what is 0.75 as an integer? Here's a hint: it's not 1. In integer math, the decimal is truncated. This means that the number is cut off at the decimal, leaving only 0. If you're trying to convert to a percentage by multiplying by 100, 100 times 0 is still 0.

If we use the same numbers, but this time multiply first by 100 before dividing by 200, we get 150 times 100 = 15000, then 15000 divided by 200 = 75.

Your Turn

Using what you know about integer math and building a graphical display in the terminal, try making a graphical display that shows the result of each sensor as its marker. You could use "x" for the left light sensor and "o" for the right one.

Try printing a number as a decimal to the Terminal. For example, how would you print 1562 millimeters as 1.562 meters in the Terminal using BlocklyProp when only integers are allowed? Here's a hint: if you divide 1562 by 1000, your left with 1. 1 times 1000 is 1000 and using subtraction you can find the rest of the number.

Roaming with Light Sensors

Now, let's make the ActivityBot follow light! The following code should allow your robot to follow a flashlight beam, or navigate out of a dark room through a brightly lit doorway.

Light Navigation Code

Find a flashlight, the brighter the better.

In BlocklyProp, find your Light Sensor Test Graphical project from the last page.

Save your project as with a new name, such as Navigate by Light.

Delete the blocks that print to the Terminal at the beginning and end of the program, and add blocks for the ActivityBot as shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360° before you save it.

Set the power switch to 1, then click Load and Run (save to EEPROM).

Disconnect your robot from its programming cable, and set it in an open area.

Set the power switch to 2, then press and release the reset button.

Shine the flashlight on the floor in front of the ActivityBot, which should turn towards the bright spot. If your flashlight isn't very strong, you may need to point it directly at the sensors.

Try shutting off the lights in the room, but opening a door to a brightly lit area outside. The ActivityBot should find its way out of the room.

How it Works

This program uses the Robot blocks for the ActivityBot. After initializing the ActivityBot, the program consists of a repeat forever loop which receives values from the phototransistors and uses them to adjust the servos' speeds to navigate toward whichever side detects brighter light.

First, the now familiar variableslightLeft, lightRight, and nDiff are setup for taking and using the sensor measurements. Then, thevariablesspeedLeft and speedRight are set up for use with the Robot drive speed block later on.

The first two parts inside of the repeat forever loop are the same as our previous test program. They take the light sensor measurements and store the values in lightLeft and lightRight.

The next line is the same nDiff equation used in Test Light Sensor Graphical project. It calculates nDiff, which will have a value in the range of -100 and 100. Positive nDiff values mean the left photoresistor is sensing brighter light, and negative nDiff values mean the right photoresistor is sensing brighter light. The farther the value is from zero, the greater the difference in the amount of light that the two phototransistors are sensing.

The variables speedLeft and speedRight are initialized to 64. Keep this in mind when looking at the if...else block that comes next.

The first condition translates to "if nDiff is greater than or equal to zero (brighter light on the the left), make speedLeft equal to 64 minus nDiff × 4." The new value for speedLeft would be something less than 64, while speedRight remains 64. These variables are then used in the Robot drive speed block after the if...else block. For example, if nDiff = 32, this statement is the same as speedLeft = 64 - (32 × 4), which equals -64. The result is Robot drive speed (left = -64, right = 64) which makes the ActivityBot rotate to the left toward the light.

However, if nDiff is NOT positive, the code drops to the else part of the if...else block, making speedRight equal to (nDiff × 4). This translates to "make speedRight equal to 64 plus nDiff × 4." This is still a number smaller than 64; remember that nDiff is negative here. For example, if nDiff = -16, this statement is the same as speedRight equals 64 + (-16 × 4) so speedRight ends up equal to zero, while speedLeft is still 64. This gives the Robot drive speed (left = 64, right = 0), causing the ActivityBot to pivot right towards the brighter light.

Did You Know?

Phototaxis — This is the term that describes an organism moving its whole body in direct response to light stimulus. Moving towards brighter light is called positive phototaxis, and moving away from brighter light would then be negative phototaxis. While the Navigate by Light program makes the ActivityBot mimic positive phototaxis, in nature, it seems this behavior is usually found in microscopic organisms. Moths are attracted to light, but their varied and circling flight paths around a streetlamp demonstrate that their navigation systems are far more complex.

Try This

Would you like to make your ActivityBot mimic negative phototaxis? It can be done by replacing one single variable in the Navigate by Light project.

Click Save As, and name the copy of the project Navigate By Dark.

In the nDiff equation, change the first use of lightRight to lightLeft, as shown below.

With the power switch in position 1, click Load and Run (save to EEPROM).

Put the ActivityBot on the floor, move the switch to position 2, and push the reset button.

Shine your flashlight at the ActivityBot. It should turn away from the light and seek shelter under a table or in a dark corner.

Your Turn

What other behaviors can you give your ActivityBot with light sensors?

Use additional conditions in the if...else block to add behaviors such as "stops when there is a lot of light."

Use additional variables, or set up another processor, to make your robot go to sleep after 30 seconds and wake back up when the light it detects changes.

Navigate with Infrared Flashlights

Many TVs and other equipment are controlled by infrared remotes. When you point the remote at the TV and press the channel-up button, it changes the channel for you. Pressing the button makes the remote flash a pattern of infrared light at the TV. Infrared light is not visible to humans, but the TV’s infrared receiver detects the flashing light pattern. The TV’s microcontroller decodes this pattern and uses that information to change the channel for you.

The infrared light (IR LED) and receiver work great as "flashlights" and "eyes" for your ActivityBot. The IR LEDs shine forward, and the IR receivers detect reflections off of nearby obstacles.

The Propeller microcontroller receives reflection data from the IR receivers and uses it to make navigation decisions. In this way, your ActivityBot can roam around obstacles without first bumping into them.

Follow the links below to get started.

Build the IR Sensor Circuits

In this activity, you will build and test the infrared object sensor system to make sure they detect objects in front of the ActivityBot. Just like the whisker circuits, there is one on the right and one on the left so the ActivityBot can determine which way to turn in relation to the obstacle.

In this case, each side needs two electronic components: an LED that rapidly flashes infrared light, and an infrared receiver to detect a reflection of that infrared light bouncing off of objects nearby.

Circuit

Parts Required

Find the two IR LEDs in your kit — they are the clear ones with dome-shaped (not flat) tops.

To direct the IR LED’s light, just like a flashlight beam, you will use an IR LED standoff (longer tube) and shield (shorter tube).

Insert the IR LED’s leads into the standoff tube, and out through the two holes at the bottom of the standoff.

Press firmly and the IR LED should snap into place. If it doesn’t, then pull it out, give it a half turn, and try again.

Fit the LED shield onto the standoff.

Although the shield friction-fits into the standoff, it can be helpful to place a small piece of clear tape around the tube where they meet to hold them together securely. Make sure the tape does not extend beyond the end of the tube or cover the IR LED.

Find the IR receivers in your kit. If you have two different kinds, use the ones with the silver metal cases for this activity.

The IR LED’s cathodes are connected to D/A0 and D/A1. For object detection, the D/A outputs are set to 0 V = GND. Their voltage can be increased to make the IR LEDs dimmer, for closer range detection. (They can even be tested at different voltages, or levels of dimness, to get a rough idea of the object’s distance, but that's for another activity.)

Use this wiring diagram and schematic to build the infrared detectors.

Make sure the longer IR LED anode pins are plugged into the rows shown in the wiring diagram.

Make sure your IR receivers are the silver ones with metal cases and not the black plastic ones.

*P14/P15 resistors are needed only for ActivityBot kits using External Encoders (#32500[26]).

Test the IR Sensor Circuits

The test code displays the state of each IR detector: 1 = no infrared reflection detected, 0 = yes, infrared reflected from an object is detected.

Test Code

Log into your BlocklyProp account and create a new project named Test IR Detectors.

Build the project shown below, and save it.

Click the Run Once button.

Point your ActivityBot so that both IR detectors are pointing away from any objects, and verify that both detectors report 1.

Place your hand in front of (and facing) the right IR detector, about 10 cm (≈ 4 in) away. This should display irLeft = 1 and irRight = 0, as shown below.

Repeat for the left IR detector and verify that the display updates to irLeft = 0 and irRight = 1.

Repeat for both, and verify that both display 0.

If all the tests worked, you are ready to continue to the next section. If not, go through the Troubleshooting list below.

Troubleshooting

It is essential to make sure that both IR detectors work correctly before continuing.

If your IR output is stuck at 1 or 0, it usually indicates a wiring problem. In this case, go back and check your wiring.

If the IR flickers to zero when it shouldn’t (because there are no objects in range) try turning off any nearby fluorescent lights, and retest.

If the IR only sporadically detects when an object is right in front of it, check the color codes on the resistors connected to P11 and P1. They should be brown-black-red for 1 kΩ. Also, make sure your ActivityBot is not in direct sunlight.

Make sure both IR sensors are working well before continuing to the next activity.

How it Works

First, the program makes I/O pins P26 and P27 output low (0 V). Not only does this turn off the P26 and P27 LEDs, but it also connects the D/A0 and D/A1 sockets to 0 V. The IR LED cathodes are connected to these sockets, using them for a ground connection. (We will explain why in a later activity.)

The rest of the code is inside a repeat forever loop. First, a frequency out block generates a 38000 Hz signal on P11, for 1 millisecond. P11 connects to an IR LED, causing it to strobe on/off very rapidly in a 1 ms burst.

This block is followed immediately by a check PIN block, which stores the input state of P10 in a variable named irLeft. P10 connects to the left IR receiver circuit. These IR receivers detect not just the presence of infrared light but are most sensitive to IR light that is strobing on/off very rapidly, at 38 kHz (38000 Hz). The IR detector sends a low signal (0 V) when a reflected 38 kHz IR signal is detected, and a high signal when no such signal is detected.

The process is duplicated for the right-side IR circuitry with another frequency PIN + check PIN block pair, storing the IR receiver's output in the irRight variable.

The next six lines should look familiar by now. The four Terminal print blocks display labels and values for the irLeft and irRight variables. A pause (ms) 150 block slows down the loop for optimal display. Finally, a Terminal clear screen block erases the old data before the next trip through the loop.

Did You Know?

Infrared — It means “below red,” and it refers to the fact that the light’s frequency is below that of red on the color spectrum.

Filtering — The IR receiver has a filter built in that makes it look for infrared that flashes on/off 38000 times per second (38 kHz). This allows it to differentiate between infrared coming from the TV remote and other IR sources such as halogen and incandescent lamps as well as sunlight streaming in through a nearby window.

Sunlight — Even though the IR receiver filters for sunlight, direct sunlight can often swamp the IR LED’s signal. Try to keep it indoors and out of any sunlight streaming in through windows.

Try This

The P26 and P27 lines are currently in use providing 0 V to the IR LED cathodes, so you cannot use their LEDs for indicating the IR detector states like you did with whiskers. So, let’s build some LEDs on the breadboard for "object detected" indicators.

Use those parts to build the two added LED indicator circuits shown here.

*P14/P15 resistors are only needed for ActivityBot kits using External Encoders (#32500[26]).

Next, you will need to modify the code to turn a given light on if its IR receiver returns 0, or off if it returns 1.

Use the Save Project As button to make a copy of your project with a new name, such as Test IR Detectors Try This.

Add the two if...else blocks shown below to the repeat forever loop, just before the pause (ms) block.

Run the program and verify that each red LED turns on when you put an obstacle in front of the IR object detector that’s next to it.

Your Turn - Test for IR Interference

If you have an infrared remote, you can further modify your IR detection code so that it sounds an alarm if it detects IR interference from the environment. This is a useful test to find out if nearby fluorescent lights or other devices are sending out signals that could affect your robot's behavior. The key is not to emit any infrared with the IR LEDs. If the receivers still send a low signal, there must be IR interference coming from another source.

If interference is detected, make the piezospeaker get your attention with a series of six 50 ms, 4 kHz chirps separated by six 50 ms pauses. You can use a TV remote to test this.

Use the Save Project As button to make a new copy, and name it Test IR Detectors Your Turn.

Point an infrared remote (such as a TV remote) at your IR receivers, and press and hold a button. Verify that the indicator lights come on.

Add an if...do block that plays the series of six 50 ms, 4 kHz chirps separated by six 50 ms pauses if either irLeft or irRight hold a 0.

Save the program to EEPROM.

Now you can disconnect the robot from the computer and walk around your workspace. Try pointing your robot at different light sources. If you hear the beeping alarm, you know that a 38 kHz infrared signal is detected. The ballast on some styles of fluorescent tube lighting is notorious for causing this kind of IR interference.

Roaming with Infrared Flashlights

With your IR object sensors built and tested, you are ready to make your ActivityBot roam and avoid obstacles without bumping into them.

IR Roaming Example Code

The IR Roaming code example makes the ActivityBot go forward until it detects an obstacle. If it sees an obstacle on the left, it will turn right. Likewise, if it sees one on the right, it will turn left. And if it sees obstacles on both left and right, it will back up.

Remember, not all obstacles are visible to this infrared system.
Many dark colored objects will absorb infrared light instead of reflecting it. If in doubt, use your LED indicator program from the previous page. The red LEDs on the breadboard will show you if an object is visible to the IR object detectors.

In your BlocklyProp account, create a new project named IR Roaming.

Build the project shown below.

Be sure to set the Robot initialize block's dropdown to your particular robot: ActivityBot or ActivityBot 360° before you save your project.

Connect your ActivityBot to your computer and set the power switch to 1.

Set the COM port and click Load and run (save code to EEPROM).

Disconnect your robot and put it on the floor in an open area.

Press, hold and release the reset button as you set the power switch to 2.

As your ActivityBot starts roaming around, hold your hand in front of the IR LEDs on either side.

Your ActivityBot should promptly turn away from your hand and roam in a different direction until it detects another obstacle.

How the IR Roaming Code Works

The project begins with the now familiar frequency out block for the piezospeaker brownout alarm on P4. Next comes the required Robot ActivityBot initialize block, and a Robot set acceleration block. As we learned from previous projects, 600 ticks/s2 is a moderate acceleration value that works well with the Robot drive speed block's default value 64.

Remember that the make PIN...low blocks for P26 and P27 are needed to connect the IR LED cathodes to ground.

The rest of the code blocks are in a repeat forever loop. The next four blocks are the same as in the IR Detectors project. For each IR LED/Receiver pair, a frequency out block sends a 1 ms pulse of infrared light at 38 kHz; then a check PIN block immediately stores the IR receiver's response in a variable. The variables irLeft and irRight will each store a zero if that receiver detects an infrared reflection off of an object, and 1 if no object is detected. (Remember, the IR receivers are set up as active-low circuits.)

A single if...do block with four conditions and potential actions makes up the rest of the repeat forever loop. Those conditions check the combined state of the irLeft and irRight variables. The possible conditions are:

Neither sensor detects an object.

Both sensors detect an object.

Only the left sensor detects an object.

Only the right sensor detects an object.

The conditions are tested one at a time in order. The first condition that is true runs the code in its ...do section, and then the program flow returns to the top of the repeat forever loop.

The first if... condition uses a boolean comparison block to test whether it is true that both irLeft and irRight variables are storing a 1. That means neither IR receiver detected an object, and the ActivityBot can drive forward with Robot drive speed left 64, right 64.

The second if... condition also uses a boolean comparison block to test whether it is true that both irLeft and irRight variables are storing a zero. That means both IR receivers detected an object, and the ActivityBot can back up with Robot drive speed left -64, right -64.

If the first two conditions get skipped, it must mean that the two variables are not storing the same value. So, the next two conditions test each variable alone to see if either one detects an object.

The third if... condition checks whether irLeft is storing a zero. That means an object is detected on the left, and the ActivityBot can turn right to avoid it with Robot drive speed left 64, right -64.

The fourth if... condition checks whether irRight storing a zero. That means the an object was detected on the right, and the ActivityBot can turn left to avoid it with Robot drive speed left -64, right 64.

Did You Know?

Conserving Conditions — Since this project has only four possible conditions to check for, your if....do loop did not really need to test for the fourth. Logic tells us, if the first three conditions are false, the fourth condition must be true. So the last else...if in the if...do loop could have just been an else containing the Robot drive speed left -64, right 64 block.

Compact vs. Easy to Read — Using all four conditions is an example of building code so that it is easy to understand, rather than as short as it can possibly be. When you are first developing a project, it can be helpful to make the code as easy to understand as possible. Then save a copy, and work on making it more compact by eliminating blocks that are not necessary. However, if you will be sharing your code, or if it is a very complex project, it may be wiser to keep it readable.

Try This

Adding visible light feedback for the IR recivers can help you understand what is happening if your robot seems to behave in unexpected ways.

Save a copy of the project and name it IR Roaming Try This.

Add blocks to the project so that the red LED on the left side of the breadboard lights up only when the left IR receiver detects an object. Likewise, the right red LED should light up only when the right IR receiver detects an object. HINT: you will need to make a change to each ...do section in the if...do block.

Test drive your modified code. Your ActivityBot should be driving around as before, but with the red LEDs flashing as objects are detected and avoided.

Your Turn

If your sensor input, light and motion output system logic is now working well, it's time to tune it for performance. Your goal is to get your ActivityBot navigating as rapidly as it can without running into objects or doing nose-wheelies.

Save a copy of the project as IR Roaming Your Turn.

Iteratively increase the drive speeds and acceleration, test driving after each change until your ActivityBot is optimally tuned.

ActivityBot Troubleshooting

Is your ActivityBot having trouble?

This page lists some of the most common problems encountered when calibrating the ActivityBot, or programming it to drive for the first time.

The Calibrating the ActivityBot[31] lesson has a diagnostic program that can help find common ActivityBot servo motor/encoder/power connection mistakes and problems. If you have not already done so, follow the instructions in that activity.

If you came here after the ActivityBot failed the test program in the Try This section of Calibrating the ActivityBot[31], find the Details that match what the Terminal reported in the list below and then follow the checklist instructions.

If you followed the instructions, but are getting the same message, then check the Other Symptoms section. It starts part way down this page.

If you do not find your specific problem here or need more help, contact Parallax Technical Support by email (support@parallax.com[32]), or by phone 916 -624-8333 (toll-free: 888 99-STAMP within the USA only). You can also post a question in the Learn Forum[33] to get help from the Parallax community.

Match the Details from the calibration results against messages below.

Battery Messages

If the Details from calibration results has one of these messages:

The ActivityBot's batteries are too low. Try a new set of 5 alkaline batteries, or recharge your 6.5 to 8 V power pack.

The ActivityBot's batteries are either dead, or the P13/P12 PWR select jumper is still at the 5V setting. It should be at the VIN setting.

The ActivityBot's batteries are either dead, or one of the cells is in the battery holder backward. A short circuit in the prototyping area could also explain the slow-moving behavior.

Yikes! Servo speeds indicate your ActivityBot may have a power pack that's more than 8.5 V. Use an appropriate power source to avoid servo damage.

Try This

Important: For any of these options, after you have adjusted the batteries, make sure to repeat the Calibrating the ActivityBot[31] activity.

If the batteries are "too low," try a new set of alkaline batteries.

If the batteries are "either dead or P13/P12 PWR select is still at the 5 V setting," first check the jumper tab to the left of the P12/P13 ports. For details on setting it to VIN, go to the Electrical Connections[19] page. If the jumper settings are already correct, try a new set of alkaline batteries.

If the batteries are "either dead or one of the cells in the battery holder is in backward," check the cells to make sure that each negative terminal is connected to a spring in the battery pack. If all the cells were correct, try a new set of alkaline batteries.

If you got the "Yikes!" message, the servos were measured as turning too fast, indicating the battery voltage is too high and outside of the specification.

Swapped Cables

If the Details from Calibration Results has this message:

Either your ActivityBot's servo cables or its encoder cables are swapped.

Encoder Signals Not Detected

The Propeller cannot detect either of the ActivityBot's encoder signals.

The Propeller cannot detect the ActivityBot's right encoder signal(s).

The Propeller cannot detect the ActivityBot's left encoder signal(s).

Try This

Go to the Prepare Encoders page[35]. See how the cables are connected? Make sure the cables are firmly plugged into the encoders.
(You do not need to take your ActivityBot apart for this. Just press the encoder plugs firmly into the encoder sensors.)

Servo(s) Need Mechanical Calibration

The servo on both of the ActivityBot's sides needs mechanical calibration.

The servo on the ActivityBot's left side needs mechanical calibration.

The servo on the ActivityBot's right side needs mechanical calibration.

Try This

You will need a Phillips #1 point screwdriver with a 1/8″ (3.18 mm) or smaller shaft.

Set the Activity Board's power switch to 0.

Remove batteries from the ActivityBot's battery pack.

Unscrew the battery pack and separate it from the chassis to allow the screwdriver to get to the access holes for adjusting the servos.

Load the batteries back into the battery pack and make sure it is plugged into the Activity Board.

Set the Activity Board's power switch to 2, providing power to the servos.

Run this BlocklyProp program using the Load and run (save code to EEPROM) button. It should cause the wheel(s) reported in the details section to turn very rapidly.

Use a screwdriver to gently adjust the potentiometer in the servo, as shown below. Don’t push too hard! Adjust the potentiometer slightly until you find the setting that makes the servo turn slowly (4 seconds or more per full turn).

Other Symptoms

Symptom: The ActivityBot is on and receiving power (with new batteries), but it will not move at all or moves slowly in a twitchy manner.

Try this: First, if the servos do not turn at all, make sure the power switch is in position 2 (which powers the servo headers), and not position 1. If that doesn't help, check the servo port jumper positions. The jumper for P12 and P13 should be set to VIN. If it is set to 5V, the servos will not receive enough power. Follow the Electrical Connections[36] page instructions for moving the jumper, and then run the calibration again.

DO NOT MOVE THE JUMPER WHILE POWER PLUG OR USB CABLE IS CONNECTED TO THE BOARD.

Symptom: The ActivityBot's servos and encoders are powered when the 3-position switch is in position 1.

Try this: Potentially, a short circuit has damaged your Activity Board (original or WX version). Position 1 on the 3-position switch should not power the 3-pin headers above the breadboard where the servos and encoders are plugged in. This problem can often be caused if the shunt jumper for P12 & P13 was moved while the Activity Board (original or WX version) was receiving power from the USB port or barrel jack. Unfortunately, there is no solution for this problem once it has occurred, please contact technical support (see contact information at the top of this page).

Symptom: When the ActivityBot is connected to the computer via USB cable, no COM port registers for it and/or the computer displays an error (no board detected, or board may not be working properly).

Try this: Check the USB connection on the Activity Board (original or WX version). The USB connection port on the ActivityBot is designed to fit tightly to the Mini B connector. Even though it may feel secure, sometimes the cable may not be inserted fully into the port, and this will cause your computer not to recognize the connection or to give an error.

Symptom: The ActivityBot moves in the opposite direction from what it was programmed to do.

Try this:

This may mean that both the servo and encoder cables are swapped. Unplug P14 and P15, and plug the cable into P15 that was plugged into P14 and vice-versa. Also, unplug the P12 and P13 cables, and plug the cable that was plugged into P13 into P12 and vice-versa. Check to make sure the left and right connections match the Electrical Connections[36] page instructions and then run the calibration again. A common mistake is to switch the cables for left and right servos accidently, which causes the ActivityBot to go backward when it should go forward, left when it should go right, etc.

Issue: The ActivityBot calibration routine went fine, but instead of driving straight, it drives in a jerky, wavy line.

Solution: You may need to adjust the servo or servo bracket. Check the position of the servo inside its hole in the chassis.

Notice that there is a little bit of space around the servo. If the servo is tight against the top edge of the hole close to the encoder, with a gap left below the servo, then the beam of infrared light coming from the encoder sensor might be missing the wheel spokes and hitting the solid ring below them instead.

To fix this, loosen the servo's locknuts and then reposition the servo, so the gap is between the servo and the encoder. Doing this should ensure that the encoder sees only spokes and holes. Make sure that the servo doesn't shift position when you retighten the locknuts.

(Note: the encoder bracket was redesigned in October 2013 to mitigate this issue.)