Chapter 7. The Bug-Bot

In this chapter you build a robot (the Bug-Bot) that uses bump sensors to navigate around objects and explore a room, much like an insect would. The bump sensor is nothing more than two wires pressed together when the bot bumps into something, to let the Arduino know that it needs to find a new path (Figure 7-1). These sensors are commonly used for object detection but require that the bot have physical contact with the object to detect it. Some robots incorporate several types of sensors for object avoidance and autonomous navigation; these usually include a bump sensor on the front and/or rear of the bot to stop it if the other sensors do not.

The visible components of the Bug-bot: three bump sensors on the left, a battery and Arduino clone in the center, two antennae sensors on the right, and two hobby Servo motors with wheels attached beneath a simple, homemade plexiglass frame.

Figure 7.1. The visible components of the Bug-bot: three bump sensors on the left, a battery and Arduino clone in the center, two antennae sensors on the right, and two hobby Servo motors with wheels attached beneath a simple, homemade plexiglass frame.

The simplest of bump sensors can be constructed using a piece of wire, a nut, and a bolt. To illustrate this, I decided to build the bump sensors for the front of the Bug-bot from scratch. I then used SPST switches for the rear sensors, which have aluminum bumpers attached to them.

Reading a Switch with Arduino

The majority of the code for this project involves reading the digital state of an Input pin. Recall from Chapter 1 that a digital Input can be read only as either HIGH (+5v) or LOW (GND). You can read the state of a digital switch from any Arduino pin using the digitalRead(pin) command. The default state of each pin can be either HIGH or LOW, depending on how you want to interface the switch. In this project, I focused on using as few parts as possible and keeping the design simple.

Connecting each bump sensor switch is simple: one pole of the switch connects to the Arduino Input pin; the other connects to GND. The Arduino has internal 20k ohm pull-up resistors on each pin that can be activated in the code if needed. To minimize the amount of parts needed (no extra resistors to buy), you can utilize these internal resistors to keep the Input pin HIGH unless the bump switch connects it to GND. Although it might make more sense (to me at least) to keep the input LOW using a pull-down resistor and only read HIGH (+5v) if the switch is activated because it would require slightly less power (but the Atmega168 pins are capable of holding only an input pin HIGH and not LOW), you must utilize the Arduino's internal pull-up resistors to avoid using external resistors.

To use the Arduino's internal pull-up resistors, you simply declare the pin as an INPUT using pinMode() in the setup() function; then digitalWrite the pin HIGH. With the pull-up resistor enabled, digital pin 2 in Listing 7-1 is HIGH by default unless driven LOW by some other source (that is, the bump switch). You can test the following example by running it on your Arduino and viewing the Serial monitor. Connect pin 2 to GND to see a 0 reading; otherwise, it reads 1.

Example 7.1. Reading a Contact Switch

// Code Example 7-1: Reading a contact switch
// Switch wires should connect to GND and Arduino digital pin 2
// The LED on pin 13 will stay On, unless pin 2 is connected to GND
// The variable "button_state" will hold the value of the button
// The button value can be either HIGH (1) or LOW (0)

int LED = 13;  // use LED connected to pin 13
int button = 2; // use pin 2 to read the button switch
int button_state; // use this variable to hold the value of "button" (pin 2).

void setup(){
  Serial.begin(9600);  // Start serial monitor at 9600 bps.

  pinMode(LED, OUTPUT);   // declare "LED" (pin 13) as an OUTPUT.
  pinMode(button, INPUT);   // declare "switch" (pin 2) as an INPUT.
  digitalWrite(button, HIGH);   // Enable the internal Pull-up resistor on Pin 2.
}

void loop(){
  button_state = digitalRead(button); // read the button

    if (button_state == 0){     // if the button_state is equal to 0 (LOW),
    Serial.println("LOW");    // then serial print the word "LOW"
    digitalWrite(LED, LOW);   // and turn the LED on pin 13 Off.
}
  else {                      // Otherwise, the input is equal to 1 (HIGH)
    Serial.println("HIGH");   // so serial print the word "HIGH"
    digitalWrite(LED, HIGH);  // and turn the LED on pin 13 On.
  }
}

How the Bug-bot Works

This robot acts as an autonomous rover, driving around a room until it bumps into an obstacle. The idea is to place the sensors such that they have the widest detection area possible; this ensures that the bot does not drive into an obstacle without detecting it. It is also helpful if the sensors provide enough time to be activated and the robot stopped before it hits the obstacle. This way, your robot won't run around like a bull in a china shop, knocking things over as it rams into them.

Antennae Sensors

When designing the front bump sensors for this project, I thought it might be fun to model their function after a real-life bump sensor—like an insect antennae. To feel their way around a room, many insects rely heavily on their antennae. One of the purposes of the antennae is to detect a change in the environment (that is, a wall or obstacle) before the bug reaches the change to give it time to adjust its path.

Along the same lines, I decided to make two antennae "feelers" on the front of the Bug-bot (see Figure 7-2) to detect a wall or an obstacle. The design is quite simple; the Arduino Input wire connects to a coiled wire (a home-made spring), and a bolt connected to GND runs through the center of the coil without touching it. If the coil spring is moved, it touches the bolt and connects to GND, thereby notifying the Arduino that it has bumped into something.

The Antennae sensors are simple contact switches using a coiled copper wire attached to the Arduino input pin and a bolt attached to Arduino GND.

Figure 7.2. The Antennae sensors are simple contact switches using a coiled copper wire attached to the Arduino input pin and a bolt attached to Arduino GND.

I unwrapped about 5 inches from the top of the home-made wire coil and straightened it out in front of the robot to resemble the antennae of an ant or caterpillar. When the bot comes within a few inches of a wall or other object, the wire antennae touch the object, which moves the coil spring until it touches the GND bolt running through its center. When the switch is Closed, the Arduino immediately stops, reverses, and turns before heading in a new direction. This way, the robot can gently cruise the room without causing any damage.

Bumper Sensors

The rear bump sensors are made using three lever switches with aluminum bumpers attached to broaden their bump detection range. These are simple SPST switches that cost approximately $2 each and act in the same way as the antennae switches that you mount to the front. I decided to break the rear bumper range into three parts, left, center, and right, so the robot knows where it was bumped.

Now that you understand how the bump sensors interface to the Arduino, review the complete parts list for the Bug-bot (Table 7-1) before building.

Parts List for the Bug-bot

The parts list for this project should be a bit less expensive than the previous chapters (Table 7-1) because you build this robot "MacGyver style." To keep the cost down, make a simple acrylic frame. The Arduino clone was borrowed from Chapter 6. The antennae sensors are composed of just a few items you should have laying around, and you do not need to purchase a motor controller because of the modified Servo motors used.

Table 7.1. The Bug-Bot Parts List

Part

Description

Price

Two Servo motors: continuous rotation

HobbyPartz.com (part# Servo_SG5010). These are cheaper Servo motors that

$4.90 each

Arduino Clone: from Chapter 6 (or other Arduino)

Home-made Arduino clone: Uses an FTDI cable for programming, has own +5v regulator, and accepts most Arduino shields.

$10-$15

Three SPST limit switches

Sparkfun part# COM-00098: Switches are actually SPDT, but you use only two of the thee poles.

$1.95 each

6v battery

Sparkfun part# PRT-08159: Four AA battery holder yields 4.8v (with 1.2v rechargeables) or 6v (with 1.5v alkalines). 6v rechargeable battery pack.

$2.00

Two wheels

I pulled two wheels from an old thrift-store R/C car that I had laying around.

$1.00

12-inch × 16-inch plexiglass sheet, ¼-inch thick (6mm)

Your local hardware store should sell sheets of ¼inch-thick acrylic plexiglass, or you can order it online.

$7.00

¾-inch wide aluminum flat bar: ⅛-inch-thick, 12-inch long

Again, your hardware store should sell assorted pieces of metal; if not, look online.

$3.00

Two SPST power switches

Radio Shack part#275-324. These are standard SPST switches: one is used for power and the other to toggle the mode of the robot. These are optional but make things easier.

$2.99 ea

Most of these parts should be locally available for you to purchase; although Servo motors are typically less expensive online. The bump sensors can be any momentary button switch that you can find, and the toggle switches can be recycled or mismatched as long as they work.

Note

If you don't want to build a new robot base, you can repurpose or add bump sensors to one of the previous robots: Linus or Wally. Although I build a different platform for each project to give examples of the many ways to build a robot, most of the concepts and examples used in this book can be hacked onto another robotic platform and should require only minor tweaking.

I bring this up to let you know that you do not have to actually build three robots to do three different things—if you can afford only the parts for one frame, you can still add several different sensors to it to make a multifunction robot. If you already have a frame, you can skip the frame-related parts and simply add the sensors to your existing robot.

The Motors

For this bot, I again use hobby Servo motors modified for continuous rotation. You can either buy these motors from Sparkfun.com (part# ROB-09347) premodified, or you can modify a normal Servo motor using the steps this chapter provides.

These motors use little power and provide a large amount of torque for their size, but they need to have wheels mounted to them (as you did in Chapter 4). Luckily, most Servo motors come with a small bag with several adapter plates in various sizes that mount to the Servo output shaft. I try to find the two wheels (usually from a thrift store toy car) and then go through the Servo adapter plates to see which one has the best fit to the wheel—usually the largest one.

Modifying the Servo Motors

When modifying the Servo motors in Linus the line-bot (Chapter 4), I removed the entire electronics circuit leaving only a DC gear-motor; this time with the bug-bot, I modified only the circuit to retain use of the built-in motor-controller. You might recall that this modification requires removing both the plastic stop piece on the motor's output shaft and the positioning potentiometer. Without removing these two pieces, the output shaft of the Servo cannot physically complete a full rotation (see Figure 7-3).

On the left, you can see the potentiometer mounted to the Servo motor control board. In the center is the resistor divider created from two 2.2k ohm resistors to replace the potentiometer. On the right is the Servo motor gear box with the plastic stop piece that must be removed.

Figure 7.3. On the left, you can see the potentiometer mounted to the Servo motor control board. In the center is the resistor divider created from two 2.2k ohm resistors to replace the potentiometer. On the right is the Servo motor gear box with the plastic stop piece that must be removed.

Materials needed for continuous rotation are as follows:

  • Small Philips-head screwdriver

  • Soldering iron

  • Pair of small wire snips

  • Two 2.2k ohm resistors

The potentiometer reports the current position of the output shaft to the built-in motor controller so that it knows how to command the motor, so you just need to remove the potentiometer (by unsoldering) and replace it with a 2.2k ohm resistor divider. You can create the resistor divider by connecting one lead from each resistor to the outside holes previously occupied by the potentiometer, and connecting the other leads to each other and the center hole of the potentiometer (see Figure 7-4). The resistor divider creates a signal that mimics the center position of the potentiometer, thereby tricking the Servo motor into thinking that it is always centered, regardless of the actual position of the output shaft.

The potentiometer has been removed and the resistor divider has been soldered in its place.

Figure 7.4. The potentiometer has been removed and the resistor divider has been soldered in its place.

To complete the continuous rotation process, you must also remove the plastic stop on the motor output shaft to allow it to spin 360 degrees. To access this stop, remove the black plastic gear-box cover to reveal the base of the output shaft (as done in Chapter 4). You should see a small 3mm × 3mm piece of plastic protruding from the output shaft that keeps the shaft from spinning 360 degrees. You must completely remove this piece of plastic using a small razor knife (see Figure 7-5). Test the output shaft after removing the plastic piece to make sure it spins all the way around before re-assembling.

The plastic stop removed from the largest plastic gear (which is also the gear box output shaft)

Figure 7.5. The plastic stop removed from the largest plastic gear (which is also the gear box output shaft)

This modification enables you to drive the Servo motor directly from any Arduino pin, using the internal motor-driver circuitry built in to the Servo. The servo now acts as a gear motor with a built-in motor controller that accepts pulse signal inputs.

Controlling the Servo Motors

Remember that the Servo motor's drive circuitry is intended to use an input pulse signal from 1000 microseconds (uS) to 2000uS from an R/C receiver to direct the motor to the correct position. By replacing the potentiometer with two 2.2K ohm resistors (as a voltage divider), the Servo thinks that the motor shaft is always at the center position, regardless of where it is. If you command the Servo to full forward (2000uS pulses), the motor tries to spin indefinitely forward and never reaches its destination (that is, continuous rotation). To stop the Servo, you must provide it with a pulse signal that commands it to the position defined by the 2.2k ohm resistor divider. (This should be a pulse of approximately 1500 microseconds.)

After you replace the potentiometer with a resistor bridge, you should test the modified Servos not only to ensure that they work properly, but also to determine the stop pulse for each motor and record it for use in the final code. Using the example Code 7-2, you can connect the potentiometer removed from the Servo motor to Arduino A0 and open the Serial monitor to see the values. Simply turn the potentiometer until the motor stops spinning and record the value shown on the Serial monitor of your computer. To set up your Arduino and Servo motor to use the example test code, connect the Servo motor control wire (white or yellow) to the Arduino D9 and a potentiometer connected to A0, as shown in Figure 7-6. You also need to connect +5v and GND wires to the Servo and potentiometer.

The connections needed to test the modified Servo motors with the Arduino and a potentiometer

Figure 7.6. The connections needed to test the modified Servo motors with the Arduino and a potentiometer

Converting the Pulse Value to Degrees

Use the Servo.h library for Arduino to make the code easier to read and follow. The library provides the necessary functions to drive the Servo motors with only one line of code in the loop, each time you want to change speed or direction. Instead of commanding the Servo with a specific pulse value, the library interpolates the 1000uS – 2000uS pulse range into the 0 degrees: 179 degrees range of a standard unmodified hobby Servo motor. To stop the Servo motor, you must command it to its center position (the position supplied by the 2.2k resistor divider) using a neutral pulse, typically 89 using the Servo library (halfway between 0 and 179).

Use Listing 7-2 to test each motor and find the neutral stop pulse. To avoid reuploading the code to the Arduino multiple times, I added the temporary use of the potentiometer to assist in finding this number for each motor.

The code in Listing 7-2 is intended to test a continuous rotation Servo motor using a potentiometer to control the speed and direction. If you try this code with an standard Servo motor that has not been modified, its angular position corresponds to the position of the potentiometer.

Example 7.2. Continuous Rotation Servo Test

// Connect Servo motor signal wire (white or yellow) to Arduino D9
// Connect Servo +5v and GND wires to Arduino power source
// Connect potentiometer (center pin) to A0, outside pins to +5v and GND.

#include <Servo.h> // Include the Servo.h Arduino library

Servo servo1; // create "servo1"
int speed_val;  // use "speed_val" to hold potentiometer value

void setup() {
  Serial.begin(9600); // start serial monitor at 9600 bps
  servo1.attach(9);  // attach "servo1" to pin 9
}

void loop() {

  // read potentiometer, adjust to servo library angular value range (0-179)
  speed_val = map(analogRead(0), 0, 1023, 0, 179);

  // write adjusted potentiometer value to servo1
  servo1.write(speed_val);

  // print adjusted value to the serial monitor
  Serial.println(speed_val);
}

This code enables you to control any type of hobby Servo motor, standard or continuous rotation. If your Servo motor is not modified, it simply mimics the position of the potentiometer. If you have modified the Servo for continuous rotation, the potentiometer commands the direction and speed of the Servo motor.

With the Servo motors modified and tested, now proceed to mount the wheels to the Servo motor adapter plates and then to the Servo motors.

Mounting the Wheels to the Servos

You can mount the wheels to the Servo adapter plates using either small bolts, hot glue, or both. You can pick just about any old toy with removable wheels to mount to the Servo motors, as long as you make sure they are aligned straight and do not wobble when spinning.

First drill the center of the wheel with a drill bit that is larger than the Servo set screw head, so you can screw the adapter plate onto the Servo output shaft after the adapter plate is mounted to the wheel (see Figure 7-7).

Drill the center of each wheel using a ¼-inch drill bit to make a hole for the set screw to pass completely through, so the Servo output shaft set screw fits snugly against the Servo mounting plate.

Figure 7.7. Drill the center of each wheel using a ¼-inch drill bit to make a hole for the set screw to pass completely through, so the Servo output shaft set screw fits snugly against the Servo mounting plate.

Now mount the adapter plates to the wheels by lining them up as straight as possible before gluing them, as shown in Figure 7-8. Turn the wheel around backward, and look through the axle hole to make sure it is lined up properly with a adapter plate.

You can now test fit the wheels by mounting them on the Servo motor output shafts to make sure the adapter plates are mounted squarely. Test the Servo motor by commanding it full-speed in either direction; while spinning, check to make sure the wheels spin evenly without wobbling.

Center the Servo wheel adapter plates on each wheel before gluing them. You can use Super Glue or high strength hot glue.

Figure 7.8. Center the Servo wheel adapter plates on each wheel before gluing them. You can use Super Glue or high strength hot glue.

With the wheels mounted to the motors, you can begin building the frame.

Building the Frame

Build the frame as simple as possible, which requires only one piece of round plexiglass with holes cut for the motors and wheels. (I added a second piece of plexiglass as a top plate, which is optional.) You can cut plexiglass with a jigsaw and a fine-tooth jigsaw blade. The plexiglass should likely have a protective film coating on it when you buy it; this should be left on while you mark your lines and cut, to protect the clear finish from scratches. You can remove the film after you finish cutting to reveal the clear surface.

Marking the PlexiGlass

I used an 8-inch round electric stove drip pan (see Figure 7-9) as a template to mark the plexiglass with a permanent marker. Because the frame will be whatever size you cut it, you can choose a larger template to build a larger robot. The round template I used was actually a small oven/stove drip pan, labeled as a 6-inch pan, but with the lip it measures 8-inch total.

Mark a circle on the plexiglass using a permanent marker and a 6inch to 8-inch round tin, bowl, or any object the size you would like your frame to be. If you are artistic, you might freehand a design to cut out for your frame.

Figure 7.9. Mark a circle on the plexiglass using a permanent marker and a 6inch to 8-inch round tin, bowl, or any object the size you would like your frame to be. If you are artistic, you might freehand a design to cut out for your frame.

With the circle marked, you need to also mark the cutouts for the motors. Start by setting the wheel/motor pairs onto the acrylic sheet, with the wheels centered in the circle and parallel to each other, as shown in Figure 7-10. Mark two notches in the plexiglass large enough for the wheels to fit into. The wheels cannot stick out from the edge of the plexiglass because you want the bot to spin around without the wheels hitting anything.

Lay the motors and caster wheels onto the plexiglass, and mark the outline of the drive wheels and the mounting holes for the caster wheels.

Figure 7.10. Lay the motors and caster wheels onto the plexiglass, and mark the outline of the drive wheels and the mounting holes for the caster wheels.

Now that you have everything marked on the plexiglass frame, it is ready to be cut.

Cutting the PlexiGlass

With the frame marked, it is now time to cut the circular template line with the jigsaw. As you cut the plastic sheet, move the jigsaw slowly with the motor at full speed to ensure a clean cut and avoid cracking. If you move slowly and keep your eye on the blade, making sure it stays on the outside edge of the marked line, it should take only about 2 to 3 minutes to cut this piece (see Figure 7-11).

The circular shape has been cut, the caster wheel mounting holes have been marked, and the outline for the drive wheels has been marked.

Figure 7.11. The circular shape has been cut, the caster wheel mounting holes have been marked, and the outline for the drive wheels has been marked.

In Figure 7-11, you can see the circular piece of plexiglass after cutting with the jigsaw along the template line. Cut on the outside of the marked line because you can always go back and cut more, but it is hard to do accurately if you have already cut the marked line completely off. (That is, you cut the inside edge of the line.)

You can now cut out the sections for the motors and drill holes for the caster wheels, as shown in Figure 7-12.

After cutting with a jigsaw (fine-tooth blade) and drilling holes for the caster wheels, the frame base plate is ready to mount the motors and wheels.

Figure 7.12. After cutting with a jigsaw (fine-tooth blade) and drilling holes for the caster wheels, the frame base plate is ready to mount the motors and wheels.

In Figure 7-12, you can see the circular frame that has been cut to allow for the wheels to poke through. I lined the motors up with the wheels attached and marked their silhouette with a red permanent marker, aligning them as centered as possible. At this point, you can also drill the mounting holes for the two caster wheels.

Mounting the Motors

Mount the motors to the plexiglass using hot glue to keep them in place. Apply enough glue to cover the majority of the Servo motor casing; then press each motor to the frame, making sure the motors are parallel to each other and the cuts. The motor shafts should poke out from the plexiglass, as shown in Figure 7-13.

Using a high-temperature glue gun, glue each motor into place onto the plexiglass frame. Center the motor output shafts in the gap on each side of the frame, accessible to mount the wheels.

Figure 7.13. Using a high-temperature glue gun, glue each motor into place onto the plexiglass frame. Center the motor output shafts in the gap on each side of the frame, accessible to mount the wheels.

You can now mount the wheels with adapter plates to the Servo motor output shafts. Simply place the adapter plate onto the Servo; then insert the set screw and tighten it down.

Note

If the motors are not mounted parallel to each other, the wheels will either point toward or away from each other, and the robot will not drive completely straight.

Mounting the Caster Wheels

With the motors mounted, you need to mount the two caster wheels to the front and back of the bot; this keeps the bot balanced going either direction. I used 8 small bolts to secure the caster wheels to the plexiglass, using 3 nuts on each bolt to both secure and adjust the height of the caster wheels. You need 8 bolts and 24 nuts total to mount both of them.

Use the first nut to secure each bolt tightly to the caster wheel mounting plate. Use the second nut to set the height of the caster wheel from the frame; it should be placed on the bolt about halfway down (for starters). The third nut secures the plexiglass to the second height adjusting nut. If you need to adjust the height of the caster wheel, loosen nuts two and three, adjust to the desired height, and then retighten nuts two and three to the plexiglass frame (see Figure 7-14).

Use three nuts on each bolt to make both caster wheels adjustable in height.

Figure 7.14. Use three nuts on each bolt to make both caster wheels adjustable in height.

The motors and caster wheels are the only things mounted to the bottom of the frame (see Figure 7-15). The Arduino, battery, and sensors are all mounted to the top for easy access. I drilled a large ½-inch hole through the frame to get the Servo motor wires from the bottom to the top where I needed to plug them into the Arduino.

From the underside of the frame, you can see the motors mounted with wheels attached.

Figure 7.15. From the underside of the frame, you can see the motors mounted with wheels attached.

With the bottom of the frame finished, now focus some attention to the top, where the Arduino, front and rear sensors, toggle switches, and battery will be mounted.

Mounting the Arduino

Mount the Arduino on top of the plexiglass frame. I used four bolts to mount my Arduino clone to the frame of the Bump-bot; although if you use a standard Arduino, you need only three.

The easiest way to mount the Arduino is to use #6 size nuts and bolts (1-inch or longer) to secure it to the frame. I placed the Arduino where I wanted to mount it and used a permanent marker to mark the mounting holes onto the plexiglass. When marked, drill holes through the plexiglass, install the bolts pointing upward, and secure tightly with one nut each (see Figure 7-16). These bolts should now fit nicely through the Arduino mounting holes, and you can then use a few more nuts on top of the Arduino to hold it down securely to the frame.

Measure and mark four holes to mount the Arduino onto the frame base' then drill the marked spots and use #6 bolts to hold the Arduino into place.

Figure 7.16. Measure and mark four holes to mount the Arduino onto the frame base' then drill the marked spots and use #6 bolts to hold the Arduino into place.

When the Arduino is in place, you still need to mount the battery pack and build the sensors before making connections.

Installing the Battery

You can mount the battery anywhere there is room; although because it is usually the heaviest part of the robot, place it above the wheel axis or as close as possible.

To hold the battery in place, I marked and drilled one hole on each end through the plexiglass and secured it down with two zip ties, as shown in Figure 7-17). You can be easily cut and replace the zip ties if needed, but they can retain their secure hold for many years if left alone. Alternatively, you can use a few dabs of hot glue from a glue gun to secure the battery to the top of the plexiglass frame.

The 6v battery strapped to the frame with a zip tie

Figure 7.17. The 6v battery strapped to the frame with a zip tie

I used another 6v 1000mAh NiCad battery pack from Radio Shack (one of my $0.47 clearance bin finds) and the motor speed was right on par. For longer run time, you can add multiple battery packs in parallel.

Installing the power and mode switches, I used a power switch (SPST) between the battery and Arduino, allowing for easy power switching (see Figure 7-18). The power switch can be any size but should have a current rating of 5 amps or higher to ensure that it does not overheat.

To complete the basic construction of the robot, install the power switch and optional mode switch to change the direction of the Bug-bot.

Figure 7.18. To complete the basic construction of the robot, install the power switch and optional mode switch to change the direction of the Bug-bot.

To add a mode switch, you need to mount a second toggle switch to the frame. This is a SPST mode switch used to switch the default direction of the Bump-bot, depending on which sensors you use. Connect the two pins of the mode switch to the Arduino digital pin 4 and GND.

Now that you have a powered Arduino, make a few sensors and get the Bug-bot on its way.

Making the Sensors

This robot has two different types of bump sensors: antennae feelers and bump switches. Make the antennae feelers from materials you find around the house, whereas the bump switches are small-limit switches with aluminum bumpers attached to them.

The Front Antennae Sensors

The antennae sensors are quite easy to make. You need a 4-foot to 6-foot strand of 14awg-18awg solid copper wire (bare or stripped) and a ¾-inch round rod or pipe to wrap it around (see Figure 7-19). Start by stripping any rubber insulation from the copper wire, leaving it in a single long piece. When stripped, place the ¾-inch round pipe or rod into a bench vise with the end of the copper wire secured to it. Begin wrapping the copper wire as closely as possible until the wire runs out, periodically tightening the wire as you wrap. Do this twice because you have two front antennae sensors.

This image shows the wire wrapped around a ¾-inch rod to give it a coiled shape (left), and when removed it retains the coils (right).

Figure 7.19. This image shows the wire wrapped around a ¾-inch rod to give it a coiled shape (left), and when removed it retains the coils (right).

You can unwrap the end of the coiled wire about 6-inch at the top and straighten it out. This is where the shape of the antennae comes from; bend it as you want. Then solder a signal wire to the bottom of the coil to plug into the Arduino. The GND wire should be soldered directly to the bolt that you place in the center of the coil, as shown in Figure 7-20.

Activate the internal pull-up resistors on the Arduino pins used to read each sensor, and the inputs read HIGH unless you close a switch and connect to GND.

Solder a GND wire to the bottom of each bolt and solder a signal wire to the base of each coil.

Figure 7.20. Solder a GND wire to the bottom of each bolt and solder a signal wire to the base of each coil.

Drill a hole in the plexiglass on each side of the front caster wheel to mount the GND bolts for the antennae sensors. Tighten the nut down securely on the GND bolts, and place the coiled wires around them with the antennae at the top. If you use a ¾-inch round rod to wrap your antennae around, you should have plenty of space between the antennae and the bolt. Then position the coiled wire as close to center as you can, and hot glue the base of the coil to the plexiglass frame, quite liberally. It does not hurt to glue the bottom two spirals of the coil, but try not to get glue on any of the other copper spirals because it might hinder the flexibility of the sensor.

The Rear Bump Sensors

The bump sensors on the rear of the bot are small limit switches from Sparkfun.com that detect when the bot bumps into something. There are three of these bump switches, each with its own small bumper to expand each sensor's bumpable range.

Figure 7-21 shows the parts needed for the rear bumper: three SPST switches and a 12-inch piece of aluminum flat bar, ⅛-inch thick, ¾-inch wide. Bend the flat bar to fit the contour of the rear of the plexiglass frame. Use a vise and slightly bend the aluminum bar every two or three inches; then place it against the rear of the frame to make sure it fits.

The three contact switches used for the rear of the robot, with a piece of ¾-inch wide aluminum flat bar, bent to the curve of the frame.

Figure 7.21. The three contact switches used for the rear of the robot, with a piece of ¾-inch wide aluminum flat bar, bent to the curve of the frame.

When fitted with the rear of the bot, you can cut the aluminum rear bumper with a hack saw into three equal pieces to mount on each sensor (see Figure 7-22). Together, the sensors create a rear bumper capable of detecting left, center, and right impact. I also made three small "L" brackets, each from a piece of aluminum about ½-inch wide and 2-inch long. Glue these brackets to the switches to help secure them to the plexiglass frame.

The aluminum bumper bar, cut into three equal sections for each contact switch and the small "L" brackets used to mount the rear bump switches to the frame

Figure 7.22. The aluminum bumper bar, cut into three equal sections for each contact switch and the small "L" brackets used to mount the rear bump switches to the frame

With the aluminum bar cut into three pieces, mount the bump switch sensors onto the robot frame and attach the bumper levers. Start by hot gluing the small "L" brackets to the sides and bottom of each bump switch.

Next, glue the bottom of each "L" bracket to the frame; one center and the other two equally spaced between the center and each drive wheel. Make sure there is about ½-inch between each sensor to allow movement when pressed without touching each other.

Finally, hot glue the aluminum bumpers to the limit-switch arms (see Figure 7-23). You can use Epoxy, a small bolt, hot glue, solder, or any combination of these to mount the bumpers to the switch levers, so long as they stay attached when bumped.

Two of the three rear contact switches and aluminum bumpers installed. Make sure the wires soldered to the contact switches are long enough to reach the Arduino.

Figure 7.23. Two of the three rear contact switches and aluminum bumpers installed. Make sure the wires soldered to the contact switches are long enough to reach the Arduino.

With all sensors installed and the bumpers mounted, this robot should have all the hardware that it needs, but you still need to wire it up.

Making Wire Connections

You need to connect five sensors, two motors, and a battery to connect to the Arduino before loading the code and testing. The two antennae sensors in the front connect to digital pins 2 and 3. The bumper sensors in the rear connect to analog pins 0, 1, and 2, which are also called digital pins 14, 15, and 16 respectively, when used as a digital input or output. Again, the analog input pins are used only as digital inputs because they were closer to the rear bumper sensors. Use Table 7-2 to make sure each wire connects correctly before proceeding.

Table 7.2. Connections that need to be made from the motors, mode switch, and each sensor to the Arduino.

Component

Connection

Arduino connection

servo_L

Control wire (white, yellow, orange) from the Servo plug.

D9

servo_R

Control wire (white, yellow, orange) from the Servo plug.

D10

mode_pin

SPST switch: Wire one terminal to GND and the other to the Arduino digital input pin.

D4

antennae_L

Coiled, bare copper wire with a separate wire connecting the coil base to the Arduino digital input pin.

D3

antennae_R

Coiled, bare copper wire with a separate wire connecting the coil base to the Arduino digital input pin.

D2

bumper_R

SPST switch: Wire one terminal to GND and the other to the Arduino digital input pin.

D14 (A0)

bumper_C

SPST switch: Wire one terminal to GND and the other to the Arduino digital input pin.

D15 (A1)

bumper_L

SPST switch: Wire one terminal to GND and the other to the Arduino digital input pin.

D16 (A2)

Remember to connect the power signals to the Servo motor connectors (VIN+ and GND from battery) and the GND signals for each sensor and input switch. After you connect everything (see Figure 7-24), you can load the code to the Arduino and bring the Bug-bot to life!

The Bug-bot with all sensors installed, ready to test

Figure 7.24. The Bug-bot with all sensors installed, ready to test

With the necessary building steps out of the way, now load the code to the Arduino and start testing!

Loading the Code

The code for the Bug-bot should be easy to follow. This robot has only digital switches, so you can actually use any sensor on any Arduino pin using the digitalRead() command. I have them plugged into the closest pin to each sensor, but you can make adjustments as you need. Just remember to make the corresponding changes in the code.

To make things easier, the Servo motors are controlled using the Servo.h Arduino library. This library looks for an angular input value between 0 and 179 to command the speed and direction of a continuous rotation Servo, where a value of 89 should command the Servo motor to stop. The Arduino Servo library removes some of the complicated coding when working with Servo motor pulse signals.

To learn more about this library, visit the Arduino reference pages at http://arduino.cc/en/Reference/Servo.

Creating a Delay

The caveat to using a pulse signal to control the Servo motors is that a pulse is required every 20 milliseconds or so to keep the motor spinning. If no pulse is received, the motors stops until it receives a valid pulse. For instance, to back up for 1 second and then turn right for 500 milliseconds using the delay() function would pause the main loop, and no pulse signals would be sent until the delay() was complete.

To get around the delay() issue, record the value of the main system timer into a variable, and use it as a timestamp to carry out an action for a specific amount of time. The while() function creates a loop that repeats until its condition is no longer true, which can be useful with a timestamp. Simply record the system timer value when the while() loop begins, and then check the system timer over and over again until it reaches the specified time. When the condition is met, the while() loop exits and returns to the main loop(). Listing 7-3 avoids using the delay() function to blink an LED on for 3 seconds and then off for 3 seconds.

Example 7.3. Blink LED using the millis() Timer Value and while() Function

// Code 7-3 - Set time without using delay()
// Blinks LED on pin 13 for time set by variable "delay_time"

int led = 13;
int delay_time = 3000;
long timerVal;

void setup(){
  pinMode(led, OUTPUT);
}

void loop(){

  timerVal = millis();  // record the millis() value
  while (millis() < timerVal + delay_time){
    digitalWrite(led, HIGH); // turn LED On for delay_time
  }
  timerVal = millis();  // record the millis() value
  while (millis() < timerVal + delay_time){
    digitalWrite(led, LOW); // turn LED Off for delay_time
  }
}

The example records the millis() main system timer value in milliseconds. The desired "delay" for the action is then referenced from the recorded millis() value, whereas the rest of the while() loop continues. Each time the loop circles, it checks the new millis() value and compares it against the original that was recorded (that is, when the bump switch was tripped). If the new value is below the value that you set (that is, 3000 milliseconds), it continues looping; otherwise, the Arduino knows that it has been 3 seconds since it started the action, and exits the while() function back to the main loop. This method enables the motors to be updated continuously, even while the bot is backing up or turning.

Variables

When reading the millis() system timer value, use a variable type that can accommodate a large number. Now review a few of the common available types.

The standard int variable can accommodate a 2-byte value from −32,768 to 32,767. Although this is fine for most variables, the millis() system timer counts in milliseconds, of which there are 1000 each second. This means that the millis() timer value can run over the 32,767 integer value range (defined in the Arduino reference pages), about 32 seconds after you turn on the Arduino. The int variable type does not work for this purpose.

See the Arduino reference page for more information about the int variable at http://arduino.cc/en/Reference/Int.

By changing the int to an unsigned int, the value can no longer be negative, thus yielding a range from 0 to 65,535. This doubles the capacity of only the int variable type, which is about 65 seconds when counting in milliseconds, so you actually need a different type of variable.

See the Arduino reference page for more information about the unsigned int variable at : http://arduino.cc/en/Reference/UnsignedInt.

The long variable can hold larger 4-byte numbers ranging from −2,147,483,648 to 2,147,483,647. This variable has an exponentially larger value range that should be adequate for your uses. Because 2,147,483,647 milliseconds calculates to approximately 24 days, this variable type should be adequate for your needs in this project.

See the Arduino reference page for more information about the long variable at http://arduino.cc/en/Reference/Long.

You can double the range of the long variable by changing it to an unsigned long variable. An unsigned value cannot contain a negative number, so the range begins at 0 and counts up. This means an unsigned long can hold a value ranging from 0 to 4,294,967,295, which is about 48 days worth of milliseconds.

See the Arduino reference page for more information about the unsigned long variable at http://arduino.cc/en/Reference/UnsignedLong.

Although the long variable would be sufficient for the Bug-bot (I don't plan on running it for 24 days straight!), I used the unsigned long variable to store the millis() value in this sketch because the millis() value is never negative.

The variable in this sketch that holds the millis() value is declared as the following:

unsigned long timer_startTick;

The millis() system timer also resets after approximately 48 days, so if your Bug-bot still runs that long without being reset, don't worry. The system timer will overflow at the same time that the unsigned long value runs out of room, and your insanely long-lasting robot should keep going.

The Code

Ready to upload? Copy the text from Listing 7-4 into your Arduino IDE or download the file from https://sites.google.com/site/arduinorobotics/home/chapter7_files.

Each line of code is commented to describe what it does. Several motor movement functions are at the end of the code (after the loop) to keep you from writing so many commands.

Example 7.4. The Main Code That Should Be Loaded to the Arduino

// Bug-bot v1.2
// (2) Servo motors (modified for continuous rotation) with tank-steering setup (pins 9
The Main Code That Should Be Loaded to the Arduino
and 10). // (5) bump sensors total - 2 in front (pins 2 and 3) and 3 in rear (pins 14, 15, & 16). // All sensors are normally HIGH (1) using arduino internal pull-up resistors. // Sensors are brought LOW (0) by contacting the switch connected to GND. // Either set of sensors can be used (front or back), by changing Mode Switch on pin 4. // Pin 4 (HIGH or LOW) changes the bots default direction and sensors. //
// include the Servo.h Arduino library

#include <Servo.h>

// create instances for each servo using the Servo.h library
// for more information, see: http://arduino.cc/en/Reference/Servo
Servo servo_L;
Servo servo_R;

//////////////////////////  Variables used for testing (you can change these)
The Main Code That Should Be Loaded to the Arduino
///////////////// // use to determine direction of bot and which sensors to use. int mode_pin = 4; // connect the mode switch to digital pin 4 int antennae_L = 3; // connect left antennae sensor to digital pin 3 int antennae_R = 2; // connect right antennae sensor to digital pin 2 int bumper_R = 14; // connect right bump sensor to Analog pin 0, which is pin 14 when used
The Main Code That Should Be Loaded to the Arduino
as a digital pin int bumper_C = 15; // connect center bump sensor to Analog pin 1 (digital pin 15) int bumper_L = 16; // connect left bump sensor to Analog pin 2 (digital pin 16) // Value to change servo stopping point pulse - use Code 7-2 to determine the specific
The Main Code That Should Be Loaded to the Arduino
pulse for each motor int servo_R_stop = 89; // set the Neutral position for Right Servo - change as needed int servo_L_stop = 89; // set the Neutral position for Left Servo - change as needed // integers to use for updating Servo motors // change these values to change the various motor actions int stop_time = 1000; // stop for 1000 millliseconds = 1 second int backup_time = 700; // backup for 700 milliseconds = .7 seconds int turn_time = 300; // turn (either direction) for 300 milliseconds = .3 seconds ////////////////////////// End of variables used for testing //////////////////////////////// // value names used to hold timing variables. unsigned long timer_startTick; // value names used to hold antennae states int antennae_R_val; int antennae_L_val; // value names used to hold bumper states int bumper_R_val; int bumper_C_val; int bumper_L_val; // Set the forward and reverse speed values for the Right Servo based on the Neutral position int servo_R_forward = servo_R_stop + 50; int servo_R_reverse = servo_R_stop - 50;
// Set the forward and reverse speed values for the Left Servo based on the Neutral position

int servo_L_forward = servo_L_stop - 50;
int servo_L_reverse = servo_L_stop + 50;

// end of variables


// Begin Setup
void setup(){

  Serial.begin(9600); // start Serial connection at 9600 bps

  servo_L.attach(9);  // attach servo_L to pin 9 using the Servo.h library
  servo_R.attach(10); // attach servo_R to pin 10 using the Servo.h library

  pinMode(mode_pin, INPUT);  // declare input
  digitalWrite(mode_pin, HIGH); // enable pull-up resistor

  pinMode(antennae_R, INPUT);  // declare input
  digitalWrite(antennae_R, HIGH); // enable pull-up resistor
  pinMode(antennae_L, INPUT);  // declare input
  digitalWrite(antennae_L, HIGH); // enable pull-up resistor

  pinMode(bumper_R, INPUT);  // declare input
  digitalWrite(bumper_R, HIGH); // enable pull-up resistor
  pinMode(bumper_C, INPUT);  // declare input
  digitalWrite(bumper_C, HIGH); // enable pull-up resistor
  pinMode(bumper_L, INPUT);  // declare input
  digitalWrite(bumper_L, HIGH); // enable pull-up resistor
}
// End Setup


// Begin Loop
void loop(){

  ////////////////////////////////////////////////////////
  // if the switch_pin is LOW, use the Antennae sensors
  ////////////////////////////////////////////////////////
  if (digitalRead(mode_pin) == 0){

    antennae_R_val = digitalRead(antennae_R); // read Right antennae
    antennae_L_val = digitalRead(antennae_L); // read Left antennae

    // Use Antennae sensors
    // check to see if either antennae sensor is equal to GND (it is being touched).
    if (antennae_R_val == 0 || antennae_L_val == 0){

      // now check to see if only the Left antennae was touched
      if (antennae_R_val == 0 && antennae_L_val == 1){
        // if so, print the word "Left"
Serial.println("Left");
        // reset timer
        timer_startTick = millis();
        // Stop motors
        stop_motors();
        // back up a bit
        backup_motors();
        // turn Right for a bit
        turn_right();
      }

      // otherwise, if the Right sensor was touched and the Left was not
      else if (antennae_R_val == 1 && antennae_L_val == 0){
        // print the word "Right"
        Serial.println("Right");
        // reset timer
        timer_startTick = millis();
        // Stop motors
        stop_motors();
        // back up a bit
        backup_motors();
        // turn Left for a bit
        turn_left();
      }

      else {
        // otherwise, both antennae sensors were touched
        // print the word "Both"
        Serial.println("Both");
        // reset timer
        timer_startTick = millis();
        // Stop motors
        stop_motors();
        // back up a bit
        backup_motors();
        // turn either direction
        turn_left();
      }
    }

    else {
      // otherwise no sensors were touched, so go Forward!
      forward_motors();
    }

    // print the states of each antennae
    Serial.print("Right sensor");
    Serial.print(antennae_R_val);
    Serial.print("    ");
    Serial.print("Left sensor");
    Serial.print(antennae_L_val);
    Serial.println("    ");
// End Antennae sensors

  }
  ///////////////////////////////////////////////////////////
  // Else, if the switch_pin is HIGH, use the Bumper sensors
  ///////////////////////////////////////////////////////////
  else{

    // read the bumper sensors
    bumper_R_val = digitalRead(bumper_R);
    bumper_C_val = digitalRead(bumper_C);
    bumper_L_val = digitalRead(bumper_L);

    // Use Bumper sensors
    // check to see if the right bumper was touched
    if (bumper_R_val == 0){
      // if so, print the word "Right"
      Serial.println("Right");
      // reset timer
      timer_startTick = millis();
      // Stop motors
      stop_motors();
      // back up a bit
      ahead_motors();
      // turn Left
      turn_left();

    }

    // check to see if the left bumper was touched
    else if (bumper_L_val == 0){
      // if so, print the word "Left"
      Serial.println("Left");
      // reset timer
      timer_startTick = millis();
      // Stop motors
      stop_motors();
      // back up a bit
      ahead_motors();
      // turn Right
      turn_right();
    }

    // check to see if the center bumper was touched
    else if (bumper_C_val == 0){
      // if so, print the word "Center"
      Serial.println("Center");
      // reset timer
      timer_startTick = millis();
      // Stop motors
      stop_motors();
      // back up a bit
ahead_motors();
      // turn Left
      turn_left();
    }

    else{
      // otherwise no sensors were touched, so go Forward (which is actually Reverse when
The Main Code That Should Be Loaded to the Arduino
the direction is switched)! reverse_motors(); } // print the states of each bumper Serial.print("Right Bumper: "); Serial.print(bumper_R_val); Serial.print(" "); Serial.print("Left Bumper: "); Serial.print(bumper_R_val); Serial.print(" "); Serial.print("Center Bumper: "); Serial.print(bumper_L_val); Serial.println(" "); } // End Bumper sensors } ///////////////////// End Loop ///////////////////// // Beginning motor control functions void stop_motors(){ // stop motors for the amount of time defined in the "stop_time" variable while(millis() < timer_startTick + stop_time){ servo_L.write(servo_L_stop); servo_R.write(servo_R_stop); } timer_startTick = millis(); // reset timer variable } void backup_motors(){ // backup for the amount of time defined in the "backup_time" variable while(millis() < timer_startTick + backup_time){ servo_L.write(servo_L_reverse); servo_R.write(servo_R_reverse); } timer_startTick = millis(); // reset timer variable } void ahead_motors(){
// go forward for the amount of time defined in the "backup_time" variable
  while(millis() < timer_startTick + backup_time){
    servo_L.write(servo_L_forward);
    servo_R.write(servo_R_forward);
  }
  timer_startTick = millis();  // reset timer variable
}

void turn_right(){
  // turn right for the amount of time defined in the "turn_time" variable
  while(millis() < timer_startTick + turn_time){
    servo_L.write(servo_L_forward);
    servo_R.write(servo_R_reverse);
  }
}

void turn_left(){
  // turn left for the amount of time defined in the "turn_time" variable
  while(millis() < timer_startTick + turn_time){
    servo_L.write(servo_L_reverse);
    servo_R.write(servo_R_forward);
  }
}

void reverse_motors(){
  // go reverse indefinitely
  servo_L.write(servo_L_reverse);
  servo_R.write(servo_R_reverse);
}

void forward_motors(){
  // go forward indefinitely
  servo_L.write(servo_L_forward);
  servo_R.write(servo_R_forward);
}
// End motor control functions

// End Code

The main loop() starts out by reading the state of the mode switch to see if it should use the front antennae sensors or the rear bumper sensors. After that is determined, the individual sensors are read to determine their states. As long as no sensor is touched, the Bug-bot can drive forward until it bumps into something.

You can program random or timed changes in direction to surprise children or pets that might be following your Bug-bot with anticipation. The possibilities for movement are entirely up to you, but you have the basic movements and actions for a simple exploring.

When you finish testing and want to make your robot nice to look at, proceed to the next section to make a bug-themed hat for the Bug-bot.

Making a Top Hat

With the frame assembled and the sensors installed, now put a hat on your little Bug-bot. Cut a piece of plexiglass the same size as the base (8 inches), but this time just cut the circle with no cutouts. The top can be painted or masked, or you can add a mascot to ride along. You can make a design on a computer and paste it to the top of the plexiglass lid with Mod-Podge crafting paste to add some character.

Because there are two bolts in the front of the bot going through the antennae sensors, I used them to mount the lid to the front. You need to add a third bolt in the rear of the bot near the bumper sensors to hold the back end of the lid, mounted from the bottom pointing upward. You can again use two nuts on each bolt to hold the plexiglass lid at the wanted height above the electronics, battery, and wheels (see Figure 7-25).

Cut another 8-inch piece of plexiglass to use for a top piece for the Bug-bot. This can serve as a lid and protect the Arduino from damage.

Figure 7.25. Cut another 8-inch piece of plexiglass to use for a top piece for the Bug-bot. This can serve as a lid and protect the Arduino from damage.

After cutting the top piece, mark the three bolt locations with a permanent marker and drill holes at the three marked locations. After drilling, test fit the clear lid onto the bolts to make sure it fits correctly and is centered above and parallel to the lower plexiglass piece. After the top is verified to fit, it is time to style it up a bit.

My wife used the open-source program Inkscape to create an 8-inch template with a neat design, modeled after an insect. We designed a small box directly above the Arduino to leave clear with no design, so you can see the "brains" of the robot through its new skin. The design was printed onto regular white paper using a color printer, placed on top of the plexiglass lid, with the excess paper trimmed off with an Exacto knife. We used Mod-Podge crafting paste to apply a thin layer beneath the design and then another layer on top of it, removing all air bubbles with a small paint brush while applying. Be sure you get the design where you want it the first time; if you try to move it after pasting it down, you will likely tear the moist paper.

Note

If you get Mod-Podge on the clear window in the center, gently remove it before it dries (within 15 minutes from application) with a few damp cotton swabs to make sure the plexiglass dries perfectly clear.

Make sure you get the orientation correct (top/bottom of lid) so it shows the printed side of the design when installed. In Figure 7-26, you can see the bottom of the lid after pasting the design; the unprinted white paper and the clear window box are all that is visible from the bottom.

The lid with design printed out and pasted on top. Here you can see the bottom view of the design (white paper) and the mounting holes and see-through cutout in the center for viewing the Arduino below.

Figure 7.26. The lid with design printed out and pasted on top. Here you can see the bottom view of the design (white paper) and the mounting holes and see-through cutout in the center for viewing the Arduino below.

After mounting the lid to the frame, you see the finished view of the Bug-bot in Figure 7-27. I painted two washers orange to place on the front bolts because this makes the Bug-bot look like it has eyes. I also spray painted the antennae sensors black (only the ends) to give it a more realistic robotic bug look.

The finished Bug-bot with antennae contact sensors, rear bump sensors, and decorative top hat to give the robot a bug-themed exterior.

Figure 7.27. The finished Bug-bot with antennae contact sensors, rear bump sensors, and decorative top hat to give the robot a bug-themed exterior.

Summary

In this chapter, you built a simple frame with two continuous rotation Servo motors, five contact sensors, a battery, some wheels, and an Arduino. This simple robot is programmed to autonomously explore a room as an insect would, using antennae "feelers" to notify it of any obstructions.

If the Bug-bot's antennae touch anything, it immediately stops driving and turns (depending on which antennae was touched) to find a new path. The antennae sensors were designed to extend a few inches beyond the front of the robot frame, so when an object is detected, the bot has enough time to stop moving before hitting anything. There are also three bumper types sensors attached to the rear of the robot, used to detect objects going the other direction. Using a mode switch, the direction of travel and sensors used can be changed from the front antennae sensors to the rear bumper sensors for a dual-mode operation.

The Bug-bot can be tuned and tweaked to react differently when it touches an object, or even possibly trained to go through a maze. Bump sensors are used on the popular home cleaning robots from iRoomba and are always useful to keep your robots from accidentally running something over. The next chapter focuses on a larger scale robot capable of driving outside...at night...wirelessly. Did somebody say night-vision camera?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset