The next tutorial I want to look at a stepping motor... To step a stepper motor we need to sequence the coil windings... The windings are arranged so applying current to the coils in a certain sequence we can turn the motor in small steps.
The sequence shown in the diagram will step the motor in full steps 0AH, 09H, 05H, 06H..
The connections are as follows...
To half step the motor then just add a single excitation in between the steps .. As A1 and A2 are on in the first sequence moving to A1 to B2 and turning A2 off.. 0Ah, 08H, 09H …. etc.. so the half step sequence is:-
0AH, 08H, 09H, 01H, 05H, 04H, 06H, 02H...
The code to show it's operation is here..
Code 9
And the same code in C
Code 10
The Servo motor!!!
I'm going to jump into a slightly faster river now... I would like to move onto a servo motor... The RC servo motor uses a pulse to determine position... Not PWM ( pulse width modulation ) but we can use PWM to achieve this.
The pulse needs to be roughly 1.5mS long to sit the motor in a central position, it the pulse is modified to 1mS the servo will turn to a minimum position, if the pulse is increased to 2mS the servo will move to the maximum position.
Servo RC motors are pretty cheap to get hold of... Most robotic/ hobby websites will stock them for next day delivery.. This is a basic servo motor..
The best way to drive a servo is with a CCP module in PWM mode.. The servo period needs to be 6mS ~ 20ms or 166hz to 50hz ...If we use 6mS, we can set 25% duty to represent 1.5mS and 16% and 33% to represent 1mS and 2mS respectively.. If we use a 10 bit resolution, that will be 160 bits of control, 80 positions left and 80 positions right..
However!! The chip we are using hasn't one of these modules, so I'm going to drive a timer to do the job for me... Here is the connections.... I have two push buttons to change the positions..
Now simple control is just Left and right... If we want to move the servo with a potentiometer we will need to do the I2C tutorial as the micro hasn't got an ADC onboard....So for now I'll calculate the times for 1mS... 1.5mS...And 2mS.. Pressing a button will move the motor to it's maximum or minimum positions... Releasing will return the motor to the central position..
The servo consumes very little power from the micro pin so no buffer is needed...
Code 11
I am using R6 and R7 to systematically load the values needed to move the motor..
To use the timer to give exact timing we need to intervene with its operation.. If we allow the timer to run from 0 ~ 65535 it would take 70.89mS so if we pre-load the timer with a calculated figure we can get it to time out when we need it to.. We need to count 1392 clock cycles to get 1.5mS..
1392 * 1.0815uS = 1.5mS... You need to deduct 1392 from the maximum count of 65535.... The calculated values are in the code..
The C code is here..
Code 12
I have used a function to change the timer pre-load... Using an “unsigned int“ ensures the value isn't evaluated as a negative..
I am working on the next two tutorials.... As we speak... a multiline LCD screen, namely a 16 x 2.. and the serial communication to a PC running a terminal program..
The sequence shown in the diagram will step the motor in full steps 0AH, 09H, 05H, 06H..
The connections are as follows...
To half step the motor then just add a single excitation in between the steps .. As A1 and A2 are on in the first sequence moving to A1 to B2 and turning A2 off.. 0Ah, 08H, 09H …. etc.. so the half step sequence is:-
0AH, 08H, 09H, 01H, 05H, 04H, 06H, 02H...
The code to show it's operation is here..
Code 9
Code:
IDX equ 20H
org 0 ; Reset vector
sjmp Start
org 30H ; Code starts here
Start:
clr A ; A = 0
mov IDX,A ; Store initial array index
mov DPTR,#digits ; Get array start point
While:
jnb P0.0,CCW ; Counter clockwise?
jnb P0.1,CW ; Clockwise
sjmp While ; do it again ( Forever loop )
CCW:
mov A,IDX ; get current step
movc A,@A+DPTR ; Get stepper position
mov P1,A ; Move motor
acall delay ; Step delay ( 100mS )
mov A,IDX ; get current step
inc A ; Next index
jnb Acc.3,NotOver ; Check index variable
clr A ; not more than three
NotOver:
mov IDX,A ; Store current array index
sjmp While ; Back to loop
CW:
mov A,IDX ; get current step
movc A,@A+DPTR ; Get stepper position
mov P1,A ; Move motor
acall delay ; Step delay ( 100mS )
mov A,IDX ; get current step
dec A ; Previous index
jnb Acc.7,NotUnder ; Check index variable
add A,#8 ; not less than zero
NotUnder:
mov IDX,A ; Store current array index
sjmp While ; Back to loop
delay:
mov R2,#180 ; 2 clock cycles (call) = 2
mov R1,#0 ; 2 clock cycles (loading) = 2
d1:
djnz R1,d1 ; 2 * 256 clock cycles *180 = 92160
djnz R2,d1 ; 2 * 180 clock cycles = 380
ret ; 2 clock cycles (return) = 2
; * 1.0815 (11.0952 osc) = 100.07ms
digits: db 0AH,08H,09H,01H,05H,04H,06H,02H ; 8 step patterns 0AH to 02H
end
And the same code in C
Code 10
C:
#include<8051.h> // definition file
unsigned char digits[] = {0xA,0x8,0x9,0x1,0x5,0x4,0x6,0x2};
char idx;
void delay(void) // How to get approximately 100mS..
{
int x = 8410; // The while statement consumes 11.89uS (11 clock cycles )
while(x--); // So 8410 * 11.89uS = nearly 100mS
}
void CCW(void) // Direction Anti
{
P1 = digits[idx]; // Get step position
if(++idx > 7) idx = 0; // Only 8 steps
}
void CW(void) // Direction Norm
{
P1 = digits[idx]; // Get step position
if(--idx< 0) idx = 7; // Only 8 steps
}
void main(void) // Main entry point
{
idx = 0;
while(1) // Forever loop
{
if(!P0_0)CCW(); // Check switch 1
if(!P0_1)CW(); // Check switch 2
delay(); // step delay
}
}
The Servo motor!!!
I'm going to jump into a slightly faster river now... I would like to move onto a servo motor... The RC servo motor uses a pulse to determine position... Not PWM ( pulse width modulation ) but we can use PWM to achieve this.
The pulse needs to be roughly 1.5mS long to sit the motor in a central position, it the pulse is modified to 1mS the servo will turn to a minimum position, if the pulse is increased to 2mS the servo will move to the maximum position.
Servo RC motors are pretty cheap to get hold of... Most robotic/ hobby websites will stock them for next day delivery.. This is a basic servo motor..
The best way to drive a servo is with a CCP module in PWM mode.. The servo period needs to be 6mS ~ 20ms or 166hz to 50hz ...If we use 6mS, we can set 25% duty to represent 1.5mS and 16% and 33% to represent 1mS and 2mS respectively.. If we use a 10 bit resolution, that will be 160 bits of control, 80 positions left and 80 positions right..
However!! The chip we are using hasn't one of these modules, so I'm going to drive a timer to do the job for me... Here is the connections.... I have two push buttons to change the positions..
Now simple control is just Left and right... If we want to move the servo with a potentiometer we will need to do the I2C tutorial as the micro hasn't got an ADC onboard....So for now I'll calculate the times for 1mS... 1.5mS...And 2mS.. Pressing a button will move the motor to it's maximum or minimum positions... Releasing will return the motor to the central position..
The servo consumes very little power from the micro pin so no buffer is needed...
Code 11
Code:
IDX equ 20H
org 0 ; Reset vector
sjmp Start
org 30H ; Code starts here
Start:
mov TMOD,#01H ; Timer 0 16 bit timer.. 1.5ms / 1.085uS = 1392 ( timer reload values )
; 1ms = 941.. (0xFFFF - d941 = 0xFC52...)
While: ; 2ms = 1843.. ( 0xFFFF - d1843 = 0xF8CC )
jb P0.0,cont
sjmp left
cont:
jb P0.1,cont1
sjmp right
cont1:
mov R7,#090H ; 0FA90H = 1.5mS Middle
mov R6,#0FAH
cont2:
mov TH0,R6 ; Load selected pulse width
mov TL0,R7
clr TF0 ; Ensure timer runs
setb TR0
setb P1.0
jnb TF0,$
mov TH0,#0C0H ; 20mS delay
mov TL0,#0H
clr TF0 ; Ensure timer runs
setb TR0
clr P1.0
jnb TF0,$ ; rest of period
sjmp While ; do it again ( Forever loop )
left:
mov R7,#052H ; 0FC52 = 1mS.. Fully left
mov R6,#0FCH
sjmp cont2
right:
mov R7,#0CCH ; 0F8CC = 2mS.. Fully right
mov R6,#0F8H
sjmp cont2
end
I am using R6 and R7 to systematically load the values needed to move the motor..
To use the timer to give exact timing we need to intervene with its operation.. If we allow the timer to run from 0 ~ 65535 it would take 70.89mS so if we pre-load the timer with a calculated figure we can get it to time out when we need it to.. We need to count 1392 clock cycles to get 1.5mS..
1392 * 1.0815uS = 1.5mS... You need to deduct 1392 from the maximum count of 65535.... The calculated values are in the code..
The C code is here..
Code 12
C:
#include<8051.h> // definition file
#define LEFT 0xF8CC
#define RIGHT 0xFC52
#define CENTER 0xFA8F
#define PAUSE 0xC000
void SetTimer(unsigned int time)
{
TH0 = time>>8;
TL0 = time & 0xFF;
}
void main(void) // Main entry point
{
TMOD = 1; // 16 bit timer
while(1) // Forever loop
{
if(!P0_0) SetTimer(LEFT); // Set time for maximum left
else if(!P0_1) SetTimer(RIGHT); // Right
else SetTimer(CENTER); // Or center
TF0 = 0;
TR0 = 1; // Timer on
P1_0 = 1;
while(!TF0); // Wait until timer expires
P1_0 = 0;
TR0 = TF0 = 0; // RESET Flag and timer off
SetTimer(PAUSE); // 20mS period
TR0 = 1;
while(!TF0); // Wait again
TF0 = 0;
TR0 = 0; // Reset... again timer off
}
}
I am working on the next two tutorials.... As we speak... a multiline LCD screen, namely a 16 x 2.. and the serial communication to a PC running a terminal program..