Hemi345
Senior Member
The code snippet below is the early stages of driving a stepper motor to wind/unwind a sun shade inside my greenhouse/coldframe project. It was written to background receive a serial transmission from the main board to tell the 18M2 what to do. The stepper motor is connected to ports "M3" and "M4" on Adafruit's FeatherWing DC/Stepper board.
Code:
#PICAXE 18m2
#no_data
#terminal 38400
setfreq m32
'CONSTANTS (c)
symbol cPCA9685 = %11000000
symbol cBaseAddr= 6 'first LEDx register (LED0_ON_L); 4 registers per LED
symbol cPWM = 2048 'half speed (higher the number, the slower the speed)
symbol cFullOn = 4096 'full on
symbol cSteps = 400 'one turn using half stepping
symbol cPause = 50 'amount of time inbetween steps
'VARIABLES (b=bit,v=byte,w=word)
symbol bA1 = bit0
symbol bA2 = bit1
symbol bB1 = bit2
symbol bB2 = bit3
symbol vPhases = b0 'bB2,bB1,bA2,bA1
symbol vPause = b1 'amount of time inbetween steps
symbol vCurPos = b2 'current position of stepper motor
symbol vDir = b6 'direction to run stepper motor
symbol vNextStep= b7
symbol vPin = b9 'port connected to PWM pin on TB6612
symbol vPosRx = b11 'position of the sun shade, (1=open,2=closed)
symbol vNewaddr = b12 'register on PCA9685 to change
symbol wPwmVal0 = w7 '(b14,b15)
symbol vPwmVal0L = b14 'low byte
symbol vPwmVal0M = b15 'high byte
symbol wMotorRx = w8 'b16,b17 stepper motor to work with (if there's more than one)
symbol vMotorRxCheck= b17 'high byte of wMotorRx, just to determine if valid data rx'd
symbol wSteps = w9 'b18,b19
symbol vGenVar0 = b27 'general use variable
#rem
M3 = PWM LED2:
A1 = LED4
A2 = LED3
M4 = PWM LED7:
B2 = LED6
B1 = LED5
M1 = PWM LED8:
A1 = LED10
A2 = LED9
M2 = PWM LED13:
B2 = LED12
B1 = LED11
#endrem
wPwmVal0 = 1
pause 4000 'give the serial terminal time to start up
sertxd ("Author: Hemi345",13,10)
sertxd ("Program: ",ppp_filename,13,10)
sertxd ("Downloaded: ",ppp_date,13,10)
#rem various help links
'https://motion.schneider-electric.com/technology-blog/stepper-motor-basics-half-and-micro-stepping/
'https://www.adafruit.com/product/2927 - link to module w/ PCA9685 chip
#endrem
hi2csetup i2cmaster, cPCA9685, i2cfast_32, i2cbyte
hi2cin 0, (vGenVar0)
sertxd ("Mode 1a: ",#vGenVar0,13,10)
hi2cout 0, (%00100000)
#rem
bit 7:0 0 Restart enabled
bit 6:0 0 Use internal clock
bit 5:0 1 Auto increment on
bit 4:1 0 Normal Mode on (sleep disabled)
bit 3:0 0 (don't use)
bit 2:0 0 (don't use)
bit 1:0 0 (don't use)
bit 0:1 0 AllCall (do not respond)
#endrem
pause 1500 'give the device time to start the oscillator
hi2cin 0, (vGenVar0)
sertxd ("Mode 1b: ",#vGenVar0,13,10)
hi2cin 1, (vGenVar0)
sertxd ("Mode 2a: ",#vGenVar0,13,10)
hi2cout 1, (%00010100)
#rem
bit 7:0: 0 reserved
bit 6:0: 0 reserved
bit 5:0: 0 reserved
bit 4:0: 1 Logic state inverted (1), state not inverted (0)
bit 3:0: 0 LEDs change on ACK (1), change on STOP (0)
bit 2:1: 1 totem-pole (1), open-drain (0)
bit 1:0: 0 umm, what?
bit 0:0: 0 umm, what?
#endrem
pause 1500 'give the device some time
hi2cin 1, (vGenVar0)
sertxd ("Mode 2b: ",#vGenVar0,13,10)
pause 4000
init:
wPwmVal0 = cPwm 'set PWM high value to default
vGenVar0 = 0
do while vGenVar0 < 4
lookup vGenVar0,(2,7,8,13),vPin 'ports connected to PWM pins on TB6612
gosub setPWM 'on ports LED2,LED7,LED8,LED13
inc vGenVar0
loop
hsersetup B9600_32, %000 'setup hardware serial Baud rate to 9600, %00 = true inverted (idle high), clear the buffer
Pause 1500
sertxd("Ready.",13,10)
main:
do
if pinc.2 = 1 then
gosub allOff
reset
end if
wPwmVal0 = cFullOn
vPause = 40
wMotorRx = $FF 'set the var to a non-valid value
vPosRx = $FF 'set the var to a non-valid value
HSerIn wMotorRx 'read first byte from buffer, this will be sent as ASCII ('S' for the Shade stepper)
HSerIn vPosRx 'read second byte from buffer, this will be sent as decimal (1,2 for the shade stepper)
'comment out the two HSerIn lines above and uncomment "wMotorRx = "S" : vPosRx = 1" below to operate stepper manually
'wMotorRx = "S" : vPosRx = 1 'change to 2 to run the other direction
if vMotorRxCheck = 0 Then 'valid character received for motor, data is in the low byte of wMotorRx
hsersetup B9600_32, %000 'clear the buffer so if something comes in while the shade is moving it can act on it later.
pause 1500
if wMotorRx <> $FF then 'for multiple steppers, this will identify the correct one (future use). the ASCII letter 'S' is for Shade stepper
sertxd("Received ",wMotorRx,#vPosRx,13,10)
sertxd("Current Position ",#vCurPos,13,10)
if vPosRx = vCurPos then
sertxd("Already at ",#vCurPos,13,10) 'already in position, do nothing
else
wSteps = 0
if vPosRx = 1 then
vDir = 0
else if vPosRx = 2 then
vDir = 1
end if
gosub stepMotor
gosub allOff
endif
endif
endif
loop
allOff:
vPhases = 0
gosub setPins
sertxd("----",13,10)
return
setPWM: 'sets PWM value for current going through phases; uses vPin and wPwmVal0
vNewaddr = 4 * vPin + cBaseAddr 'jump to the LEDx_ON_L register
sertxd("Set PWM on Pin ",#vPin," to ",#wPwmVal0,13,10)
hi2cout vNewaddr,(0,0,vPwmVal0L,vPwmVal0M)
return
setPins: 'sets state of phases on stepper motor; uses vPhases
if bA1 = 1 then
hi2cout 22,(vPwmVal0L,vPwmVal0M,0,0)
'sertxd("A1=1 ")
else
hi2cout 22,(0,0,0,0)
'sertxd("A1=0 ")
end if
'vPin = 3
if bA2 = 1 then
hi2cout 18,(vPwmVal0L,vPwmVal0M,0,0)
'sertxd("A2=1 ")
else
hi2cout 18,(0,0,0,0)
'sertxd("A2=0 ")
end if
'vPin = 5
if bB1 = 1 then
hi2cout 26,(vPwmVal0L,vPwmVal0M,0,0)
'sertxd("B1=1 ")
else
hi2cout 26,(0,0,0,0)
'sertxd("B1=0 ")
end if
'vPin = 6
if bB2 = 1 then
hi2cout 30,(vPwmVal0L,vPwmVal0M,0,0)
'sertxd("B2=1 ")
else
hi2cout 30,(0,0,0,0)
'sertxd("B2=0 ")
end if
return
#rem
M3 = PWM LED2:
A1 = LED4
A2 = LED3
M4 = PWM LED7:
B1 = LED5
B2 = LED6
M1 = PWM LED8:
A1 = LED10
A2 = LED9
M2 = PWM LED13:
B1 = LED11
B2 = LED12
#endrem
stepMotor: 'acts on wStep
vNextStep = 1
do while wSteps < cSteps
if vNextStep > 8 then
vNextStep = 1
end if
if vDir = 0 then 'CW
lookup vNextStep,(0,10,8,9,1,5,4,6,2),vPhases
else 'CCW
lookup vNextStep,(0,2,6,4,5,1,9,8,10),vPhases
end if
gosub setPins
pause vPause 'amount of time inbetween steps
inc wSteps
inc vNextStep
loop
return
Last edited: