This is only a preview of the December 2020 issue of Practical Electronics. You can view 0 of the 72 pages in the full issue. Articles in this series:
|
Make it with Micromite
Phil Boyce – hands on with the mighty PIC-powered, BASIC microcontroller
Part 23: Analogue inputs and servos
T
hroughout this series we have
shown you how to interface different
types of hardware (components
and modules) to the Micromite. The
Micromite is then programmed to act
as ‘an intelligent controller’ to make the
attached hardware behave as we want.
The exact behaviour of the hardware
is ultimately determined by software,
or to be more specific, by the sequence
of MMBASIC commands that are used
within the program code.
Along the way we have demonstrated
how to use buttons, infrared receivers,
and GPS modules for inputs, and have
used LEDs, motors and piezo sounders
for outputs, as well as using various types
of display modules. These have all used
MMBASIC commands that are essentially
based on digital signals; for example,
standard on/off control of inputs and
outputs (such as buttons and LEDs), or
UART, SPI, or I2C protocols to interact
with devices (such as a GPS module,
LED matrix or IPS display).
This month, we want to go right back
to the basics and cover one area that has
been requested by several PE readers;
and that is to explore how to use the
Micromite to read (and respond to) an
analogue input. We will be demonstrating
this by using a potentiometer to feed a
variable voltage (between 0V and 3.3V) to
an analogue input pin; and then use the
relevant MMBASIC commands so that the
voltage level can be measured. To make
this a bit more interesting, we will use the
input voltage (ie, the rotational position of
the potentiometer) to control the position
of a servomotor ‘actuator arm’ – see Fig.1.
Just two low-cost items are required
to follow the topics this month: a linear
Questions? Please email Phil at:
contactus<at>micromite.org
50
Fig.1. This month, we show how to read an analogue input (a voltage supplied by the
potentiometer) and use it to control the actuator arm on a mini servomotor.
potentiometer and a small servomotor
(often just called a ‘servo’). You may
well have one, or both, of these items in
your ‘spare parts’ drawer, but if not, they
can be purchased online at minimal cost
from many different sources – more on
these items shortly.
Available pins
Before we can start to connect anything to
the Micromite we first need to understand
which Micromite pins are available for use
as an analogue input. Referring to Fig.2, you
will see a representation of the I/O headers
on our Micromite Keyring Computer. For
now, ignore the servomotor at the top and
the potentiometer at the bottom.
The position (and pin number) of
the available analogue input pins are
highlighted in grey. As you can see, there
are ten analogue input pins available:
pins 2-7, and pins 23-26.
Also highlighted in Fig.2 are the five
PWM pins. The reason these are labelled is
that each of these PWM pins can be used to
control a servomotor instead of outputting
a PWM signal. This is achieved in code
by using the SERVO command instead of
the PWM command – more on this later
when we come to control our servomotor.
The 0V, 3.3V, and 5V header positions
are also labelled. We’ll need these when
we connect the potentiometer and the
servomotor (as you can see in the top
and bottom of Fig.2).
Analogue voltage source
One of the first things learnt in electronics
is Ohm’s Law. We are not going to go into
great detail here other than to say that
we are using the concept of a potential
divider (ie, two resistors connected in
series) to effectively generate our variable
voltage which we will then feed into our
Practical Electronics | December | 2020
P W M
individual values of R1
and R2 will both vary,
but they will always add
Serv o
motor
up to a total of 10kΩ (or
whatever is the value of
the potentiometer).
Assume that our
potentiometer has a
26 25 24 23 22 21 19 18 17 16 15
spindle that is turned –
0 V
5 V
much like a traditional
M K C
volume control on an
0 V
3 .3 V
amplifier. At one end of
1 2 3 4 5 6 7 8 9 10 11 12 13 14
spindle travel (eg, fully
anti-clockwise), R1 will
10kΩ
be 10kΩ, and R2 will be
0Ω, in which case Point
B = 0V. At the other end
of spindle travel (fully
clockwise), then R1 = 0Ω,
Fig.2. The position (and pin numbers) of the ten available
and R2 = 10kΩ, in which
analogue input pins are highlighted above, along with the
case Point B = 3.3V.
five available PWM pins. Also shown are the connections to
I did say that we
the potentiometer and servomotor.
would go back to basics,
the reason being that I just wanted to
analogue input pin. Fig.3a shows a simple
demonstrate how a potentiometer can be
example of a potential divider based on
used as the source of our variable analogue
two 5kΩ resistors, connected in series,
voltage. Fig.2 shows how to connect the
between 0V and 3.3V.
potentiometer across the 3.3V supply, and
If we were to measure the voltage at
the wiper (ie, point B in the explanation
Point A (relative to 0V), then without
above) to analogue input Pin 5.
even using Ohm’s Law we can see that it
Go ahead and connect a potentiometer
would be 3.3V. Likewise, Point C would
as shown by using whatever method
be 0V. However, it is Point B that we are
works best for you. I prefer to plug the
interested in, as this will be a voltage
potentiometer directly into a breadboard,
somewhere between 0V and 3.3V.
and then use jumper wires to the MKC
Since the two resistors are of equal
(see Fig.1). However, you may prefer to
value, then we can quickly conclude
solder wires onto your potentiometer.
that the voltage at Point B would be half
The only important point to mention
of the 3.3V applied across both resistors;
is to ensure that you correctly identify
ie, 1.65V. This can indeed be verified by
the potentiometers wiper contact out of
calculation by using the familiar equation
the three choices. This wiper-contact is
V = IR. For completeness, we will calculate
the one connected to the Micromite’s
it as follows:
analogue input pin.
Current through both resistors: I=V/R =
Note that it is safe to use a potentiometer
3.3/(5,000 + 5,000) = 0.00033A (= 0.33mA)
with any value between 220Ω and
Voltage across R2 = I × R = 0.00033 ×
100kΩ; hence you will probably have
5,000 = 1.65V
something in your spares drawer that
The reason for showing this calculation
you can use straight away. If you have
is that if we were to vary the value of
various potentiometer values to choose
either R1 or R2, then the voltage at point
from then we suggest using one closest
B would change.
to 10kΩ as you can’t do much damage
So, let us now consider a potentiometer,
with 0.33mA.
which is effectively a variable potential
divider – refer to Fig.3b. Here, R1 + R2
= 10kΩ, and it is fixed by the actual
MMBASIC AIN parameter
value of the potentiometer. However,
Now that we have an analogue voltage
as the potentiometer’s mechanical
source connected to the MKC, let’s proceed
spindle (or slider) is adjusted, then the
with how to measure it from within
2 B
P W M
P W M
P W M
P W M 2 A
1
1 C
1 B
1 A
A
3 .3 V
3 .3 V
3 .3 V
5kΩ
V O U T= (3 .3 – 0 ) ×
B
2
R 2
R 1 + R 2
5kΩ
0 V
=
3 .3
2
= 1 .6 5 V
C
B
10kΩ
0 V
0 V
A
V O U T
C
Fig.3 a) A potential divider comprisies two resistors; b) a potentiometer is effectively a
variable potential divider.
Practical Electronics | December | 2020
MMBASIC. Next, start your Terminal
program so that you have a connection
to your MKC, and get yourself to the
command prompt (possibly press Ctrl-C
should you have an auto-running program).
The first command we will require
is SETPIN. We saw this early on in this
series when we used it to configure an
I/O pin to be either a digital input, or a
digital output. As a reminder, we used:
SETPIN 3,DIN for configuring pin 3 as
a digital input (ie, detect button press)
SETPIN 4,DOUT for configuring pin 4
as a digital output (ie, control an LED)
So to configure pin 5 as an analogue input,
we simply follow the above format and
use: SETPIN 5,AIN
Type this at the command prompt
(then press the Enter key). You won’t
actually see anything happen apart from
the cursor moving down to the next line
– if you see an error message then simply
correct anything mis-typed.
Now that we have configured Pin 5 as
an analogue input, we can proceed with
reading its value. This is really simple,
as all you need to do is type: PRINT
PIN(5)and press Enter. MMBASIC
will then return the voltage value and
display it on the terminal screen – try it
now. Next, adjust your potentiometer,
and repeat the PRINT PIN(5) command
– you should now see a different value.
There are two more things to check, and
that is the measured voltages at each
extremity of the potentiometer. So, turn
it fully clockwise and check the voltage;
and repeat for fully anti-clockwise. In
one position you should see 0V, and
in the other, 3.3V. Note that fully anticlockwise may read 3.3V rather than 0V
– this is not an error, it just depends on
which way round you have the 0V and
the 3.3V connected to the potentiometers
end contacts.
One important point to note is that
the MKC’s analogue input pins can only
read a voltage between 0V and 3.3V.
Should you wish to read a higher analogue
voltage then you will need to use external
hardware (such as an op amp) to scale it
down to between 0V and 3.3V.
Analogue voltage reader
We have just seen how to configure
an analogue input pin, and also how
to read the voltage level on the pin.
However, this was all done directly from
the command prompt. So let’s now write
a program that continually displays the
voltage on the Terminal screen so that
as we adjust the potentiometer we see
the voltage value change on the screen.
This is very easy to achieve, but we will
need to use some VT100 Escape codes
to help format the terminal display
nicely. Now type the following sevenline program into your MKC (remember
51
to save any work first, or alternatively, just insert these lines
before the start of your existing code).
SETPIN 5,AIN
PRINT CHR$(27)+“[2J”
DO
PRINT CHR$(27)+“[2;2H”;
Vin=PIN(5)
PRINT STR$(Vin,1,2);
LOOP
Before you run the program, let’s first take a quick look at how
it works (if you have been following this series then there
won’t be anything here you don’t recognise).
The first line, as we have just seen, configures pin 5 as an
analogue input. The second line uses an Escape code to clear
the terminal screen. Then we have a DO…LOOP comprising
three lines. The first of these lines positions the cursor 2 lines
down the screen, and 2 characters along the line (ensure you
type this exactly as shown above – case sensitive and with
the semi-colon at the end of the line). This Escape code is
used so that the cursor position is moved away from the topleft corner of the screen and hence makes it easier to read the
voltage that we are about to display. The second line in the
DO…LOOP loads a variable (that we have called Vin) with the
measured analogue voltage on pin 5. We are storing the voltage
value in a variable as we will not only be displaying the value
on the screen, we will also be using it for a calculation when
we add the servo (discussed shortly). The last line in the DO…
LOOP displays the value on the screen and uses the STR$()
command to format it to 1 leading digit along with 2 decimal
places. The STR$() command is used because we need to
convert a number (ie, Vin) into a string (something that can
be displayed), so that we can then format it to the required
number of characters (here x.xx). Doing this ensures that the
displayed voltage appears to remain in a static position rather
than jumping about.
Now RUN the program and check it works. As you adjust the
potentiometer, you should see the displayed value vary. If not,
check your wiring, and also that your code has been entered
correctly. Do check that at one end of the potentiometer’s travel
the value is 0.00, and at the other end it is 3.30; however, do
note that if you do not get exactly to 0.00 or 3.30 this will not
be a fault of anything you have done; it will simply be down
to the quality of the potentiometer.
A simple servo
Now that we have a method of adjusting an analogue voltage
(between 0V and 3.3V), and also have the ability to read the
voltage within our code, we can use it to control a mini servo.
So what is a servo? Essentially, it is a motor with built-in
positional control. It has a spindle that is typically limited to
a rotational movement of 180° (half a turn). Onto the spindle
you can attach an actuator arm, which in turn can be attached
to something mechanical. For example, in a toy car, a servo’s
actuator arm may be attached to the front-wheel mechanism
allowing the servo to steer the car.
A servo has three wires, two for power (5V in this case), and
one for a control line. The control line requires a signal that is
a square wave (within a certain frequency range). The square
wave’s duty cycle (the ratio of on-time to off-time) determines the
position of the servo’s spindle. MMBASIC makes it very easy to
control a servo thanks to the SERVO command – this eliminates
the need to worry about the signal timing, as we will see shortly.
If you don’t have a servo in you spares drawer, then many are
available online at a very low cost and we would recommend
obtaining a few as they can be a lot fun to use. Please see Fig.4
for the type of mini servo we are using here.
52
Servomotor cable
colour code
Red
+5V
Brown GND
Orange PWM
Fig.4: A low-cost mini servomotor is readily available online. It’s a
perfect match for MMBASIC’s SERVO command.
MMBASIC SERVO command
You may recollect that we used the PWM pins earlier in the
series (along with the PWM command) to drive a piezo buzzer.
Essentially, the PWM command was used to adjust the frequency
of a square wave that in turn was driving the piezo sounder;
the end result enabled us to play different musical notes. For
the purpose of music generation, the PWM command used a
duty cycle of 50% – ie, a precise square wave. However, as
mentioned above, a servo uses a specific frequency, and it is
simply the duty-cycle that is adjusted in order to move the
servo’s spindle to a specified position. The duty-cycle value is
represented as a time (in ms) with a typical value range from
0.8ms to 2.2ms for most servos.
MMBASIC’s SERVO command has the following syntax:
SERVO channel, freq, duty-timeA[, duty-timeB,
duty-timeC]
Here, channel is set to 1 or 2 (depending on which Micromite pin
is used – see pinout in Fig.1); freq is set to an appropriate value
for the servo used (we will be using a frequency of 100Hz); and
duty-time is the time (in milliseconds (ms)) as described above.
So, if you have a servo available, now is the time to connect
it to your MKC. Simply connect the three leads as shown in
Fig.2 – in other words, connect the servo’s red lead to +5V,
the servo’s brown lead to 0V, and the orange lead to Pin 26.
Do a quick check you have it connected correctly, and then
start your Terminal app so that you have a connection to your
MKC and can see the command prompt.
Next, type: SERVO 2,100,1.2 and check that the servo
moves. Note that it is better to add an actuator arm onto the
servo’s spindle so that you can clearly see it moving. If you
don’t have an actuator arm, just use a small piece of tape and
attach it to the spindle to simulate a ‘pointer’. If it does not
move, then recheck your three connections, and also check
that you have typed the command exactly as shown.
Now repeat the above but with a duty-time of 0.8 (instead
of 1.2), and then try 2.2. You should then see the servo move
near to its extreme positions covering an angle of close to 180°.
Potentiometer control of the servo
Now that we have connected up the servo, and seen how
MMBASIC can be used to directly control the position of the
servo, we will modify our program code from earlier so that
turning the potentiometer adjusts the position of the servo’s
spindle. As always, this is much easier than it sounds; so go
ahead and make the following changes by adding the four
lines of code highlighted in bold:
Practical Electronics | December | 2020
MinVal=0.8
MaxVal=2.2
SETPIN 5,AIN
PRINT CHR$(27)+“[2J”
DO
PRINT CHR$(27)+“[2;2H”;
Vin=PIN(5)
PRINT STR$(Vin,1,2);
SerPos=((MaxVal-MinVal)*(Vin/3.3))+MinVal
SERVO 2,100,SerPos
LOOP
Before running the program, we’ll quickly explain what the
four lines of code do that have just been added. The first two
lines simply set two variables that we will use in a calculation
within the DO…LOOP. If you look at the names and values,
you should recognise that they represent the minimum and
maximum values for the servo’s duty time (in ms, as discussed
earlier). Note that in the real world, different quality servos
have different performances and specifications. It may be
that your specific servo can work beyond these values, hence
setting them in the first two lines of code makes it very easy
to try different values that may well work with your servo.
For now, though, leave them set to the values of 0.8 and 2.2.
The third line added may look complex, but it is just a
calculation that maps (‘translates’) a voltage value between 0
and 3.3 (from the potentiometer) to a value between 0.8 and
2.2 (ie, between MinVal and MaxVal) to be used by the SERVO
command. The fourth line then uses the mapped/calculated
value (which we have stored in the variable SerPos) and
passes that to the servo.
Now RUN the program and make sure that the servo moves
proportionally to the turning of the potentiometer. As usual, if
anything does not work as expected, check your connections,
and also check your code.
Challenges
There are many modifications that you could make to this
month’s code, and we would certainly encourage you to
experiment. Here are two ideas to try:
Change the MinVal and MaxVal values to find the optimum
values that give you as near as 180° of spindle movement. Be
careful doing this as the servo mechanism can be damaged
if a relatively big (or little) value is used in error. I advise
applying 0.1ms step changes at a time.
Get the spindle to move in the opposite direction. This
could be achieved by simply swapping the two 0V and
3.3V wires on the potentiometer (try it and see!). However,
imagine the scenario where you were part of the hardware
design team and you created a PCB and you don’t want
to have to modify the PCB. Instead, you want to swap the
direction by modifying the software – this is your challenge!
I hope this month’s topic of analogue inputs and servos has
inspired you to explore things further. If you have built the
Micromite Robot Buggy, then how about trying to make a
remote control based on two potentiometers: one for speed,
and the other for turning (much like a radio-controlled car).
Alternatively, use two potentiometers along with two servos
and make a pan/tilt mechanism onto which you could attach
a distance module so that you can measure the distance to
any object that you are pointing it at.
Next month
One further topic that we have been asked to cover is pulse
counting, so next month that is exactly what we will be
exploring. Until then, have fun coding!
ESR Electronic Components Ltd
All of our stock is RoHS compliant and CE
approved. Visit our well stocked shop for
all of your requirements or order on-line.
We can help and advise with your enquiry,
from design to construction.
3D Printing • Cable • CCTV • Connectors • Components •
Enclosures • Fans • Fuses • Hardware • Lamps • LED’s •
Leads • Loudspeakers • Panel Meters • PCB Production •
Power Supplies • Relays • Resistors • Semiconductors •
Soldering Irons • Switches • Test Equipment • Transformers
and so much more…
JTAG Connector Plugs Directly into PCB!!
No Header!
No Brainer!
Monday to Friday 08:30 - 17.00, Saturday 08:30 - 15:30
Our patented range of Plug-of-Nails™ spring-pin cables plug directly
into a tiny footprint of pads and locating holes in your PCB, eliminating
the need for a mating header. Save Cost & Space on Every PCB!!
Station Road
Cullercoats
North Shields
Tyne & Wear
NE30 4PQ
Tel: 0191 2514363 sales<at>esr.co.uk www.esr.co.uk
Practical Electronics | December | 2020
Solutions for: PIC . dsPIC . ARM . MSP430 . Atmel . Generic JTAG . Altera
Xilinx . BDM . C2000 . SPY-BI-WIRE . SPI / IIC . Altium Mini-HDMI . & More
www.PlugOfNails.com
Tag-Connector footprints as small as 0.02 sq. inch (0.13 sq cm)
53
|