Read The Arduino Inventor's Guide Online
Authors: Unknown
The Drawbot will move around using the two motor wheels as power and steering and a skid caster at the other end for balance. This method is called
differential steering
. This particular Drawbot is designed as a front-wheel-drive system, using a ping-pong ball as a skid caster in the back. As the Drawbot moves around, it will skid the ping-pong ball over the surface. Glue the ping-pong ball into place as shown in
Figure 8-16
, trying to center it as much as possible for the best balance.
NOTE
If you want to make your own wheels, use the shape and dimensions in
Figure 8-15
for the axle holes.
FIGURE 8-16:
Attaching a ping-pong ball as a skid caster
Now, set the breadboard holder, the Arduino, and a battery pack on top of the chassis, as shown in
Figure 8-17
. Use a little bit of tape or dabs of glue to make sure they don’t move around.
FIGURE 8-17:
The breadboard holder, the Arduino, and a battery pack on the cardboard chassis
Reconnect the USB cable to your Arduino board or plug in your battery pack and watch what happens. You might need to hold on to the cable so that it doesn’t get tangled up. The robot should move forward slowly for 1 second, reverse direction quickly for 1 second, and then stop for 1 second. Because all of your code is in the
loop()
, the Drawbot will repeat this motion over and over again until you disconnect it from power. While you’re working on tweaking your code, you may want to put the Drawbot’s back end up on a few books to keep the wheels from touching the table.
Now, if your robot doesn’t behave like you expect it to, you’ll need to do a little troubleshooting to figure out what’s going on. First, identify the problem. There are two common problems that we’ve seen with this bot: moving in the wrong direction and turning in circles. If it moves backward first instead of forward, switch the red and black wires for both motors going to the H-bridge. If your robot moves in circles instead of moving forward or backward, try flipping the motor wires on either Motor A or Motor B—don’t flip both of them, or you’ll get the same problem again. You should now have a Drawbot that moves forward and then backward, stops, and repeats this motion.
Before moving on, test how far the Drawbot moves in 1 second and make a note of this. You’ll add a marker pen for it to start drawing lines, and you may need to adjust the speeds and the times
so that the Drawbot is easier to control. Slower speeds and shorter times might be best if you’re working on a small table.
Now that you’ve mastered moving your robot forward and backward, see what fun patterns you can make with your new creation. Before you put a marker onto your Drawbot, try turning corners.
To turn the robot to the right, both motors need to spin counterclockwise, and to turn the robot left, they need to spin clockwise. See if you can get your Drawbot to do a little square dance! To draw a square, the basic steps are as follows:
• Move forward.
• Turn 90 degrees.
• Move forward.
• Turn 90 degrees.
• Move forward.
• Turn 90 degrees.
• Move forward.
• Turn 90 degrees.
Figure 8-18
illustrates the steps needed. You’ll notice that you repeat the same steps four times. You already know you can use a
loop()
for repeated actions, but loops repeat forever, and you want your Drawbot to stop after four turns. Luckily there’s a programming technique that’s perfect for repeating a part of the code a set number of times: a
for()
loop.
FIGURE 8-18:
Steps to a simple square dance
A
for()
loop starts with the command
for
, followed by a set of parentheses. Inside the parentheses there are three sections. See
Listing 8-7
.
LISTING 8-7:
The
for()
loop
for
(
➊
int
count = 0;
➋
count < 4;
➌
count++)
{
➍
//insert code here that you want to repeat
}
The first part
➊
is the declaration and initialization of a counter variable that keeps track of repetitions of the loop. You declare this variable as an integer, name it
count
, and initialize it to
0
. You can name this variable anything you want, so long as you use the same variable name in the next two parts. The next part is the
condition statement
➋
, which controls whether the
for()
loop continues to repeat or stops. Here, you continue repeating as long as the condition statement
count < 4
is
true
. Since
count
was initialized at
0
, this condition is
true
on the first pass, and the loop will repeat. The third part is the
increment statement
➌
, which tells the
for()
loop what to do with the counter variable after each repetition. Here,
count++
is a shorthand for
count = count + 1
. This increments the counter variable by 1 for each repetition. The final part
➍
is the code that you want to repeat or loop through, like any code you place inside curly brackets.
So in all, the
for()
loop’s arguments are saying that the loop should continue to run until it’s run four times, at which point the count will be incremented to
4
, the condition statement will be
false
, and the loop will exit. The
for()
loop is a really handy way to clean up code and repeat instructions a particular number of times.
Now, use this new skill to write your square dance code. Replace the
loop()
in your sketch with the
loop()
in
Listing 8-8
. Everything else will stay the same.
LISTING 8-8:
Square dance code
void
loop
()
{
➊
for
(
int
count = 0; count < 4; count++)
{
//drive forward
➋
setMotorA(100);
setMotorB(-100);
➌
delay
(500);
//turn right
➍
setMotorA(-100);
setMotorB(-100);
delay
(250);
}
➎
delay
(1000);
}
SHORTHAND FOR QUICKLY MANIPULATING VARIABLES
Often you may want to increment, decrement, or just modify the value of a variable in code. The most common use is to increment the value of a variable by one for each repetition of a loop, which you can do with the code
variableName = variableName + 1
. But there are also a few shorthand methods to modify values of variables, shown in the following table.
SHORTHAND CODE | LONGHAND CODE | DESCRIPTION |
variableName++; | variableName = variableName + 1; | Increment by 1 |
variableName += 2; | variableName = variableName + 2; | Increment by 2 |
variableName += n; | variableName = variableName + | Increment by |
variableName--; | variableName = variableName - 1; | Decrement by 1 |
variableName -= 2; | variableName = variableName - 2; | Decrement by 2 |
variableName -= n; | variableName + variableName - | Decrement by |
variableName *= n; | variableName = variableName * | Multiply by |
variableName /= n; | variableName = variableName / | Divide by |
To draw a square, the sketch uses the
for()
loop
➊
to repeat the steps four times. The robot first drives forward
➋
for just half a second
➌
. You want to make sure that it doesn’t go too far and draw all over your floors. Next, to turn the robot, the sketch sets both motors to spin counterclockwise
➍
. To complete each square, you add a short, 1-second delay
➎
. Notice that the delay is after the curly bracket for the
for()
loop. The Drawbot will repeat the steps—move forward and turn four times—and then wait for 1 second before the whole
loop()
repeats. This will give you a chance to manually move the Drawbot or reposition it if you need to. The values in this code worked well in our office, but you may need to fine-tune
and play around with the speed settings and timing for your own Drawbot. Tweak your sketch until you get your Drawbot moving in a square-like pattern. Don’t worry if it’s not perfect—just keep testing out the speeds of the corner turns. This is part of the art you’ll be creating!
We’ve included the full sketch for the square-dancing Drawbot in
Listing 8-9
.
LISTING 8-9:
Complete Drawbot square dance code
const byte
AIN1 = 13;
const byte
AIN2 = 12;
const byte
PWMA = 11;
const byte
BIN1 = 8;
const byte
BIN2 = 9;
const byte
PWMB = 10;
void
setup
()
{
pinMode
(AIN1,
OUTPUT
);
pinMode
(AIN2,
OUTPUT
);
pinMode
(PWMA,
OUTPUT
);
pinMode
(BIN1,
OUTPUT
);
pinMode
(BIN2,
OUTPUT
);
pinMode
(PWMB,
OUTPUT
);
}
void
loop
()
{
for
(
int
count = 0; count < 4; count++)
{
//drive forward
setMotorA(100);
setMotorB(-100);
delay
(500);
//turn right
setMotorA(-100);
setMotorB(-100);
delay
(250);
}
delay
(1000);
}
void
setMotorA(
int
motorSpeed)
{
if
(motorSpeed > 0)
{
digitalWrite
(AIN1,
HIGH
);
digitalWrite
(AIN2,
LOW
);
}
else if
(motorSpeed < 0)
{
digitalWrite
(AIN1,
LOW
);
digitalWrite
(AIN2,
HIGH
);
}
else
{
digitalWrite
(AIN1,
LOW
);
digitalWrite
(AIN2,
LOW
);
}
analogWrite
(PWMA,
abs
(motorSpeed));
}
void
setMotorB(
int
motorSpeed)
{
if
(motorSpeed > 0)
{
digitalWrite
(BIN1,
HIGH
);
digitalWrite
(BIN2,
LOW
);
}
else if
(motorSpeed < 0)
{
digitalWrite
(BIN1,
LOW
);
digitalWrite
(BIN2,
HIGH
);
}
else
{
digitalWrite
(BIN1,
LOW
);
digitalWrite
(BIN2,
LOW
);
}
analogWrite
(PWMB,
abs
(motorSpeed));
}