syncfusion pdf viewer mvc : Convert multi page pdf to single jpg software Library dll winforms .net html web forms Introduction.to.Mechatronics.and.Measurement.Systems34-part1623

7.9 Method to Design a Microcontroller-Based System 
321
' stepper.bas (PIC16F84 microcontroller)
' Design Example
' Position and Speed Control of a Stepper Motor
' Four pushbutton switches are used to index to four different
' positions (0, 45, ' 90, and 180 degrees). Another pushbutton switch
' is used to toggle in and out of speed control mode (indicated by
' an LED). When in speed control mode, a potentiometer is used to
' control the speed. When to the right of the center position,
' the motor is turned CW at a speed proportional to the pot position.
' The motor turns CCW for pot positions to the left of center. The pot
' position is read from an external A/D converter (National
' Semiconductor ADC0831). The PIC retrieves the bits from the A/D
' converter via a clock signal generated by the PIC. The stepper
' motor is controlled via an E-lab EDE1200 unipolar driver IC and
' a ULN2003A Darlington driver.
' Define I/O pin names
led Var PORTB.0 
' speed control indicator LED
AD_start Var PORTB.1 
' A/D converter conversion start bit
' (must be held low during A/D conversion)
AD_data Var PORTB.2 
' A/D converter data line
' (for serial transmission of data bits)
AD_clock Var PORTB.3 
' A/D converter clock signal (400 kHz maximum)
P1 Var PORTA.2 
' position 1 NO button (0 degrees)
P2 Var PORTA.3 
' position 2 NO button (45 degrees)
P3 Var PORTA.4 
' position 3 NO button (90 degrees)
P4 Var PORTA.1 
' position 4 NO button (180 degrees)
SPD Var PORTA.0 
' speed control NO button to toggle speed control mode
motor_dir Var PORTB.6 
' stepper motor direction bit (0:CW 1:CCW)
motor_step Var PORTB.5 
' stepper motor step driver (1 pulse = 1 step)
' Declare Variables
motor_pos Var BYTE 
' current angle position of the motor (0, 45, 90, or 180)
new_motor_pos Var Byte 
' desired angle position of the motor
delta Var BYTE 
' required magnitude of angular motion required
num_steps Var BYTE 
' number of steps required for the given angular motion
step_period Var BYTE 
' millisecond width of step pulse (1/2 of period)
i Var Byte 
' counter used for For loops
AD_value Var BYTE 
' byte used to store the 8-bit value from the A/D converter
AD_pause Var BYTE 
' clock pulse width for the A/D converter
blink_pause Var BYTE 
' millisecond pause between LED blinks
bit_value Var BYTE 
' power of 2 value for each bit used in the A/D conversion
' Define Constants
CW Con 0 
' clockwise motor direction
CCW Con 1 
' counterclockwise motor direction
(continued )
Error processing SSI file
322 
CHAPTER 7 
Microcontroller Programming and Interfacing
' Initialize I/O and variables
TRISA = $FF 
' configure all PORTA pins as inputs
TRISB = %00000100 
' configure all PORTB pins as outputs except RB2
High AD_start 
' disable A/D converter
Low motor_step 
' start motor step signal in low state
motor_pos = 0 
' assume the current position is the 0 degree position
step_period = 10 
' initial step speed (1/100 second between steps)
AD_pause = 10 
' 10 microsecond pulsewidth for the A/D clock
blink_pause = 200 
' 1/5 second pause between LED blinks
' Blink the speed control LED to indicate start-up
Gosub blink : Gosub blink
' Wait for a button to be pressed (i.e., polling loop)
main:
If (P1 == 1) Then
' Move motor to the 0 degree position
new_motor_pos = 0
Gosub move
Else
If (P2 == 1) Then
' Move motor to the 45 degree position
new_motor_pos = 45
Gosub move
Else
If (P3 == 1) Then
' Move motor to the 90 degree position
new_motor_pos = 90
Gosub move
Else
If (P4 == 1) Then
' Move motor to the 180 degree position
new_motor_pos = 180
Gosub move
Else
If (SPD == 1) Then
' Enter speed control mode
Gosub speed
EndIf : EndIf : EndIf : EndIf : EndIf
Goto main    ' continue polling buttons
End ' end of main program
' Subroutine to blink the speed control indicator LED
blink:
High led
Pause blink_pause
Low led
Pause blink_pause
Return
(continued )
Error processing SSI file
7.9 Method to Design a Microcontroller-Based System 
323
' (the motor step size is 7.5 degrees)
move:
If (new_motor_pos > motor_pos) Then
motor_dir = CW
delta = new_motor_pos - motor_pos
Else
motor_dir = CCW
delta = motor_pos - new_motor_pos
EndIf
' Determine the required number of steps (given 7.5 degrees per step)
num_steps = 10*delta / 75
' Step the motor the appropriate number of steps
Gosub move_steps
' Update the current motor position
motor_pos = new_motor_pos
Return
move_steps:
For i = 1 to num_steps
Gosub step_motor
Next
Return
 direction
