e001036.pdf

(115 KB) Pobierz
138910657 UNPDF
MICROPROCESSORS
programming course (5)
Part 5: Remote Rover
This month we
explore how the BoE-
Bot vehicle can be
made to respond to
commands received
from an infra-red
remote control.
20
V in
P15
V DD
10k
V SS
V in
3300
F
P3
10k
V DD
P0
infrared
receiver
100n
V DD
V SS
8
V
DD
7
4
discharge
reset
P5
Timer
2
trigger
output
3
P6
555
6
5
threshold
control
500
GND
1
Figure 20. The Remote
Rover schematic. Only
one IR receiver is
used (Panasonic type
4602).
10n
10n
By Al Williams
V SS
990050 - 5 - 11
How many remote controls do you
own? If you are like me, the number is
embarrassing. Every piece of con-
sumer electronics seems to have its
own remote these days. When you
lose or break an original remote, you
have to keep buying new remotes —
none of which completely control the
device in question.
Last month, I showed you how to
add infra-red (IR) object detection to
your BoE-Bot. IR components are
plentiful because remote controls
generally use IR to send commands
back to their parent device. So why
not make the IR detector on your
robot pick up commands from a
remote control? If you could com-
municate with the robot remotely,
you could command it to do your
bidding without leaving your chair!
Along the way you’ll find out how
the Basic Stamp measures pulses and
handles arrays.
D ETAILS
The robot circuitry is simple (see Fig-
ure 20 ). This is just about the same cir-
cuit you used last month, except there
is only one IR sensor and no LEDs. The
LEDs are in the remote control unit.
With some experimentation, you could
probably get any remote control to
work. I used a Sony unit because the
SIRCS (Serial Infra Red Control Signal;
sometimes called Control S) protocol is
well documented on the Internet. If
36
Elektor Electronics
1/2000
BASIC Stamp
138910657.007.png 138910657.008.png 138910657.009.png 138910657.010.png 138910657.001.png 138910657.002.png
you don’t have a Sony remote, get a
cheap universal remote and program it
to operate a Sony TV.
There are several common protocols
that remotes use (see
http://www.hut.fi/Misc/Electronics/docs/ir/ir
codes.html for some ideas). Most use
some form of pulse width modulation.
For the Sony protocol, the remote
sends a start bit (often called an AGC
pulse) that is relatively wide (more
than 2 ms). This allows the receiver to
synchronize and adjust its automatic
gain control (this occurs inside the IR
detector module).
After the start bit, the remote sends
a series of pulses. A 600
IRREAD:
PULSIN 0,0,W1
IF W1=0 THEN IRREAD ‘ no pulse
DEBUG ?W1
GOTO IRREAD
instructions between the PULSIN
commands. How is this possible? Sim-
ply store the raw PULSIN results and
process them later when more pro-
cessing time is available.
The problem is where do you store
the raw times? Sure you could use
variables, but you’d need at least eight
word variables (one for the start bit
and seven data bits). This could lead to
some very ugly code. If you are familiar
with other programming languages,
you might be thinking of storing the
counts in an array. That is a good idea
and luckily, the BASIC Stamp supports
arrays.
You can try this simple program to
verify that you get different widths as
you press keys on the remote. Of
course, you are not reading each bit,
so the results are not meaningful yet.
The Sony remote emits 12 data bits (13
if you count the start bit). The first
seven bits comprise the function code
(least-significant bit first) and the next
five bits make up a device ID. Since
you only want to know the function
keys, you can ignore the device ID.
Conceptually, you could read the
word like this:
µ
s pulse is a 0
A RRAYS
An array is a way of grouping similar
variables together using the same vari-
able name, with an index number to dif-
ferentiate them. For example, suppose
you wanted to work with the odd
numbers. You might write:
and 1200
µ
s pulse is a 1. There is a
s gap between each pulse. Of
course a variety of factors will affect the
timing, so you should consider these
times approximate.
µ
IRREAD:
B0=0 ‘ byte read in
B1=1 ‘ bit mask
PULSIN 0,0,W5
IF W5<1200 then IRREAD
‘ not a start bit
FOR B2 = 1 to 7
PULSIN 0,0,W5
IF W5<400 THEN READZERO
B0=B0+B1 ‘ set 1 bit
READZERO:
B1=B1*2 ‘ bump mask up
NEXT
P ULSE MEASUREMENTS
The Stamp is adept at reading pulse
widths (using the PULSIN command).
PULSIN requires three arguments. The
first specifies which pin you want to use
to measure the pulse. The Basic Stamp
will set this pin to be an input if it isn’t
already. The next argument tells the
command if you are looking for a low to
high transition (1) or a high to low tran-
sition (0). The final argument is a word-
sized variable that holds the time dura-
tion of the pulse (if any). The Basic
Stamp uses a 2
oddnums var byte(5)
oddnums(0) = 1
oddnums(1) = 3
oddnums(2) = 5
oddnums(3) = 7
oddnums(4) = 9
Now oddnums(2) refers to the third
odd number (remember, the index
starts at 0). If you reserve five elements,
then you’ll use 0 to 4 for the index. If
you use a different number, you will
write over memory that some other
part of your program is using.
This is useful because you can work
with arrays inside loops. To print all the
odd numbers, for example, you might
write:
s time base, so if the
variable contains, for example, 100, the
pulse was 200
µ
This looks like a good piece of code,
but it does not work. The principle,
however, is sound. The first PULSIN
reads the start bit and rejects any bit
that isn’t the right length. Then the
code enters a loop, reading each bit in
turn and setting the corresponding bit
in B0 when the length of the pulse is
greater than 800
s wide. The command
times out in 131 ms. If no pulse occurs
during that time, the command sets the
variable to 0. The largest possible pulse to
measure is 65535
µ
s = 131 ms.
The PULSIN command only mea-
sures pulses if it finds the specified
edge. Suppose you want to determine
how long the user pushes a button.
The button provides a zero on the
input pin when pushed. If you start
executing PULSIN after the button is
providing a zero, you’ll never measure
the pulse. You must execute PULSIN
before the edge of the pulse occurs. If
you think about it, this makes sense
because it prevents PULSIN from
returning inaccurate results. The com-
mand always measures a full pulse.
You can use a byte variable if you
are measuring pulses that will never
exceed 510
×
2
µ
s (this is much
greater than a 0 at 600
µ
µ
s; since a 1 is
I var byte
for I = 0 to 4
Debug ?oddnums(I)
next
nominally 1200
µ
s, none should be as
s).
The only problem with this code is
that there is only a 600
µ
s gap between
bits. This is not much time for the
Stamp to recover from reading the last
pulse. The Basic Stamp takes at least
470
µ
Of course, you still have to observe the
Basic Stamp’s limit on memory. Arrays
don’t give you any extra memory, they
simply help you better use the mem-
ory you already have.
s to execute an IF statement (the
average time to execute a command is
about 330
s — some commands take
longer, some take less time). Even the
quickest commands require more than
100
µ
R EADING IR
Successfully reading the IR data stream
requires a series of 13 PULSIN state-
ments (or possibly 8 if you want to
ignore the extra bits). You only need to
store 8 of these counts. So your code
could read:
s. With the commands between
successive calls to PULSIN the BASIC
Stamp misses some bits.
One option, of course, might be to
switch to a Basic Stamp IISX, which is
much faster than an ordinary Basic
Stamp. However, with some clever pro-
gramming, you can make the ordinary
Stamp II read the IR pulses at this rate.
s. However, if a pulse does
exceed this width you will get an erro-
neous result with no warning. Also,
the command always uses a 16-bit
timer internally, so using a byte vari-
able does not alter the time-out period.
With the IR sensor, you’ll need to read
pulses over 2 ms wide, so all the pro-
grams in this article will use a word-
size variable.
Assuming the IR sensor is on pin 0,
it is very easy to measure the width of
an IR pulse:
µ
irsense con 0
irstartlow con 1100
‘ minimum start bit width
irstarthi con 1300
‘ maximum start bit width
raw var word(7)
dummy var word
start var word
T HE SOLUTION
To solve this problem, you must reduce
the instructions between the PULSIN
commands. In fact, to ensure proper
operation, you must eliminate the
Elektor Electronics
1/2000
37
600
short as 800
µ
µ
138910657.003.png
Listing 8. The Remote Rover Software
pause 20
next
goto top
‘ Remote Rover by Al Williams
irsense con 0
irinput var in0
irthreshold con 450
irstartlow con 1100
irstarthi con 1300
right:
for i=1 to delay
pulsout left_servo,center+speed
pulsout right_servo,center+speed
pause 20
next
goto top
value var byte ‘ result
raw var word(7)
start var word
dummy var word
right_servo con 3 ‘ right servo motor
left_servo con 15 ‘ left servo motor
delay var byte ‘ motor cycle time
center con 750
speed var word
i var byte
read_ir:
‘ The problem here is that the gap between bits
‘ is about 500µS and the Stamp may miss bits
unless
‘ you read everything in one swoop. So you
can’t
‘ read this in a loop or even test the start
bit
‘ until you are finished.
if irinput=0 then noir
‘ Already in the middle of a pulse so skip it
pulsin irsense,0,start
pulsin irsense,0,raw(0)
pulsin irsense,0,raw(1)
pulsin irsense,0,raw(2)
pulsin irsense,0,raw(3)
pulsin irsense,0,raw(4)
pulsin irsense,0,raw(5)
pulsin irsense,0,raw(6)
‘ Could comment these out
pulsin irsense,0,dummy
pulsin irsense,0,dummy
pulsin irsense,0,dummy
pulsin irsense,0,dummy
pulsin irsense,0,dummy
‘ test for good start bit
if (start<irstartlow) or (start>irstarthi)
then noir
value=0
for dummy=6 to 0
value=value*2
if raw(dummy)<irthreshold then ir0
value=value+1
delay=10
speed=100
top:
gosub read_ir
if value=1 then forward
if value=3 then left
if value=5 then right
if value=7 then back
goto top
forward:
for i=1 to delay*2
pulsout left_servo,center-speed
pulsout right_servo,center+speed
pause 20
next
goto top
back:
for i=1 to delay
pulsout left_servo,center+speed
pulsout right_servo,center-speed
pause 20
next
goto top
ir0:
next
return
noir:
value=-1
return
left:
for i=1 to delay
pulsout left_servo,center-speed
pulsout right_servo,center-speed
read_ir:
pulsin irsense,0,start
‘ read potential start bit
pulsin irsense,0,raw(0)
pulsin irsense,0,raw(1)
pulsin irsense,0,raw(2)
pulsin irsense,0,raw(3)
pulsin irsense,0,raw(4)
pulsin irsense,0,raw(5)
pulsin irsense,0,raw(6)
pulsin irsense,0,dummy
‘ device ID — ignore
pulsin irsense,0,dummy
‘ device ID — ignore
pulsin irsense,0,dummy
‘ device ID — ignore
pulsin irsense,0,dummy
‘ device ID — ignore
pulsin irsense,0,dummy
‘ device ID — ignore
The next task is to convert the raw
data into a binary number. Here, speed
is not as critical:
Now you need only process the raw
data. It is possible that the first bit the
code read was not the start bit, so a
simple test prevents you from reading
a packet in the middle:
value var byte
value=0
for dummy=6 to 0
value=value * 2
if raw(dummy)<irthreshold
then ir0
value = value +1
ir0:
next
return
if start<irstartlow or
start>irstarthi then noir
Unfortunately, you can’t perform this
test right after the start bit is read —
you must read the entire packet and
then decide if it was correct or not.
This simply examines each value (in
reverse order). If it the raw value is
38
Elektor Electronics
1/2000
138910657.004.png
greater than the threshold, the code
adds 1 to the result. In any case, the
code multiplies the value by 2 (a shift
left) each time through the loop. (The
Stamp has a shift left operator, so you
could replace the multiply statement
with:
Internet
http://www.parallaxinc.com – BASIC Stamp Manual Version 1.9, BASIC Stamp
DOS and Windows Editor, program examples. International distribution sources.
http://www.stampsinclass.com —BoE documentation, Robotics curriculum,
BoE-Bot *.dxf and *.dwg drawing formats, discussion group for educational
uses of BASIC Stamp.
chucks@turbonet.com — creator of the BoE-Bot and author of this series. Tech-
nical assistance.
kgracey@parallaxinc.com — co-author of this article. Technical assistance and
questions about the educational program.
http://www.milinst.demon.co.uk — UK distributor of Parallax BASIC Stamp.
value = value << 1
Now you can read the keys from the
remote easily. The keys do repeat so
you’ll want to take that into account in
your program.
R EMOTE R OVER
Armed with these IR sensor routines, it
is easy to add remote control to your
robot. You just need to know what val-
ues the keys on the remote return. This
is easy enough to deduce by calling the
ir_read routine and using debug to
print out the value variable.
For the Sony’s remote, The “1” key
returned 0, the “2” key returned 1, and
so on. The “0” key returned 10. I
decided to make the “2” key move for-
ward, the “8” key move backwards,
and the “4” and “6” keys move left and
right. With the layout of the numbers
on the controller, this is a natural
arrangement. It is a simple matter to
test for any particular key and send the
correct commands to the servos (just
like the other motion commands from
previous months). You can find the
complete Remote Rover code in List-
ing 8 .
I did run into one limitation, how-
ever. After playing with the Remote
Rover code for a while, I thought about
making the robot move forward when
you pressed the “2” key and then con-
tinue to go until you
pressed another com-
mand or the “5” key.
This turned out to be a
problem.
It is easy enough to
set a flag to indicate
forward motion. How-
ever, the problem is
that when you try to
read the IR signal from
the remote, you have
to wait for each
PULSIN command to
time out before control
returns to the main
loop. With 13 com-
mands each timing out
in 131 ms, this works
out to almost 2 seconds
of dead time between
motion commands.
That makes the robot’s
motion jerky. This
doesn’t occur as badly
with the original
scheme because the
repeating codes from
the remote end the
PULSIN commands without requiring
them to time out.
Of course, you can mitigate this
somewhat by not reading the device
ID codes. This reduces the number of
time-outs, but it increases the number
of times your robot will miss the start
bit and have to resynchronize with the
remote. In the end, I decided to leave
the code as it was.
Another way to improve efficiency
is to test the sensor before sensing the
start bit. If the sensor is reading a 0,
then there is a packet in progress and
there is no way you could possibly
read it so why bother? The code in
Listing 8 implements this test.
trivial to make particular keys perform
a predefined set of steps. With a bit
more effort you could use the remote
to program a sequence, store it in EEP-
ROM, and then recall it later (like a
macro, if you will). Once you under-
stand the remote control’s protocol,
you could send the robot a series of
commands for your television, dis-
patch it to another room and then have
it repeat the commands when it is in
sight of the television. You could even
use these techniques to allow two
robots to communicate with each other
over modest distances.
Although an infrared remote uses
very fast pulses, the BASIC Stamp can
handle it if you write your software
correctly. The PULSIN command
made measuring the pulses simple and
accurate. While not strictly necessary,
arrays made the task much easier. With
a little ingenuity, there is practically no
limit to what the BASIC Stamp can do.
(990050-5)
F UTURE DIRECTIONS
There are many simple modifications
you could make to the program in List-
ing 8. For instance, it would be easy to
program the volume and channel but-
tons to alter the speed and delay vari-
ables. Try it.
Once you can read remote codes,
you can add many advanced features
to your robot. For example, it would be
Article editing: J. Buiting
Design editing: L. Lemmens
Elektor Electronics
1/2000
39
138910657.005.png 138910657.006.png
Zgłoś jeśli naruszono regulamin