Path:
AVR_EN =>
Applications => IR-controlled steppers
(Diese Seite in Deutsch:
)
 |
Applications of
AVR Single chip controllers AT90S, ATtiny, ATmega and ATxmega
Infrared controlled stepper motors with two ATtiny24
|
 |
Two infrared-controlled stepper motors on one ATtiny24
If you need to
- control one or two model cars to drive forward or backward, to the left or to the right,
- do this with two stepper motors, and
- drive within a radius of up to 360 meters (if your IR equipment functions at that distance),
and
- control your model with a homebrew IR transmitter, and
- know at any time where your model currently is (how many steps forward/backward and right/left
it has made), and
- to stop your model immediately by a fast stop command,
this here is the correct solution for all your needs.
- Hardware needed
- Stepper motor hardware
- Controller hardware
- How it works
- The IR protocol and transmit algorithm
- The receiver algorithm
- The steppers
- The controller's keys
- The controller's LCD
- The software needed
- Software to download
- IR communication
- The IR protocol
- IR transmit
- IR receive
- The stepper motor software
- The stepper timing
- The stepper algorithm
- The controller software
- Display of positions
- Key software
The hardware consists of two separate components: one that runs the model and controls
the stepper motors in the model, and one where you can manually control direction and position
by keys, with which you can transmit these commands to your model and read the target and
the actual position of those on a LCD.
This is the hardware for driving the two stepper motors. It consists of
- an ULN2801, 2802 or 2803 Darlington driver for driving the the stepper motor
coils,
alternative: use an ULN2003A with seven darlingtons and add a transistor
to drive the eight's motor bit.
The motors can be driven with any positive voltage VM, e.g. +5, +9,
+12, +15, +18, +24 and up to +50 V (ULN2803), maximum magnet coil current
is 500 mA,
- a TSOP31240 module to receive and filter IR signals from the IR transmitter LED
on the controller board with 40 kHz (transmit and receive frequency
configurable), alternative modules such as TSOP4840 possible,
- a transistor-driven constant-current driver for the IR-LED SFH4546, to transmit
the motor's actual positions to the controller board, please note that the SFH4546
has, unlike to all other LEDs, its cathode as the longer wire, alternative IR-LED
transmitting diodes such as the LD271 can also be used, and
- an ATtiny24A that does the processing and control over all that, can be an
ATtiny24, 44 or 84 too, (the latter two if you want to waste flash and EEPROM
memory), plus
- a six-pin plug ISP6 with which the ATtiny24 can be programmed within the system
(unplug the motor 2 to avoid uncontrolled motor movements during programming).
The operating voltage of the ATtiny24 (VCC) can be between 3.3 and
5 Volts (battery operation is possible). Currents are depending from the
following. The IR transmit LED consumes roughly 20 mA at average during
the rather short transmission time and at maximum 100 mA during the short
active LED-on times at 40 kHz.
This is the hardware needed for the controller board:
- R1 to R5 encode the state of the forward/backward and left/right keys to an
analog voltage and transfer this to the AD channel ADC0 input of the ATtiny24,
all have 1 or 2% tolerance and are by default R1=10k, R2=5k1, R3=2k2, R4=1k and
R5=3k3, select other combinations with the software provided
here and don't
forget to change the recognition table in the controller software,
- the "M" switch selects the motor to be controlled (up to eight
models with two stepper motors each can be controlled with one controller
(if you encode these with a resistor matrix, not shown and included here,
if more than two motors are to be controlled use a mouse piano type encoder
and add the software needed for those),
- the TSOP31240 module receives IR signals from the model(s) and initates
PCINTA2 (=PCINT0 interrupts) for the ATtiny24 to analyze the time over which
the signal input is high or low,
- output pin PA3 transmits IR signals with 40 kHz via the constant-current
transistor BD439 and an IR-LED, by that applying a self-defined protocol,
- four port bits provide the bidirectional data bus for the LCD, its control
lines are served by PB0 to PB2, the backlight of the LCD is provided by the
220Ω resistor to plus and its contrast is adjusted with the 10k trim
resistor,
- the ISP6 plug allows programming the ATtiny24 within the system.
The operating voltage depends from the LCD, either 3.3 or 5.0 V or anything in
between can be used, therefore battery operation is possible.
This chapter describes how the different components work.
IR transmitting uses portpin PA3. It is an output, that is switched by the interrupt
service routine of TC1 on compare match A. This switching implies the use of the
"toggle" mechanism, by writing a one to bit 3 of the PINA port register.
A high on the PA3 pin switches the base of the driver transistor to +1.2 to
+1.3 V, as set by the 1N4148 diodes. That leads to an initiated current of
approx. 100 mA through the collector-emitter connection, until the emitter
voltage reaches (+1.3 - 0.6) Volt, which is the case when 0.7 [V] / 6.8 [Ω]
= 103 mA. Base current at this CE current is roughly 0.3 mA, so that
the current through the diodes (either (3.3 - 1.3) [V] / 330 [Ω]
= 6.1 mA at 3.3 Volt or (5 - 1.3) [V] / 330 [Ω] = 11.2 mA
at 5 Volt operating voltage is not influenced significantly, it remains nearly
constant.
The IR LED diode has a forward voltage of VForw = 1.6 V, so the
heat power of the transistor is either (3.3 - 1.6 - 0.7) * 103 = 103 mW at
3.3 V operating voltage or (5.0 - 1.6 - 0.7) * 103 = 278 mW at 5 Volt.
At these maximum heat powers the transistor does not need any additional cooling.
From the thermal power view, a smaller transistor would also be possible, but the
maximum current of a TO18 transistor of 100 mA could be exceeded.
At 40 kHz transmitting frequency one on/off cycle of the LED is lasting
25 µs. The minimum number of bursts (on/off cycles) to be detected
by the TSOP31240 is 10, so the minimum duration of a complete burst signal is
250 µs. The same applies for the pause following the burst. So,
0.25 ms for an on as well as for the minimum-length of an off cycle is
sufficient for a reliable operation of the receiver. The protocol of the IR
transmission/receive is based on that and described in the software section.
The assembler software allows other timing parameters, such as other LED
frequencies, longer on and off times, etc., too. So design your own, if you
aren't happy with the default settings.
IR reception is performed by the TSOP31240 module. If enough IR signals of its
filter frequency of 40 kHz have been received, its output pin changes to low.
Missing IR signals lead to the output pin going to high. Both level changes initiate
PCINT0 interrupts, if so enabled by the mask and the PCINT0 interrupt enable.
The duration of those signals (active and pauses) is measured using the TC1, clocked
by the ATtiny24 clock frequency (at 8 or 4 MHz). Each of the signal changes
restarts TC1.
The further algorithm is described in the software section below.
The two steppers are connected to the lower and the higher nibble of port A. If
you use an ULN2801/2/3, you're fine. If it is a ULN2003A, this has only seven
darlington drivers, the eight's driver is via an additional transistor.
Driving the motors forward and backwards, or left and right, is either done in full
step mode or in half step mode. When in full-step mode, coils 1, 2, 3 and 4 are
activated stepwise in a row to drive the motor forward. The magnet follows the
changes in the magnetic fields produced by the four coils.
In half-step mode, first coil 1 is activated. In the next step coil 2 is additionally
activated and the magnet moves to a position between coil 1 and coil 2. After that
coil 2 is activated alone, so the magnet moves towards coil 2. Further five steps
follow with either two or one coil activated.
That yields, when moving clockwise (forward) the following nibbles are used to drive
the active stepper in the following manner:
Mode | Steps | Driver nibble movement forward |
Full-step | 4 | 0b0001=0x1 => 0b0010=0x2 => 0b0100=0x4 => 0b1000=0x8= > (repeat) |
Half-step | 8 | 0b0001=0x1 => 0b0011=0x3 => 0b0010=0x2 => 0b0110=0x6 => 0b0100=0x4 => 0b1100=0xC => 0b1000=0x8 => 0b1001=0x9 => (repeat) |
Backward or left direction simply reverses the direction of those steps.
Note that in full-step mode only one of the four magnets of the stepper is sourcing
current, while in half-step mode every second step switches two magnets on. So the
power with which the steppers are driven is by 33% higher in half-step mode. That
also means that the motor speed in half-step mode can be slightly higher than in the
full-step mode. The desired speed of movement, at starting the motor and accelerated
over the next following steps, is configurable in the source code.
The two stepper motors are implemented with the following algorithm.
On start-up and when target positions change, the motor is driven with a lower
frequency in cStepSlow (in Hz) to allow for a smooth motor start. This can for
example be 100 Hz (10 ms/step) and is configurable by the source code.
In each round (e.g. in 96 full steps (as shown here) or in 192 half steps, as defined
in the constant cStepsSlowFast) the frequency is first slowly, later faster
increased by reducing the delay between the steps. This repeats until the motor is
driven with the maximum frequency as set in cStepFast. The acceleration is then
stopped and the motor frequency remains at that value.
The same happens in reverse, if the motor nears its target position: the speed is
step by step reduced with its speed reduction constant cStepsFastSlow until he
reaches its lowest speed.
For the detailed implementation see the software section below.
Design and operation of the four keys has been described
here.
When using the right resistors, each key combination of the four keys produces a
unique voltage on the output. So if the keys Forward and Left are
both pressed, the target position of motor 1 increases and the target position of
motor 2 decreases. The longer a certain key is pressed, the larger is the increase
or decrease caused by the key. The following table shows the increases with time.
Key pressed for ... seconds | Position increase/decrease |
Half-step | Full-step |
<0.85 | 1 | 2 |
0.852 | 2 | 4 |
1.70 | 4 | 8 |
2.56 | 8 | 16 |
3.41 | 16 | 32 |
4.26 | 32 | 64 |
5.11 | 64 | 128 |
5.96 | 128 | 256 |
6.82 | 256 | 512 |
7.67 | 512 | 1,024 |
8.52++ | 1,024 | 2,048 |
Each change of the target position is immediately transmitted from the controller
to the model, so that reaction times are very short.
The LCD is driven like shown here. The include file
lcd.inc provides all necessary routines, such as
LcdInit that configures the LCD, LcdSram that writes SRAM content
to the LCD, etc. etc.. If you want to know how that works, follow the above link.
A special feature of the LCD are the special characters that are applied to display
the current stage of transmit/receive on the IR:
Transmit | Receive |
# | Char | Description | # | Char | Description |
0 |  | Transmit has started |
4 |  | Reception has started |
1 |  | Transmit has failed |
5 |  | Reception has failed |
2 |  | Transmit completed |
6 |  | Reception completed |
3 |  | Transmitter empty |
7 |  | Receiver empty |
Those special characters are updated whenever the display of the line is necessary
(because a value has changed) or when the respective event (error during transmission
or reception) occurs.
The software for the controller and the motors is written in AVR assembler source
code. It is under contruction.
Both work with the standard fuses. The clock frequencies are increased by software
(writing to the CLKPR portregister), so no clock fuses have to be changed in advance.
Both, the controller and the motors use a bi-directional IR transmit/receive
connection. The following describes how this works in detail.
This is how the IR communication protocol works. It starts with phase I, where
any incoming IR receiver bits are detected, and transmit is skipped if any
activities on the receiver happen during that time. The register rBits
starts at 32. This is resulting from
- the inactive signal in phase I, plus
- one long start signal in phase II, plus
- one shorter start signal in phase III, plus
- four bits with motor number, plus
- 24 bits that encode the position, plus
- the final phase that ends transmission and finally restarts the receiver.
rCnt is decresed every time that an inactive phase ends and the next
active phase starts.
If no signals are detected in phase I, the receiver is disabled by clearing its
interrupt-enable bit and the LED-active part of phase II starts. In this phase
the compare match A in TC1 is set to 12.5 µs for generating a 40 kHz
signal (@8 MHz = 99, @4 MHz = 49). The register rCnt counts the number of
ON/OFF phases of the LED. For the 2 ms long active LED signal
2,000 / 12.5 = 160 of such phases are necessary, providing 80
cycles of 25 µs each with the LED switched on and off.
After having switched the LED on and off, a duration of 2 ms pause is performed.
This is done by setting the compare match value to 16,000 (at 8 MHz clock)
and setting rCnt to one. In this phase no active switching takes place.
After the 2 ms phase II is over, the 1 ms long active signal phase
III starts. The following pause of 1 ms duration is again achieved by
a pro-longed OCR1A value.
The following 28 single bits to be transmitted all start with a 250 µs
long active phase. If a zero is to be transmitted, a pause of 250 &mico;s
follows. If a one is transmitted the pause is longer, 500 µs.
Finally a last active phase of 250 µs and a prolonged pause of
750 µ follows. After that the receiver is switched on again by
enabling its interrupt flag.
The complete cycle lasts for between 22 and 29 ms, depending from the number
of longer-lasting one-bits to be send.
Transmit and receive both use TC1 in normal CTC mode with compare match A and
the corresponding interrupt. The flow is shown in the diagram to the right.
The red clock cycle counts in the flow diagram are relevant to ensure that
during active LED phases, where compare A matches occur every 12.5 µs
@40 kHz LED frequency (10.4 µs @48 kHz) resp. every 100
(clock=8 MHz) or 50 clock cycles (clock=4 MHz) and the maximum number
of consumed clock cycles in the compare match interrupt routine must not exceed
these available clock cycles. Otherwise compare matches would be missed and the
whole timing would get corrupted.
In receive mode the number of to-be-tranmitted bits in rBits is zero
and OCR1A is set to 0xFFFF. If the compare match occurs, the counter is
restarted at a high count to signal an illegal overflow of the TC1 to the
receiver software part (normal receptions of IR signals do not last that long).
Prior to starting a transmission (by setting rBits to a non-zero value)
the bits to be transmitted have to be prepared. Those are left-adjusted in the
four transmit registers rTxN, where N ranges from 0 to 3 and 3 is the
most significant. The toggle register rTgl has to be cleared, because
transmit starts with an inactive LED. The compare match A of TC1 is set to the
length of this inactive period and the cycle counter rCnt is set to
one. Lastly rBits is set to the number of bits (header plus data bits
plus one last bit) and transmission starts.
If rBits is not zero, the transmitting part of the TC1's compare match
interrupt starts. At first, the register rTgl is written to LED input
portregister. If the respective bit in rTgl is one, writing this bit
toggles the port pin switching the LED on and off. As this register is zero
at the beginning of the transmit cycles no toggling occurs in this stage.
Then the number of pulse counts in rCnt is decreased. If it is not zero
(as it will be at start-up the transmission), the interrupt returns by restoring
SREG to its initial value and a RETI. As this code sequence is needed very
often, it is written as the macro RetInt to reduce source code lines
and to increase code readability.
If rCnt reaches zero, the toggle bit in rTgl is reversed by ex-oring
it with the active LED bit set. This operation either results in a zero- or a
non-zero state. If the toggle bit now is one, an active phase starts. If it is
zero, a pause starts and the flow diverts to the right side.
In case a new active phase starts (rTgl not zero), first the number of bits
is decreased. If that reaches zero, the transmit process is over, the receiver
interrupt is enabled and the compare match value is set to the top of TC1. As
rBits now is zero until software starts a new transmit sequence, normal
receive takes place. This is particularly relevant when switching from transmit to
receive: to ensure that the receiver sensor does not get activated, a long pause
at the end of the end of the transmit allows the receiver to get rid of pulses
and to return to the normal receive situation.
If rBits does not get zero zero after decreasing it, the pulse duration
in TC1 is set to 12.5 µs at 40 kHz. As this source code is also
used very often, it is written into a macro SetOc, which expets as first
parameter @0 the value that OCR1A should be set to.
The remaining code sets the number of LED on/off cycles in rCnt and depends
from the number of rBits:
- if it is 30, the duration of phase III is written to rCnt,
- if it is 31, it is checked whether a receiver signal came in in flag bRx;
if that was the case, transmission is terminated and the bTxSkip flag
is set, otherwise the duration of phase II is written to rCnt,
- if it is smaller than 30, the duration of phase IV is written to
rCnt.
If rTgl was zero after inverting it, the register rCnt has to be set
one and the pause duration has to be written to OCR1A. If rBits is 30, the
duration of phase III is written to OCR1A. If it is 31, the duration of phase II
is written. If neither it is checked whether it is the last bit, in which case the
final pause duration is written. In the other cases, the next bit to be transmitted
is shifted to the carry flag, and the duration either of a zero or a one is written
to OCR1A.
The longest of all these subdivisions of the interrupt service routine needs 38
clock cycles. That limits the clock frequency to at least 3 MHz at 40 kHz
IR frequency or to 3.65 MHz at 48 kHz and provides even the opportunity to
use even higher IR frequencies than 48 kHz with a 4 or 8 MHz controller
clock.
At 8 MHz the sleep share in LED active phases is at 86%, over all transmit
phases the sleep share is at 93.4%. This increase of the sleep share results from the
fact that TC1 absolves the long pause cycles in an inactive manner with just
counting clock cycles and without any interrupts in between until the pause ends.
If many ones have to be processed, the sleep share even increases to up to 95.2%.
As all the times are configurable by changes to the source code the IR signal can
be flexibly designed. The number of bits is not configurable but needs major
changes in the source code if more or less than 28 are to be processed.
To the right are the first pulses of an active LED cycle in the simulator
avr_sim's oscilloscope view.
Frequency and pulse width are exact.
On the left side are the active LED pulses with 2 ms length in phase II.
On the right you see the two header signals transmitted. The durations of 2 and
1 ms length are obvious.
Left are the header signals in phase II and III and the first four bits (the motor
number) have been transmitted.
On the right all 28 data bits and the final bit have been transmitted.
On the left are 24 ones and four zeroes transmitted.
And right is the transmit of all ones.
The receiver procudes a PCINT interrupt every time the IR sensor sees an active
IR LED (high-to-low signal) and if the LED cycle turns off (low-to-high signal). The
receiver uses the 16-bit timer TC1 to measure the time over which the input pin
remains low and over which it remains high. The receiver algorithm uses these
durations to check whether these times are correct (= within the expected duration)
and collects the 28 data bits from this stream.
In order to do the duration measurement accurate, the PCINT interrupt service
rotine starts by reading the MSB of TCNT1, and by that ignoring and overwriting
the LSB. TCNT1 is then cleared by writing zeroes to it. That means the timer
restarts on every signal reception. Setting the bRx flag on each signal
reception event to block the start of the transmission algorithm. Finally SREG
is read for later recovery of the SREG flags.
The flow then is diverted depending from the polarity of the receiver pin: if
it is clear, an inactive LED signal had been coming in and was measured, otherwise
the receiver sensor had seen an active LED signal.
In case of a pause received (left part of the flow diagram), its duration is compared
with the shortest length of pause signals (which is a data zero). If the pulse
is shorter (below its minimum length, the carry flag is set), an error has happened
and the bRxE bit in rFlag is set one.
If it is longer and shorter than its maximum length, the zero bit is fine, the carry
flag is cleared and the zero is shifted into the reception area in the SRAM buffer.
If after shifting a one comes out of the four bytes, all bits have been received
correct and the received position is copied to the respective registers of the
position and the bRx flag is cleared to enable transmissions to start.
If not a zero bit has been received, it has to be tested if a one has been received.
If the duration is higher or equal to the minimum duration and smaller than the
maximum duration, a one-bit has been received and it is proceeded similarly with a
one in the carry flag.
If the duration exceeds the maximum of a one-bit, the algorithm diverts to the check
of the header lengthes of header 2 and then header 1. As both the active and inactive
phases of the two header signals have identical duration, this simplification is
possible. If the header 1 is correct, the receiver storage buffer is set to 0x000008
to collect data bits and finalize the bit collection.
This is the complete reception of incoming IR signals. The algorithm is used in the
controller board's tiny as well as in the motor's tiny. Both, the transmit and the
receive algorithm can be used generally, therefore those are encoded as include
source code file that can be included into both source codes without any specific
modification. That structuring of the source code requires that used parameters, such
as the controller's clock rate, are provided to the include. All parameters that have
to be defined outside the include are listed on top of the include source code. If
entry parameters are missing within the include source code the assembler run will
lead to errors and assembling will fail. So when assembling other source code that
uses this include take care that anything has been set correct.
As the 16-bit timer/counter 1 is completely and permanently occupied by the IR
transmit and receive algorithm, only the 8-bit timer TC0 is available for timing
of the stepper motors. The TC0 runs permanently, with a fixed prescaler value.
The stepper motors are to be driven with a frequency of between, e.g., 100 to
400 Hz. That means that their stepping requires delay times between 10
and 2.5 ms. As the motor controller ATtiny24 runs with either 8 or
4 MHz and TC0 needs 256 clock cycles for its turn-around, the following
times are achieved with the different prescaler values:
Clock | Prescaler | Turn-around time | Delay | Delay | Min=2 | Max f | Max=254 | Min f |
MHz | | (ms) | (10 ms) | (2.5 ms) | (µs) | Hz | (µs) | Hz |
8 | 1 | 0.032 | 80,000 | 20,000 | 0.25 | 4,000,000 | 63.5 | 15,748.03 |
8 | 0.256 | 10,000 | 2,500 | 2 | 500,000 | 508 | 1,968.50 |
64 | 2.048 | 1,250 | 312.5 | 16 | 62,500 | 4,064 | 246.06 |
256 | 8.192 | 312.5 | 78.125 | 64 | 15,625 | 16,256 | 61.52 |
1,024 | 32.768 | 78.125 | 19.53125 | 256 | 3,906.25 | 65,024 | 15.38 |
4 | 1 | 0.064 | 40,000 | 10,000 | 0.5 | 2,000,000 | 127 | 7,874.02 |
8 | 0.512 | 5,000 | 1,250 | 4 | 250,000 | 1,016 | 984.25 |
64 | 4.096 | 625 | 156.25 | 32 | 31,250 | 8,128 | 123.03 |
256 | 16.384 | 156.25 | 39.0625 | 128 | 7,812.5 | 32,512 | 30.76 |
1,024 | 65.536 | 39.0625 | 9.765625 | 512 | 1,953.135 | 130,048 | 7.69 |
That means that
- at 8 MHz clock delay times between 2.5 and 10 ms are best covered with
a prescaler value of 1,024, because 19 as well as 78 counter pulses fit well
into the delay time schedule and provide enough difference for the consequtively
applied compare match A and B values (1,024 clock cycles provide enough time in
between two steps),
- at this clock frequency the span of motor frequencies ranges between 15 (for a
large and very slow stepper) and 3,900 Hz (for a small and very fast
stepper),
- at 4 MHz clock and with 1,024 the count difference is shorter (9 to 39), but
still is in a realistic functional range. A prescaler value of 256 would also fit
and would yield a more exact timing,
- at this frequency the span is between 8 and 1,950 Hz, still a manageable
range.
The range of potential frequencies is broad enough with a fixed prescaler value of
1,024. At that and at 8 MHz TC0 runs with 7.8125 kHz or at 4 MHz at
3.90625 kHz. Its two compare matches A and B control the motor movements of
motor 1 and motor 2. Those can occur at multiples of 128 or 256µs, depending
from the controller clock.
From that the following algorithm results for driving the motors:
- Timer TC0 runs with the clock rate divided by 1,024 (at 7.81 resp.
3.91 kHz). On compare match the flags bM1 or bM2 are set.
- Further processing of the flagged compare matches is performed outside the
interrupt service routines. The two flags are checked and if set the respective
motor is moved (or not).
- The further processing of the motors is formulated as a macro, because the code
for the two motors does not differ much. The macro takes parameter @0 as motor
number (either 1 or 2) to do the different tasks, if necessary.
- First of all the set flag has to be cleared. Then the respective old motor
position is copied to the SRAM storage space, where it substracted from the target
position. If after that the carry flag is set, the motor is to be moved backwards.
If the carry flag is clear, and the Z flag is clear, then a move forward is performed.
This is also the case if the lower bytes of the position are not equal to the target
position's lower bytes.
- In case the motor is to move backwards, either a 1 (in half step mode) or a 2
(in full step mode) is to be subtracted from the current motor position. Additionally,
the distance is to be negated because it is negative (to get the positive distance to
the target positionand needed later on). In case motor movement is forward, the 1 or
2 are added to the current position.
- The motor's sCnt is cleared, so if the next position matches the target position,
the routine will start with that count. The the lower three bits of the actual position
are then converted to the next driver nibble (by use of the nibble table and of LPM)
and are written to the respective motor nibble by reading and saving the other nibble.
- To increase the speed of the next motor step, the speed delta is the subtracted from
the sDlyN variable by a 16-bit subtraction. If the MSB of the sDlyN is
smaller than the minimum delay (at the highest motor movement frequency), sDlyN
is set to this minimum to prevent from too high driving speed.
- The distance to the target position, as calculated in sMNP, is the checked.
If the distance is smaller than the constant cNearN the delay is increased by
the constant cFastSlow. In that case it is checked whether the delay would
exceed the maximum delay (and set to the maximum if that is the case).
- Finally, the variable sDlyN is added to the current TC0 count and then written
to the respective compare match register port.
- If the motor finally reaches its target position and the counter sCntN is
at zero (the last compare match was a movement), the current postion is transmitted
via the infrared conncetion. This is repeated at every compare match after 256 clock
cycles (every 65 ms) if the flag bTxSkipped had been set. If sCntN
reaches the constant cMotorOffN the motor driver is switched off by clearing
its motor bits.
The algorithm that determines which coil(s) of the stepper need to be activated uses
the following table:
StepTable:
.db 1,3,2,6,4,12,8,9 ; Stepper coils to be activated
In full-step mode, advancement of the positions are with two (so that only four of
these values are used), while in half-step mode each single position is used.
Algorithm uses the lowest three bits of the position as displcement to this table
to read the driver value nibble with the LPM instruction for the next driver nibble.
If motor 2 is to be written, the lower nibble read has to be swapped to the higher
nibble and the upper nibble has to be overwritten with the next nibble. In case of
motor 1 the upper nibble is preserved, the lower nibble is cleared and overwritten
by the nibble read from the table.
The controller's LC Display shows
- in line 1 the target position of the first motor, as adjusted with the forward/backward keys,
- in line 2 the actual position of the first motor, as reported via the IR backlink by the stepper
software,
- in line 3 the target position of the second motor, as adjusted with the right/left keys,
- in line 4 the actual position of the second motor, as reported via the IR backlink by the stepper
software.
The target and actual positions are in steps of the motor, so +100 means that motor 1 has to move to step
100 and then reports back 100 as position. As the 24-bit signed integers cover a range between -8,388,608
and +8,388,607, the positions need a conversion software that handles up to 9,000,000. The conversion is
in detail as shown below.
The actual positions of motor 1 and motor 2 are also converted from positions to rounds. This is done by
multiplying the position with the factor 16,777,216 / steps per round and dividing the result by 16,777,216
(to round up and skip the last three bytes of the multiplication result), just to avoid a perform a
24-by-24-bit division. The number of steps that the stepper motor and its gear reduction need for one round
of the wheel are configurable for motor 1 and 2 separately, but can well exceed 1,000 steps per round. For
example: the small stepper motor 28BYJ-48 needs 96 steps per round, so the position is multiplied with
16,777,216 / 96 = 174,762, rounded up to 174,763. By doing a 24-by-24-bit multiplication, the error margin
is very small. The result is displayed behind the R: in the actual line.
In both cases only negative numbers are signed, the sign character is placed immediately in front of the
numbers for better recognition.
The display of 24-bit-signed integers of positions and of the rounds is performed using the decimal
conversion of the 24-bit numbers in the routine DecimalConv. Depending from the input in rmp
(0 to 3) this routine does all converting, multiplying and formatting of one complete line for the LCD.
To save registers, the decimal conversion is done by loading the decimal number to the registers
rDec2:rDec1:rDec0 and by repeated subtraction of this decimal from the number in
rNmb2:rNmb1:rNmb0. The digit subtraction, counting as well as the leading zero blanking is
done in the subroutine DecDigit. By calling this routine with 1 million, 100,000, 10,000, 1,000,
100 and 10 in rDec the single digits are determined and written to their appropriate positions
in the line buffer. Lastly an eventual negative sign is added on an appropriate position, if necessary.
The four keys Forward, Backward, Right and Left are connceted to a
resistor matrix R1 to R5, which produces a characteristic voltage on the AD input pin ADC0.
©2020-2022 by http://www.avr-asm-tutorial.net