step_motor:
Pulsout motor_step, 100*step_period 
' (100 * 10microsec = 1 millisec)
Pause step_period
' Equivalent code:
' High motor_step
' Pause step_period
' Low motor_step
' Pause step_period
Return
' Subrouting to poll the POT for speed control of the stepper motor
speed:
' Turn on the speed control LED indicator
High LED
' Wait for the SPEED button to be released
Gosub button_release
' Polling loop for POT speed control
pot_speed:
' Check if the SPEED button is down
(continued )
Error processing SSI file
324 
CHAPTER 7 
Microcontroller Programming and Interfacing
If (SPD == 1) Then
' Wait for the SPEED button to be released
Gosub button_release
' Turn off the speed control LED indicator
Low led
' Assume the new position is the new 0 position
motor_pos = 0
' Exit the subroutine
Return
EndIf
' Sample the POT voltage via the A/D converter
Gosub get_AD_value
' Adjust the motor speed and direction based on the POT value and
  step the motor a single step.
  Enforce a deadband at the center of the range
  Have the step period range from 100 (slow) to 1 (fast)
If (AD_value > 150) Then
motor_dir = CW
step_period = 100 - (AD_value - 150)*99/(255 - 150)
Gosub step_motor
Else
If (AD_value < 100) Then
motor_dir = CCW
step_period = 100 - (100 - AD_value)*99/100
Gosub step_motor
EndIf
EndIf
' Continue polling
goto pot_speed
' Subroutine to wait for the speed control button to be released
button_release:
Pause 50 
' wait for switch bounce to settle
While (SPD == 1) : WEND
Pause 50 
' wait for switch bounce to settle
Return
' Subroutine to sample the POT voltage from the A/D converter
'   to the original 0 to 5V analog voltage range.
get_AD_value:
' Initialize the A/D converter
Low AD_clock 
' initialize the clock state
Low AD_start 
' enable the A/D converter
Gosub pulse_clock 
' send initialization pulse to A/D clock
(continued )
Error processing SSI file
7.9 Method to Design a Microcontroller-Based System 
325
' Get each converted bit from the A/D converter (at 50 kHz)
bit_value = 128 
' value of the MSB
AD_value = 0
FOR I = 7 To 0 Step -1 ' for each bit from the MSB to the LSB
'  Output clock pulse
Gosub pulse_clock
AD_value = AD_value + AD_data*bit_value
bit_value = bit_value / 2
Next i
' Disable the A/D converter
High AD_start
Return
' Subroutine to send a pulse to the A/D clock line
pulse_clock:
Pulsout AD_clock, 1 : PauseUS 10 
' 20 microsecond pulse
Return
THREADED DESIGN EXAMPLE 
DC motor position and speed controller—Full solution with serial interface 
C.3  
The figure below shows the functional diagram for Threaded Design Example C (see Section 
1.3 and Video Demo 1.8). Presented here is the entire solution to this problem. This solution 
utilizes two PIC microcontrollers. The main PIC is referred to as the “master” PIC, because 
ve” PIC, 
because it simply provides information to the master PIC upon command.      
microcontrollers
SLAVE
PIC
MASTER
PIC
liquid crystal display
DC motor with
digital position encoder
quadrature
decoder
and counter
1
2
3
4
5
6
7
8
9
*
0
#
keypad
keypad
decoder
button
buzzer
H-bridge
driver
The circuit schematic and software listings are shown below. The code is commented, 
so you should be able to follow the logic as it relates to the functional diagram and circuit 
V
i
d
e
o
D
e
m
o
1.8DC motor 
position and 
speed controller
(continued )
Error processing SSI file
326 
CHAPTER 7 
Microcontroller Programming and Interfacing
schematic. There are two software listings. One is for the master PIC (a PIC16F88) that 
monitors the keypad (see Threaded Design Example C.2), provides a menu-driven user inter-
face on the LCD (see Threaded Design Example C.2), and drives the motor (see Threaded 
Design Examples C.4 and C.5). The other listing is for the slave PIC (a PIC16F84) that 
to the master PIC. 
As with the other threaded design examples, details covering the different components 
of the design can be found throughout the book. This solution is a good example of how to 
communicate among multiple PICs using a serial interface. The specific code designed to 
implement the communication can be found in the  get_encoder  subroutine in the master PIC 
code and the main loop in the slave PIC code. One I/O line is simply set high or low by the 
master PIC to command the slave PIC when to send data. A second I/O line then receives the 
data through a standard serial communication protocol.
master PIC code:
' dc_motor.bas (PIC16F88 microcontroller)
' Design Example
' Position and Speed Control of a DC Servo Motor.
The user interface includes a keypad for data entry and an LCD for text
messages. The main menu offers three options: 1 - position control,
2 - speed control, and 3 - position control gain and motor PWM control.
a separate pushbutton switch. When in gain and PWM control mode,
pressing 1/4 increases/decreases the proportional gain factor (kP)
and pressing 3/6 increases/decreases the number of PWM cycles sent
to the motor during each control loop update.
back to the main menu. E-Lab's EDE1144 keypad encoder is used to detect
keypress) to the PIC16F88. Acroname's R179-6V-ENC-MOTOR servo motor is
running dc_enc.bas, is used to communicate to an Agilent HCTL-2016
quadrature decoder/counter to track the position of the motor encoder.
The 16F88 communicates to the 16F84 via handshake (start) and serial
communication lines.
' Configure the internal 8MHz internal oscillator
DEFINE OSC 8
OSCCON.4 = 1 : OSCCON.5 = 1 : OSCCON.6 = 1
(continued )
Error processing SSI file
7.9 Method to Design a Microcontroller-Based System 
327
' Turn off A/D converters (thereby allowing use of pins for I/O)
ANSEL = 0
' Define I/O pin names
key_serial Var PORTB.0 
' keypad serial interface input
motor_dir Var PORTB.7 
' motor H-bridge direction line
motor_pwm Var PORTB.6 
' motor H-bridge pulse-width-modulation line
stop_button Var PORTB.4 ' motor stop button
enc_start Var PORTB.2 
' signal line used to start encoder data transmission
enc_serial Var PORTA.7 
' serial line used to get encoder data from the 16F84
enc_rst Var PORTB.5 
' encoder counter reset signal (active low)
(continued )
5 V
20 × 2 LCD character display
V
ss
V
cc
V
ee
RS R/W W E
DB4 DB5 DB6 DB7
1 2
3 4
5
6
11 12
13
14
330 Ω
330 Ω
4.7 kΩ
330 Ω
0.1 μF
5 V
5 V
20 k
pot
5 V V 1 k
PIC16F88
RA1
RA0
RA7
CLKO
V
dd
RB7
RB6
RB5
RB4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RA2
RA3
RA4
RA5
V
ss
RB0
RB1
RB2
RB3
1
2
3
4
5
6
7
8
9
*
0
#
1
2
3
4
5
6
7
keypad
EDE1144
XMIT
+5 V
GND
R0
R1
R2
R3
Beep
Valid
OSC1
C3
C2
C1
C0
OSC2
1
3, 4, 14
2, 5
6
7
8
9
10
11
12
13
15
16
18
5 V
5 V
buzzer
2N2222
DC motor
with
encoder
4.7 kΩ
1 kΩ
S17-3A-LV
H-Bridge
+
HCTL-2016
CLK
CHA
CHB
D0-7
PIC16F84
SEL
PORTB
RA2
RA3
RA4
RA0
RA1
OE
RST
5 V
1 k
NO
stop
button
LED
LED
5 V
17
18
1
2
3
6–13
3
4
5
2
1, 15–9
7
6
J2-2
J2-3
J3-1
J3-6
J2-5
J2-4
DIR
PWM
VMOTOR
GND
Error processing SSI file
328 
CHAPTER 7 
Microcontroller Programming and Interfacing
' Declare Variables
key_value Var BYTE 
' code byte from the keypad
motor_pos Var Word 
' current motor position in degrees
new_motor_pos Var Word 
' desired motor position (set point) in degrees
error Var Word 
' error magnitude between current and desired positions
motor_speed Var BYTE 
' motor speed as percentage of maximum (0 to 100)
motion_dir Var BIT 
' motor direction (1:CW/Forward 0:CCW/Reverse)
on_time Var WORD 
' PWM ON pulse width
off_time Var WORD 
' PWM OFF pulse width
enc_pos Var WORD 
' motor encoder position (high byte and low byte)
i Var Byte 
' counter variable for FOR loops
kp Var BYTE 
' proportional gain factor position control
pwm_cycles Var BYTE 
' # of PWM pulses sent during the position control loop
' Define constants
key_mode Con 0 
' 2400 baud mode for serial connection to keypad
key_1 Con $30 
' hex code for the 1-key on the keypad
key_2 Con $31 
' hex code for the 2-key on the keypad
key_3 Con $32 
' hex code for the 3-key on the keypad
key_4 Con $34 
' hex code for the 4-key on the keypad
key_5 Con $35 
' hex code for the 5-key on the keypad
key_6 Con $36 
' hex code for the 6-key on the keypad
key_7 Con $38 
' hex code for the 7-key on the keypad
key_8 Con $39 
' hex code for the 8-key on the keypad
key_9 Con $41 
' hex code for the 9-key on the keypad
key_star Con $43 
' hex code for the *-key on the keypad
key_0 Con $44 
' hex code for the 0-key on the keypad
key_pound Con $45 
' hex code for the #-key on the keypad
CW Con 1 
' motor clockwise (forward) direction
CCW Con 0 
' motor counterclockwise (reverse) direction
pwm_period Con 50 
' period of each motor PWM signal cycle (in microsec)
  (50 microsec corresponds to 20kHz)
enc_mode Con 2 
' 9600 baud mode for serial connection to the encoder IC
' Initialize I/O and variables
TRISB.6 = 0 
' configure H-bridge DIR pin as an output
TRISB.7 = 0 
' configure H-bridge PWM pin as an output
motion_dir = CW 
' starting motor direction: CW (forward)
motor_pos = 0 
' define the starting motor position as 0 degrees
motor_speed = 50 
' starting motor speed = 50% duty cycle
kp = 50 
' starting proportional gain for position control
pwm_cycles = 20 
' starting # of PWM pulses sent during the
  position control loop
Low motor_pwm 
' make sure the motor is off to begin with
Low enc_start 
' disable encoder reading to begin with
Gosub reset_encoder 
' reset the encoder counter
(continued )
Error processing SSI file
7.9 Method to Design a Microcontroller-Based System 
329
' Wait 1/2 second for everything (e.g., LCD) to power up
Pause 500
' Receive dummy byte from the PIC16F84 to ensure proper communication
SERIN enc_serial, enc_mode, key_value
' Wait for a keypad button to be pressed (i.e., polling loop)
Gosub main_menu 
' display the main menu on the LCD
main:
Serin key_serial, key_mode, key_value
If (key_value = key_1) Then
Gosub reset_encoder
Gosub position
Else
If (key_value = key_2) Then
motor_speed = 50 
' initialize to 50% duty cycle
Gosub speed
Else
If (key_value = key_3) Then
Gosub adjust_gains
Endif : Endif : Endif
Goto main 
' continue polling keypad buttons
End ' end of main program
' Subroutine to display the main menu on the LCD
main_menu:
Lcdout $FE, 1, "Main Menu:"
Lcdout $FE, $C0, "1:pos. 2:speed 3:gain"
Return
' Subroutine to reset the motor encoder counter to 0
reset_encoder:
Low enc_rst  
' reset the encoder counter
High enc_rst 
' activiate the encoder counter
Return
' Suroutine for position control of the motor
position:
' Display the position control menu on the LCD
Lcdout $FE, 1, "Position Menu:"
Lcdout $FE, $C0, "1:0 2:45 3:90 4:180 #:<"
' Wait for a keypad button to be pressed
Serin key_serial, key_mode, key_value
' Take the appropriate action based on the key pressed
If (key_value == key_1) Then
new_motor_pos = 0
Else
(continued )
Error processing SSI file
330 
CHAPTER 7 
Microcontroller Programming and Interfacing
(continued )
If (key_value == key_2) Then
new_motor_pos = 45
Else
If (key_value == key_3) Then
new_motor_pos = 90
Else
If (key_value == key_4) Then
new_motor_pos = 180
Else
If (key_value == key_pound) Then
Gosub main_menu
Return
Else
Goto position
Endif : Endif : Endif : Endif : Endif
' Position control loop
While (stop_button == 0) 
' until the stop button is pressed
' Get the encoder position (enc_pos)
Gosub get_encoder
'
' Convert encoder pulses to degrees. The encoder outputs 1230 pulses
  per 360 degrees of rotation
motor_pos = enc_pos * 36 / 123
If (new_motor_pos >= motor_pos) Then
error = new_motor_pos - motor_pos
motor_dir = CW
Else
error = motor_pos - new_motor_pos
motor_dir = CCW
Endif
' Set the PWM duty cycle based on the current error
If (error > 20) Then  ' use maximum speed for large errors
motor_speed = kp
Else
' Perform proportional position control for smaller errors
motor_speed = kp * error / 20
Endif
' Output a series of PWM pulses with the speed-determined duty cycle
Gosub pwm_periods  
' calculate the on and off pulse widths
For I = 1 to pwm_cycles
Gosub pwm_pulse 
' output a full PWM pulse
Next I
Error processing SSI file
Error processing SSI file