When you think about robots, you probably imagine drones, self-driving cars, or humanoid robots like Atlas or Asimo. Many of these more serious robots start their costs at thousands of dollars, and there is no real upper limit (Atlas costs over a $1M, for example). It is possible, however, to build small, interesting robots with a few inexpensive electronic components coupled with some materials you can readily find at home.
One of the great things about NodeBots is being able to prototype rapidly. The combination of an approachable language like JavaScript with friendly hardware such as Arduino means you can explore ideas and see how things work. Being able to prototype and play with robotic techniques quickly helps with learning and exploring concepts.
In this chapter, we’ll explore several robotic concepts using a basic robot called the SimpleBot (Figure 1-1). The first design of the SimpleBot came as the result of a challenge from my child, who asked to build a robot together one evening after dinner. With the clock ticking and only an hour to work before bedtime, it meant using things we had on hand—no laser cutters, CNC mills, or 3D printers. In true hacker spirit, we fabricated using cardboard, cable ties, and rubber bands to get something that worked.
Figure 1-2 shows the SimpleBot we made that night. After building it, we fell in love with prototyping using materials such as cardboard, cable ties, and more recently, corflute (corrugated plastic board) for robotics. These materials are inexpensive and easy to work with using scissors or a good craft knife. You don’t have to have access to tools such as a laser cutter, though if you do, then you can still work with these materials—it just becomes even faster to cut things out (and a bit more accurate). Working with these materials allows you to fabricate on your kitchen table and kids can easily work with them, too.
After that first effort, the SimpleBot has gone through numerous revisions and is now used as a teaching robot for some NodeBot events. I hope I’ve convinced you that building robots out of simple materials such as cardboard is a good idea. This chapter is going to cover:
Building the basic SimpleBot platform
Cutting the cord and untethering our SimpleBot from our computer
Before you get building, remember there’s no right or wrong way to build your SimpleBot. The design of the SimpleBot was intentionally left open-ended so you can make it any way you want. Others have built versions as minimal as possible on one extreme, as well as automated Nerf-Gun-Toting platforms on the other. The point of the SimpleBot is to play, explore, and extend it, to further your understanding of robotics—so customize away.
The SimpleBot project is divided into two parts with components needed at each stage. All of the components for this chapter are listed in Table 1-1, and then the elements needed for each stage are listed again when you get to that point in the chapter. Table 1-2 lists the parts needed for the wireless version.
Count | Part | Estimated price | Part numbers/source |
---|---|---|---|
1 |
Arduino Uno - R3 |
$24.95 |
MS MKSP99; AF 50; SF DEV-11021 |
1 |
Half-sized breadboard |
$5 |
MS MKKN2, SF PRT-12002, AF 64 |
Multi |
Jumper wires (male to male) |
$4.95 |
MS MKSEEED3, SF PRT-11026, AF 758 |
Multi |
Jumper wires (male to female) |
$5 |
MS MKKN5, SF PRT-09385, AF 825 |
2 |
Continuous rotation (CR) servos; if you have standard servos, an Adafruit tutorial shows how to mod them into CR servos |
$14 |
MS MKPX18, AF 154, SF ROB-09347 |
15 |
Cable ties (3–4mm wide and about 200mm long is perfect) |
$1 |
Various suppliers/stores |
1 |
7.4v RC battery pack (LiPo, Li-Ion, or whatever you can get a hold of) |
$5 |
Old or broken RC toys are good sources of these |
1 |
LM7806 or NTE962 6V voltage regulator (drops the voltage to something the servos can use) |
$2 |
RadioShack or Amazon |
1 |
Chassis material—a square of thick cardboard or corflute (3–5mm thick), approximately 400mm square |
$2 |
Various suppliers/stores |
1 |
A printout of the template file |
Free |
Included with source code |
Count | Part | Notes | Estimated price |
---|---|---|---|
4x |
50V 0.1uF ceramic capacitors |
Ceramic is best, but others will work |
$0.50 |
1x |
USR WiFi232-T module |
$15 |
Start by cutting out the template on your cardboard. It doesn’t need to be perfect. A knife, a cutting mat, and a ruler make it easier to do the inside holes than scissors. With the wheels, the center hole can be cut out or just left, it’s only a target so you know where the center is so you can screw through it to the servo.
You should now have a full set of chassis pieces. The large piece with the bumps at the end is the base, and the bumps are the front. Use the bumps to push through the small holes on the smaller rectangle, which you can use as a bumper to mount things on.
Next, mount the wheels to the servo. Take the cross-shaped servo horn (you should have a packet of different shaped plastic fittings with your servo) and align the center with the center of the wheel. You can use a piece of wire or a needle to poke small holes in your material to mark the points to screw (Figure 1-3).
Screw the wheels securely to the servo horn. If you prefer, just glue them on (but then you can’t reuse the servo horns later)—either way works fine. Once you have the wheels mounted on the servo horns, screw through the center of the wheel and the horn into the small gear on the servo. Go easy and hold everything in place while you turn the screwdriver; being rough here can strip the gears in your servo and cause them to slip. Do this for both servos so you now have two wheels.
Gently rotate the servo to ensure it turns freely. If you’re using cardboard or corflute, your mounting screws may be a little long. They don’t have to go all the way through, but make sure they clear the body of the servo when you turn them.
Next, mount the servos to the chassis, as shown in Figure 1-4. You want to place these more or less to the front so the weight balances. You can put them anywhere, but bear in mind you may need to weigh down one end if you find it’s tipping. Mount the servos so the side with the wheel is closest to the front of the chassis, and attach them with two cable ties through the mounting holes to keep them in place. Use two cable ties so the servo body doesn’t twist when you start driving.
When you attach the cable ties, only tighten them enough to stop movement, but not so tight as to rip the cardboard or corflute.
Mount the battery between the wheels as in Figure 1-5. Again, you can use a cable tie, but double-sided tape or a bit of Blu-Tack works well here, too, if you want to recharge easily. Trim the cable tie excess off as you go or it gets a little hard to mount everything.
Next, fashion a simple “skid” for the SimpleBot to stay balanced. You can do this by looping a cable tie toward the back of the SimpleBot in the middle of the chassis. Do this from the top so the catch of the tie doesn’t get caught on anything. The underside of the loop should be about the same height as half the wheel so the body sits level. It will feel “loose,” but don’t worry, you secure this with the breadboard in the next step.
Finally, add the breadboard. Mount this across the point you put the skid cable tie so the board holds the skid down. The cable tie can go down the length of the board where the channel is and you can still place ICs across it.
Now that you’ve finished the mechanics, it’s time for the electronics. The complete wiring diagram is shown in Figure 1-6, with each piece explained next.
Start by creating a battery power rail. This goes to the back of the breadboard and gives you at least 7.4V. Join the grounds on both sides of the breadboard together. Mount the Arduino Nano at one end and join its ground. As you can see with the Nano, position it to either side of the main channel, over the cable tie, and position the USB connection on one side so it’s easy to plug in, as shown in Figure 1-7.
Now create the power for the servos. The servos want 6V so the battery will give them a bit too much, so use a +6V voltage regulator to output a nice clean 6V for the servos. Put that 6V on the other rail of the breadboard so you can attach the servos there.
Note that we’re using the breadboard to bring power from the battery to the regulator from “behind,” then power from the regulator to the other rail from the “front.” This is a good way of keeping what is going on straight in your head when it comes time to debug the circuit later in this chapter.
The servos can be attached to the front power rail with voltage and ground going to each. The left servo signal wire goes to pin 9 and the right servo signal wire goes to pin 8 on the Arduino, as shown in Figure 1-8.
Give yourself a pat on the back and tidy up all the wires so nothing is dangling on the floor—you are now ready to start working on your code.
All source code for the examples in this book can be found on GitHub.
Ensure Node.js is installed (see “Installing Node.js”). You only need a couple of packages for the SimpleBot, which can be installed from a terminal shell with:
npm install johnny-five temporal keypress
Your Arduino needs Firmata on it (see “Arduino”) so the first thing to do is test that everything works before building something more complex to control the SimpleBot. The following code connects to the Arduino over USB and then runs the servos forward for 3 seconds, stops for 3 seconds, goes backward for 3 seconds, and finally stops before exiting.
Connect your SimpleBot to your computer and run the script shown in Example 1-1 and replace <serialport>
with the serial port your Arduino is connected to.
var
five
=
require
(
"johnny-five"
);
var
temporal
=
require
(
"temporal"
);
var
opts
=
{};
opts
.
port
=
process
.
argv
[
2
]
||
""
;
var
board
=
new
five
.
Board
(
opts
);
board
.
on
(
"ready"
,
function
()
{
var
left_wheel
=
new
five
.
Servo
.
Continuous
(
9
);
var
right_wheel
=
new
five
.
Servo
.
Continuous
(
8
);
temporal
.
queue
([
{
delay
:
5000
,
task
:
function
()
{
console
.
log
(
"going forward"
);
left_wheel
.
cw
();
right_wheel
.
ccw
();
}
},
{
delay
:
3000
,
task
:
function
()
{
console
.
log
(
"stopping"
);
left_wheel
.
stop
();
right_wheel
.
stop
();
}
},
{
delay
:
3000
,
task
:
function
()
{
console
.
log
(
"going backward"
);
left_wheel
.
ccw
();
right_wheel
.
cw
();
}
},
{
delay
:
3000
,
task
:
function
()
{
console
.
log
(
"stopping"
);
left_wheel
.
stop
();
right_wheel
.
stop
();
}
},
{
delay
:
1500
,
task
:
function
()
{
console
.
log
(
"Test complete. Exiting."
);
process
.
exit
();
}
}
]);
});
If this all works, great! Your SimpleBot is working properly.
If your SimpleBot isn’t working as described, don’t worry, it is time for some debugging:
Check your wiring.
Each servo should be connected to the power rail from the battery and to ground on the red and brown (or black) wires. The left servo’s signal wire should be connected to pin 8 on the Arduino and the right servo’s signal wire connected to pin 9 on the Arduino.
Also ensure that the battery’s ground is connected to the Arduino’s ground, as per the wiring diagram—you need a common ground across power sources.
Check your wiring with a particular focus on ensuring your servo signal line is wired into the correct pin on the Arduino.
This is caused by a servo rotating in a different direction than is assumed in the code. You can unhook the servo and flip it over, which will make all the other code samples behave. Otherwise, just modify the code to change the offending servo’s command from servo.ccw()
to servo.cw()
and vice versa.
Now that the SimpleBot is working correctly, you can create a simple program to drive it around. As a starting point, let’s take input from the keyboard in order to drive the SimpleBot forward and backward, spin it left or right, and also to stop it. The code shown in Example 1-2 is a very basic example of how to drive using keyboard control.
var
five
=
require
(
"johnny-five"
);
var
keypress
=
require
(
"keypress"
);
keypress
(
process
.
stdin
);
var
opts
=
{};
opts
.
port
=
process
.
argv
[
2
]
||
""
;
![]()
var
board
=
new
five
.
Board
(
opts
);
board
.
on
(
"ready"
,
function
()
{
console
.
log
(
"Control the bot with the arrow keys, the space bar to stop, Q to exit."
)
var
left_wheel
=
new
five
.
Servo
.
Continuous
(
9
);
var
right_wheel
=
new
five
.
Servo
.
Continuous
(
8
);
// Configure stdin for the keyboard controller
process
.
stdin
.
resume
();
process
.
stdin
.
setEncoding
(
"utf8"
);
process
.
stdin
.
setRawMode
(
true
);
process
.
stdin
.
on
(
"keypress"
,
function
(
ch
,
key
)
{
![]()
if
(
!
key
)
{
return
;
}
if
(
key
.
name
==
"q"
)
{
console
.
log
(
"Quitting"
);
process
.
exit
();
}
else
if
(
key
.
name
==
"up"
)
{
![]()
console
.
log
(
"Forward"
);
left_wheel
.
cw
();
right_wheel
.
ccw
();
}
else
if
(
key
.
name
==
"down"
)
{
console
.
log
(
"Backward"
);
left_wheel
.
ccw
();
right_wheel
.
cw
();
}
else
if
(
key
.
name
==
"left"
)
{
console
.
log
(
"Left"
);
left_wheel
.
ccw
();
right_wheel
.
ccw
();
}
else
if
(
key
.
name
==
"right"
)
{
console
.
log
(
"Right"
);
left_wheel
.
cw
();
right_wheel
.
cw
();
}
else
if
(
key
.
name
==
"space"
)
{
console
.
log
(
"Stopping"
);
left_wheel
.
to
(
90
);
right_wheel
.
to
(
90
);
}
});
});
Connect to the board using the serial connection supplied from the command line.
Set up an event waiting for a keypress on the keyboard.
Check the key that was pressed and then, depending on which direction you want to go, engage the motors as discussed in the section on differential drive.
Connect your SimpleBot to your computer and run the script with:
node simplebot.js <serialport>
You should now be able to drive your SimpleBot around the table or floor using the arrow keys on your keyboard and hitting the spacebar to stop.
Here are some tips in case you get stuck:
See the previous troubleshooting section on tracking down wiring issues.
This is due to continuous rotation servos being a hack on normal servos, as well as each servo being manufactured slightly differently. Some servos have a “tuning pot” at the back, which you can turn so that it stops when you set it to stop.
If you don’t have one of these, then you can set your stop point in code.
On a CR servo, the stop position is defined as the center (recall a normal servo operates in an arc that is usually 180°), which is usually 90°. Setting a lower value than this will rotate the servo one direction and above this will rotate the other.
In the stop code, set the servo to move to the 90° position. As such, you might have to tune your stop point a little, changing the stop code to be like this:
left_servo
.
to
(
87
);
right_servo
.
to
(
94
);
There’s no “correct” number and every servo will be slightly different, so a few minutes of tinkering will enable you to figure out the number you need for that servo.
Now that you have your SimpleBot driving around the table, you’ll notice one big limitation—the length of the USB cable tethering your bot to your computer. Obviously one solution is to use a longer cable; however, anything over 3 meters long starts having signal issues, not to mention the potential of tangles and the weight the robot has to drag around.
A better solution is to cut the cord altogether—letting the SimpleBot roam free and unshackled from its USB tether!
For this build, we’ll use a single battery with bypass filters to smooth the voltage spikes from the servos as a result of everything using just the one battery. We’ll also use WiFi, as this will give a little more range than Bluetooth and allows driving around the workspace or home or wherever the WiFi network exists.
The WiFi module used in this circuit is very inexpensive at about $12 and is quite a clever bit of circuitry. The module operates as a WiFi-to-Serial bridge so anything sent to it over the network gets copied to its serial lines and vice versa. This means our Arduino setup is almost exactly the same as before, but it can go wireless with the addition of this module—a great result for $12, and one change to the code.
The specific items you’ll need for this stage are listed here:
50V 0.1uF ceramic capacitors
M-M jumper wires
M-F jumper wires
USR WiFi232-T module
Before starting, unplug your Arduino from the USB so you don’t short anything out while building this circuit.
The first thing to do is add decoupling capacitors to the Arduino ground and VIN, as this will be powered from battery. Also add capacitors to the power and ground for each of the servos, as shown in Figure 1-9.
The wireless module uses 2mm pitch headers, so it can’t be plugged into the breadboard directly. Use the M-F jumper wires to connect the module to the breadboard instead. Add the WiFi module with the connections illustrated in Figure 1-10 and mapped in Table 1-3.
WiFi232 Pin | Arduino Pin |
---|---|
1 |
GND |
2 |
VCC (3.3v); don’t plug this into 5V! |
5 (RX) |
Arduino (TX) Pin 1 |
6 (TX) |
Arduino (RX) Pin 0 |
Check, check, and triple check your wiring. There’s no reverse or over-current protection on these modules, and applying power with too much voltage or GND and VCC back to front will quickly toast your WiFi module.
These modules are designed to take an external antenna, so your range will be drastically reduced if you don’t use it. The antenna can be readily attached to the chassis with a nice lump of Blu-Tack or hot glue.
Finally, put a jumper wire from the battery power rail to the VIN pin on the Arduino. This will give the Arduino 7.4V, which is plenty for it to run.
That was easy; now for the software side.
Let’s walk through the wireless portion in stages. When you remove wires, there’s more complexity, so you need to make sure each element works before moving onto the next. If anything goes wrong, just backtrack a little and try again.
Once 3.3V is supplied, the WiFi module will power up. By default, it will be in Access Point mode. Wait about 10–15 seconds and then in your available WiFi networks on your computer you should see the “USR-WIFI232-T” SSID appear. Connect to this network and once connected, you can try two things to see if it’s all working.
The module IP address is 10.10.100.254, and it has a DHCP server so it should assign you something in that range once you connect. Test pinging 10.10.100.254 and if you’re getting responses like those shown in Example 1-3, move to the next step.
$
ping 10.10.100.254 PING 10.10.100.254(
10.10.100.254)
56(
84)
bytes of data.64
bytes from 10.10.100.254:icmp_req
=
1
ttl
=
255
time
=
2.21 ms64
bytes from 10.10.100.254:icmp_req
=
2
ttl
=
255
time
=
23.5 ms64
bytes from 10.10.100.254:icmp_req
=
3
ttl
=
255
time
=
29.5 ms ^C --- 10.10.100.254 ping statistics ---3
packets transmitted,3
received, 0% packet loss,time
5013ms rtt min/avg/max/mdev=
2.215/20.281/29.502/9.622 ms
If this doesn’t work, diagnose your network interface and make sure you’re not using a static IP or some other configuration that overrides DHCP.
Now open a web browser and point it at 10.10.100.254. The username and password by default are both “admin.” In this interface, you can configure the common aspects of the module itself. Try setting it to operate in STA+A mode, which means it operates as a WiFi station (connects to your WiFi network), but also operates as an access point if you need it (like when taking a SimpleBot to the park).
If you’ve ever configured a WiFi router, then everything will look pretty familiar. Supply the connection details for your network and get the module to connect. You should now see all of the connection information.
If you can’t get to the wireless module using these methods for some reason, try connecting over serial directly. You’ll need something like an FTDI or other serial ttl USB cable. Connect using a serial console at 115200 baud. The WIFI232-T user guide has more information on using AT commands.
Because the WiFi module can work at a higher baud rate, the Arduino should talk at that speed, too. To change this, open the StandardFirmata sketch and then do a “Find” for the line that looks like this:
Firmata
.
begin
(
57600
);
Change it to connect at 115200 instead:
Firmata
.
begin
(
115200
);
That’s all. Compile and upload the sketch to the Arduino.
Because you’re using the Arduino hardware serial port, if you need to flash your Arduino, you’ll need to remove the RX and TX wires connected to the WiFi module so you can talk to the Arduino over USB. If you get an stk_500 sync error, it’s probably because you forgot to unplug the serial wires.
The next step is to make sure communication is occurring properly before trying to send messages from Johnny-Five and the application.
The WIFI232 module exposes TCP port 8899, and whatever is sent to and from the serial connection is sent through that TCP port. Messages will get passed like this:
PC <--> WiFi Network Interface (TCP 8899) <--> WIFI232 Network Interface (TCP 8899) <--> WIFI232 Serial Interface <--> Arduino Serial Interface
If you connect to the module using Telnet, you should be able to see any serial messages coming from the Arduino. Although most Firmata data is encoded, one message is in clear text—when it sends the name of the Firmata sketch being used to the receiver as part of startup.
On my networks, the module is using IP: 10.0.1.12 so telnet there on port 8899 with telnet 10.0.1.12 8899
.
Windows doesn’t usually install the Telnet client by default. You’ll need to make your way to the Add/Remove Windows Components section of the Control Panel and install it.
This gives the following response:
Trying 10.0.1.12...
Connected to 10.0.1.12.
Escape character is '^]'
.
That’s good, because everything is connected. Hit the reset button on the Arduino so the sketch restarts. You should see the telltale Pin 13 LED blink sequence and within a few seconds something like this:
Trying 10.0.1.12...
Connected to 10.0.1.12.
Escape character is '^]'
.
��yStandardFirmata.ino
Success! You just received a message from Firmata onto your PC without any wires. Quit Telnet (press Ctrl+] then type “quit”). You’re now ready for the step you’ve been waiting for.
Now that you have Firmata messages traveling over the network, all you have to do is get Johnny-Five to read and write them. The problem is that Johnny-Five assumes you have a Serial device connected—something like “/dev/ttyUSB0” or “/dev/tty.USBSerial.” Instead, you have a network socket. One option is to go and write an IO interface for Johnny-Five, but that’s overkill for a simple socket, and it’s not like you’re writing a new messaging protocol—you’re just sending messages via the magic of WiFi rather than a pair of wires. Instead, follow the steps described here (for Mac/Linux, use socat, and for Windows, use VSPE):
Socat creates relays between two otherwise independent data channels. Knowing this, you can use pseudoterminals to allow you to create a “fake” serial terminal. A “faked” serial terminal can then be used by Johnny-Five and our application. You should be able to install socat on Linux from your distribution’s package manager. On Mac OS X, you could use Homebrew.
Make a relay between a pseudoterminal that looks like a serial port and connect that to the TCP socket used to talk to the WIFI232 module. On my networks, the WiFi module is at 10.0.1.12—yours will be different, so just replace that. Here’s how it will work:
PC <--> Pseudo terminal (~/dev/ttyV0) <--> TCP Socket (10.0.1.12:8899)
To create this route, use this command (remember to replace 10.0.1.12 with the correct address for your WiFi module):
socat -d pty,nonblock,link=
$HOME
/dev/ttyV0 tcp:10.0.1.12:8899
The -d
switch is a debugging parameter, so remove it if you don’t want details, and use it up to four times for lots of messages if something doesn’t work.
This command tells socat to create a pseudoterminal (pty
). Don’t block it (nonblock
; you can use it from other processes) and link
it to $HOME/dev/ttyV0 (in this case that puts it at /home/ajfisher/dev/ttyV0, but put it wherever you fancy). Socat then connects that terminal to a TCP connection at 10.0.1.12 using port 8899. Once socat is running, create another terminal window and use screen
to connect to a fake serial connection:
screen ~/dev/ttyV0
Do the Arduino reset trick again and you will see the Firmata sketch name. If that all works, then you’re ready to wirelessly control your SimpleBot. All you need to do is pass in the fake serial connection to the program you wrote before, and away you go. At this point, it will work just like it did before, but your SimpleBot will now be wireless:
node simplebot.js /home/user/dev/ttyV0
On Windows, use a piece of software called Virtual Serial Ports Emulator (VSPE). This allows you to define a COM port and then create mappings for other endpoints such as to network services.
In the end, the messages should route like this:
PC <--> Virtual COM Port (COM10) <--> Bridge <--> TCP Client (10.0.1.12:8899)
Download and install the software and once you have it open create two devices:
Create the first one as a “Connector” from New Devices and set it to be COM10—this creates a COM port for Windows to talk to and will be what is passed to the Node.js application:
TCP Client
Host: 10.0.1.12 (or whatever your WIFI232 IP is)
Port: 8899
The next one created is a “Bridge” type, which bridges between two data streams:
Serial port
Port: COM10 (type it in—it won’t be in the drop-down as it’s not “real”)
Speed: 115200
Save the config and press the “play” button to have it all run.
You should now just be able to run the SimpleBot application like before:
node simplebot.js COM10
The most common problems here are related to power or range causing resets.
If you don’t have enough power or haven’t used decoupling capacitors, your Arduino or WiFi module may reset when you do big direction changes on the motors. Check the circuit, make sure you put the capacitors in, and check the power levels on your battery pack.
If you are getting persistent resetting issues, you may be drawing too much current from your servos. If they are particularly heavy duty (high torque), then it’s possible you’re dropping the voltage too much for the Arduino. You may need a higher capacity battery designed for RC car use.
If you are going out of range of your WiFi network, you may get garbled messages and your SimpleBot stops responding. This is where you start thinking about bigger antennas, and other radio types in order to make the range even longer.
Over the course of this chapter, you’ve taken some cardboard and turned it into a robot. With just a basic robot made from some scrap and some inexpensive components, you’ve explored a range of topics:
Differential drive
Programming control systems
Remote control
Now that you have your own SimpleBot working, you can take it in many interesting directions to learn even more robotics concepts. Here are some things you might want to try:
Add autonomy and collision avoidance.
Add a Raspberry Pi running Node.js to do all of the processing and logic on the robot and make it even more autonomous.
Use a Raspberry Pi tethered to your mobile phone and make a remote web-controlled bot that can drive anywhere.
Use some reflection sensors to get your SimpleBot to follow lines.
Add some encoder wheels so you can measure distance of travel/speed, and turn more accurately.
Add a light sensor and program your SimpleBot to be attracted to or run away from light.
Program your SimpleBot to spin around and light up some LEDs whenever you get a tweet or someone sends you an email.
Explore different drive mechanisms using more wheels or even omniwheels for a SimpleBot that can change direction without spinning on the spot!