Download Rotary Encoders Mechanical

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Valve RF amplifier wikipedia , lookup

Power MOSFET wikipedia , lookup

Surge protector wikipedia , lookup

Microcontroller wikipedia , lookup

Resistive opto-isolator wikipedia , lookup

Power electronics wikipedia , lookup

Crossbar switch wikipedia , lookup

Schmitt trigger wikipedia , lookup

Switched-mode power supply wikipedia , lookup

Trionic T5.5 wikipedia , lookup

Rectiverter wikipedia , lookup

Opto-isolator wikipedia , lookup

Immunity-aware programming wikipedia , lookup

Charlieplexing wikipedia , lookup

Transcript
Rotary Encoders Mechanical
Objective
DC motors are useful devices. They have significantly more torque than stepper motors. Even
when geared down, they are much faster. The only real draw back with DC motors is you never
really know just where they are. If you need to turn exactly 2.5 revolutions, then stop, back up a
bit then turn forward again, this is very difficult to get right with just timing.
The solution is the encoder, a small device that mounts on the shaft of a DC motor and gives an
output that corresponds to the number of degrees that the motor has traveled. There are
numerous types of these devices, the most accurate are optical and can give angle measurements
with 0.1 degree accuracy. These are also the more expensive devices. This document looks at
the mechanical encoders with lower accuracy that sell for less than $1.
The Mechanical Encoder
These simple devices usually have two switches that open and close as the shaft turns. The shaft
of the encoder is mechanically connected to the shaft of the motor. Care must be
taken when mounting the encoder. The shafts must be collinear and concentric. If
not, there will be friction, and usually damage.
In the Bourns PEC12R devices there are 3 pins. The center pin is common to both
switches and is usually connected to ground. The Bourns PEC12R is a low
resolution device. It comes in 2 flavors, 12 steps per revolution and 24 steps per
revolution. This means that each switch opens and closes 12 or 24 times in each full
turn of the shaft. The switches are mounted to the shaft in such a way that first one switch (the A
switch) closes then the other (the B switch closes). By noting which of the switches closes first,
one can tell if the shaft is rotating clockwise or counter clockwise.
The Encoder Signal
The encoder is a couple switches. They are either open (∞ resistance) or closed (0 resistance).
This is similar to working with push buttons. Remember the
Arduino cannot measure changes in resistance. The change in
resistance must be converted into a change in voltage.
A series resistor makes this possible. Consider the voltage at
Point A in the circuit at the right. When the switch is open, no
current can flow in the loop. The current through R1 is 0. Since
V = IR for any resistor then the voltage change across R1 is 0
since 0*20K = 0. That means the voltage change across R1 is 0
so if the voltage on the Left of R1 is 5, and there is no change,
then the voltage on the Right side of R1, namely the voltage at Point A must also be 5V, digital
HIGH.
When the switch closes, the resistance between point A and ground is 0 so the voltage at point A
must be the same as ground i.e. 0 Volts, or LOW.
If Point A is connect to an Arduino Pin set to be an input pin, we can read this pin with a
digitalRead(Pin #); command and we will get either HIGH or LOW and the program can tell of
the switch is closed or open.
Just as with the Push Button, we can use the internal
resistors provided by the Arduino Processor to
create this circuit. In this picture, we see the encoder
connected to the Arduino. Pins 2 and 3 are input
pins with their internal pullup resistors active. As
the shaft turns, these voltage will go HIGH and
LOW. Counting these tranistions will allow the
program to know how far the shaft has turned.
Noting which pin transitioned first will allow the
program to know whether it is rotation clockwise
(CW) or counter clockwise (CCW).
Consider the diagram at the Left. This shows how the voltage on
the two pins will change as the shaft is rotated. The horizontal
axis is time. If Signal A goes HIGH (switch opens) first, then
Signal B, the shaft is rotating clockwise (CW). If Signal B goes
HIGH then A the shaft is rotating counter clockwise (CCW).
It is not difficult to connect the Arduino to Encoder. Reading the
signal and determining how far it has turned, or what the speed is
can be a bit more difficult. The next section explores the code that
will make it happen.
What is an Interrupt
As with most things involving Arduino programs, there are multiple ways to do this. This write
up is going to explain using the interrupt to detect the transitions. Interrupts and the Interrupt
Service Routines (ISR) area powerful tool that are required in a number of programming
operations.
Microprocessors execute programs one line at a time and it follows a sequence through the
program. The second program line follows the first and so on. Flow control statements like if,
for, while or switch can cause the sequenced to skip or repeat certain sections of the program.
Function calls will cause the program to jump to a routine and return when that routine is
completed.
Sometimes a program requirement demands that this well order set of operations needs to be
interrupted. These interruptions are triggered by events outside the normal operation of the
program. When the events that require the normal sequence be interrupted, a programmer might
use and ISR.
An ISR is a special subroutine that is executed when some external event demands that normal
the program sequence be interrupted and a special set of instructions be executed. The
programmer cannot predict when these events will happen, or what program instruction will be
in progress.
This is exactly the situation we have with the encoder. The program needs to know when the A
and B pulses occur but it cannot predict when that will happen. It can't just do nothing waiting
for a transition, but it has to react when it does. This is an ideal time for an ISR, or more
accurately 2 of them.
When an event, like the voltage on a pin transitioning from low to high, happens, the program
needs to stop what it's doing and react.
Creating an ISR
The Arduino IDE makes it easy. The Uno processor has two pins that can be connected to
external stimuli that will trigger an Interrupt Service Routine - pins 2 and 3. Creating an ISR
requires two things 1. it must be defined using the attachInterrupt() function.
2. There must be a subroutine that executed when the event happens
The Arduino Uno has 2 pins that are able to detect interrupt causing events, pins 2 and 3. There
are 2 interrupts that can be associated with these 2 pins, int0, and int1 respectively. The program
tells the processor that Interrupts are going to be active with the attachInterrupt() function. This
function requires 3 parameters inside the parenthesis.
Interrupt number - 0 if the event is going to happen to pin 2 or 1 if it happens on pin 1.
ISR name - the name of the routine that will be executing when the event happens.
Triggering event - What causes the interrupt to happen - this can be
RISING - the pin transitions from LOW to HIGH.
FALLING - the pin transitions from HIGH to LOW
CHANGE - the pin changes state either RISING or FALLING
LOW - The ISR executes whenever the pin is LOW
Let's look at a simple example:
In this program the Arduino
onboard led blinks as the wheel
turns the encoder and the A output
generates interrupt events.
In the setup() routine, the program
defines pin 13 as an output, pin 2 as
an input and activates the internal
pull-up resistor. Line 6 in the
program activates interrupt Int0 (the
one for pin 2) and associates it with
the void ISR_Blink() routine. ISR_Blink() is a very simple routine. It toggles (whatever is now,
make it different) pin 13, the on-board led.
In this picture, the encoder
(lower right corner) is attached to
the motor shaft. The 3 pins are
connected to the Arduino pin 2,
3, and ground.
Rotating the wheel rotates the
encoder shaft and the LED turn
on and off.
The processor has 2 hardware
interrupt pins, 2, and 3 and to
fully utilize the encoder's
information, both would be
helpful.
The first program shows how to
get the motor direction. To do this, our configuration needs to read output
A and output B. If B is low when a rising edge happens on A, the encoder
is turning clockwise (CW). If B is high when a rising edge hits on A, the
shaft is turning CCW. This first modification to the program includes a
direction variable boolean CW = true. Note if CW is false, then the shaft
is turning CCW.
This program initializes pin 3 as well
as 2, The program reads pin 3 to
determine the direction of rotation.
In the ISR_Blink routine if pin 3 is low,
then the program sets the Boolean
variable CW to false indicating that the
shaft is turning counter Clockwise. If
pin 3 is high, then CW is set to true.
Another thing to note in this program is
the definition of the Boolean variable
CW - Note the word volatile in front of
the type casting. volatile means the variable could change unexpectedly. This is important in the
loop program. Normally a variable value only changes when the program changes it an then in
expected ways. Because an interrupt can happen any time, and the variable CW is set inside the
ISR, the value of CW might change without the loop function changing it.
Another valuable bit of information is the number of steps that have transpired. This will tell us
how far the wheel has turned, that is how many steps have happened. This information can be
used to get the distance traveled, and when used in conjunction with a millis() function call, can
give us the speed of rotation.
The Only Negative is that It Doesn't Work
This is very interesting, but it would be remiss not to mention "Bounce". All mechanical
switches, when they open or close will bounce. The contact doesn't just "make contact". When a
contact is made it will make and break several
times before settling to a secure connection. We
are configured so interrupts occur when the switch
opens.
This scope picture shows the bounce on a falling
edge. This is when the switch closes. Note high
voltage on the left indicates the switch is open.
When it closes in the center of the screen, we see it
bounce several time before setting to the closed
state.
We can see bouncing is less on the opening
contact, but still some noise happens that can cause the counter to increment more times than
appropriate. There are several ways to reduce or eliminate bounce. The simplest is to ignore all
interrupts that happen in quick succession.
Consider ISR_Blink() in this program. This routine will be called whenever there is a rising edge
(transition from LOW to HIGH) on pin 2. If it has not been more than 6mS since the last such
transition, it will be ignored.
Remember, millis() gives the
number of milliseconds since the
program started. On the last
transition, the variable tm was set
equal to millis(). At that time
millis() - tm was 0, not greater
than 5. Only when it has been at
least 6 mS since the last
transition will cnt increment.
From Experiment, it can be shown that this
particular encoder produces 32 pulses per
revolution. In our code, the loop function
counts the rising edges for a full 500mS then
displays them.
The motor speed is controlled by the pulse
width modulator pin 5 and 6. The operator
can enter a number to set the pulse width and
control the energy to the motor. 128 is the
minimum to overcome the inertia to start the
motor. At 255, the Serial monitor reads 30
pulses in 500 mS - or 60 pulses per second.
That means 60 pulses/second * 60 Seconds/minute / 32pulses / revolution = 112 rpm. At a 50%
duty cycle (128 to pin 5) and we a reading of 13, or 26 pulses per second. Calculate the rpm for
this speed
____________________________________
If the motor is running and the operator further reduces the pulse width to 90, the reading is 7, or
14 pulses per minute. Calculate the rpm at this rate.
____________________________________ Note, if the motor is stopped, at this duty cycle
there is not enough power overcome the static friction and start is moving, but if it is running, it
can be slowed to this value.
Conclusions
A simple encoder attached to the motor can be used to determine the motor speed, or the total
angle of rotation using interrupts. External interrupts can trigger the execution of an ISR, in
direct response to the event.
ISR are easy to implement with the Arduino and can provide useful information.
If you have any questions, please feel free to contact me
Adrian Krag
[email protected]
707 321 6985