stepper control with acceleration and variable freq square wave output

alistairsam

Senior Member
Hi,

I did get the concept of using two bytes to store values upto 65535, but was'nt sure how that worked with interal eeprom storage addressing.

when you say

So if you have a value like 32456 in w1 then to save to EEPROM
WRITE <location>, (b3, b2)
is'nt that for writing into data memory? Is'nt this different from EEPROM memory?

also, does that mean numbers above 255 have to be broken into their 8 bit msb and lsb and then specified as data?

I'm just not clear about the location which I read is a number between 0 and 255, and the b3,b2, and whether I'll have to then use alternate location numbers in the address if i'm using two bytes.

eg, if
write 1 (b3,b2) uses two bytes, then is the next write possible only at location 3 (as location two would've been used by b2)

so write 1 (msb,lsb)
then write 3 (msb,lsb)
and so on?

how is it done for eeprom memory with the eeprom command?

how many address locations are there for a 28X2 internal eeprom?
 

alistairsam

Senior Member
In addition to reading more about bytes and word variables in PICAXE Manual 2 around page 10 and onwards, you could also have a look at my PICAXE memory map here: http://www.picaxeforum.co.uk/showthread.php?t=11514
hi just saw the memory map. its clearer now, but still not sure how 16 bits are written in eeprom.
for example, i want to store the following numbers in sequence in eeprom.

25000
12500
6250
3125
2000
1429
1000
714

thanks
 

westaust55

Moderator
@Alistair,

I think the time has come to suggest that you need to spend a little more time reading the PICAXE programming Manual.

EEPROM command is used to load data into EEPROM at the time a program is downloaded into the PICAXE.
WRITE command is used to change values in the e EEPROM memory while the program is being executed
READ command is used to retrieve values from the EEPROM memory during program execution.

eg, if
write 1 (b2,b3) uses two bytes, then is the next write possible only at location 3 (as location two would've been used by b2)

so write 1 (lsb,msb)
then write 3 (lsb,msb)
and so on?
Yes, that is correct.
Don&#8217;t forget that you also have EEPROM memory location 0 as well.
 
Last edited:

westaust55

Moderator
how many address locations are there for a 28X2 internal eeprom?
Please try looking in the PICAXE manuals . . .

If you look at PICAXE Manual 2 page 49 it states:
PICAXE-18A, 18X, 20X2, 28X1, 28X2, 40X1, 40X2 - - - 0 to 255

The same details aregiven in the memory map I linked you to.
 

westaust55

Moderator
hi just saw the memory map. its clearer now, but still not sure how 16 bits are written in eeprom.
for example, i want to store the following numbers in sequence in eeprom.

25000
12500
6250
3125
2000
1429
1000
714

thanks

To store the values with EEPROM statements at initial download then use:

Code:
SYMBOL word 1 = 25000
SYMBOL word 2 = 12500
SYMBOL word 3 = 6250
SYMBOL word 4 = 3125
SYMBOL word 5 = 2000
SYMBOL word 6 = 1429
SYMBOL word 7 = 1000
SYMBOL word 8 =  714

SYMBOL MSB1 = word1 / 256
SYMBOL MSB2 = word2 / 256
SYMBOL MSB3 = word3 / 256
SYMBOL MSB4 = word4 / 256
SYMBOL MSB5 = word5 / 256
SYMBOL MSB6 = word6 / 256
SYMBOL MSB7 = word7 / 256
SYMBOL MSB8 = word8 / 256

EEPROM 0,(word1, MSB1, word2, MSB2, word3, MSB3, word4, MSB4, word5, MSB5, word6, MSB6, word7, MSB7, word8, MSB8)
EDIT: note that it should for consistency in fact be LSB in the lower byte and MSB in the higher byte.
I have corrected the data in my earlier post and my quote of your post to reflect this.
Then you can read the data back from EEPROM with commands like:
READ 0, WORD w0

Note the WORD keyword allows you to read and write word variables
 
Last edited:

alistairsam

Senior Member
@Alistair,

I think the time has come to suggest that you need to spend a little more time reading the PICAXE programming Manual.

EEPROM command is used to load data into EEPROM at the time a program is downloaded into the PICAXE.
WRITE command is used to change values in the e EEPROM memory while the program is being executed
READ command is used to retrieve values from the EEPROM memory during program execution.
Hi Guys,

I'm not trying to take shortcuts by not reading the manual, I have all three open all the time and constantly reference it when testing a command in the simulator, after reading through the manuals. but will pay more attention to detail.

I basically don't need to change values once loaded into eeprom. they won't change.

will use the eeprom command with my data in the format (msb,lsb).
just was'nt sure if the byte1:byte2 method applied to eeprom storage as well.

what threw me off was the line in the manual
"- Data are constants (0-255) which will be stored in the EEPROM."

but then again, the syntax shows (data,data..) did'nt realize that meant storing two bytes in two address locations.
 

westaust55

Moderator
Note that while you can store data in either order,
if you use the LSB, MSB sequence per my code example, then as per my edited comments in earlier post you can use the WORD keyword to read straight into word variables.
 

alistairsam

Senior Member
To store the values with EEPROM statements at initial download then use:

Code:
SYMBOL word 1 = 25000
SYMBOL word 2 = 12500
SYMBOL word 3 = 6250
SYMBOL word 4 = 3125
SYMBOL word 5 = 2000
SYMBOL word 6 = 1429
SYMBOL word 7 = 1000
SYMBOL word 8 =  714

SYMBOL MSB1 = word1 / 256
SYMBOL MSB2 = word2 / 256
SYMBOL MSB3 = word3 / 256
SYMBOL MSB4 = word4 / 256
SYMBOL MSB5 = word5 / 256
SYMBOL MSB6 = word6 / 256
SYMBOL MSB7 = word7 / 256
SYMBOL MSB8 = word8 / 256

EEPROM 0,(word1, MSB1, word2, MSB2, word3, MSB3, word4, MSB4, word5, MSB5, word6, MSB6, word7, MSB7, word8, MSB8)
Thank you very much. that works perfectly.

is it possible to use a variable instead of the number in the eeprom statement.
eg.

Code:
symbol g = b4
for g=1 to 8 step 1
EEPROM 0, (wordb4, MSBb4)
next
it does'nt work in the simulator, gives a syntax error, but if it worked, it would make writing a statement for 100+ values easier.


Have written the code. will post shortly.
Now just have to test this with my stepper driver and see what frequency I can accelerate the stepper to and how smooth the ramp up is.
 

westaust55

Moderator
Thank you very much. that works perfectly.

is it possible to use a variable instead of the number in the eeprom statement.
NO, is the short answer.

SYMBOL statements and EEPROM statements are actioned at the time the program is downloaded.

Variables are not evaluated until the program is running and the actual line of code is reached.

Any SYMBOL alias names for variables and constants are swapped out during the tokenisation and download phase - the alias names as used are not transfered to the PICAXE effectively just the base variable names (such as "b5") are used inside the PICAXE.
 

alistairsam

Senior Member
thanks. makes sense.

i've written a small for next loop to generate the statements to use in a text editor.

symbol g = b1
for g=1 to 78 step 1
sertxd ("word",#b1,", MSB",#b1)
next
 

alistairsam

Senior Member
Hi,

got the code working as I'd wanted.
code below is for an spst switch at B.3
there will be 5 pins (commented out) of which only the HighCW and HighCCW will involve acceleration.

will be adding 70 more values to the accel profile to accelerate from 0Hz to 2Khz and decelerate as well.

will need to test with the stepper under load to arrive at final accel ramp and max velocity.

Thanks for all the help.

will post results after testing with the motors.

Code:
'28X2

SYMBOL word1 = 25000
SYMBOL word2 = 12500
SYMBOL word3 = 6250
SYMBOL word4 = 3125
SYMBOL word5 = 2000
SYMBOL word6 = 1429
SYMBOL word7 = 1000
SYMBOL word8 =  714

SYMBOL MSB1 = word1 / 256
SYMBOL MSB2 = word2 / 256
SYMBOL MSB3 = word3 / 256
SYMBOL MSB4 = word4 / 256
SYMBOL MSB5 = word5 / 256
SYMBOL MSB6 = word6 / 256
SYMBOL MSB7 = word7 / 256
SYMBOL MSB8 = word8 / 256

EEPROM 2,(word1, MSB1,word2, MSB2,word3, MSB3,word4, MSB4,word5, MSB5,word6, MSB6,word7, MSB7,word8, MSB8)


Symbol pauseTime = w0
Symbol eeaddr = w1
Symbol eestart = w2
Symbol eeend = w3

eestart = 0
eeend = 16
eeaddr = eestart

let dirsB = %00000000
let dirsC = %10111111


Setpinslow:
let pinsC = %00000000
goto keyscan:

keyscan:
if pinsB = %00000000 then Setpinslow
if pinB.3 = 1 then HighCW
'if pinB.4 = 1 then HighCCW
'if pinB.5 = 1 then LowCW
'if pinB.6 = 1 then LowCCW
'if pinB.7 = 1 then TrackCCW

goto keyscan:

HighCW:
let pinsC = %00111011 'set enable high and DIR high
Do
 Select Case eeaddr
Case < eeend : eeaddr = eeaddr + 2
read eeaddr, word pauseTime
 End Select
 Toggle C.2
  PauseUs pauseTime
  sertxd (#w0)
  if pinB.3 = 0 then Decel:
Loop
goto keyscan:

Decel:
Do
 Select Case eeaddr
Case > eestart : eeaddr = eeaddr - 2
read eeaddr, word pauseTime
 Toggle C.2
  PauseUs pauseTime
 End Select
  sertxd (#w0)
  Loop until eeaddr = eestart
  let pinsC = %00000000
  eeaddr = eestart
goto keyscan:
 

alistairsam

Senior Member
I carried out some fairly extensive tests with stepper motors and unfortunately, all approaches of code with pause, pauseus and toggle could not generate frequencies higher than 460Hz even with the clock set to 16Mhz.

so i had to go back to using pwmout and to test acceleration, used a static list of different pwmout values incrementing frequency from 500hz to 41Khz.
this is working well. i was able to ramp it up to 41Khz. this is using 1/16th microstepping.
not sure if there is any other way other than pwmout to generate this freq range or if it can be calculated. I don't need to ramp from lower than 500Hz.

also added a counter when there are no button depresses to set the mcu to sleep if there is no input for a few minutes as this will be battery operated.
is the settimer the other way of doing this?

have uploaded a video here

http://www.youtube.com/watch?v=oO68oe5R-Ws

Code:
'28x2
' picaxe pin assignment for stepper driver inputs
' enablepin = pinC.0
' Dirpin = pinC.1  -> High - CCW, Low - CW
' Clckpin = pinC.2
' MS0pin = pinC.3
' MS1pin = pinC.4
' MS2pin = pinC.5

' Full stepping - MS0,MS1,MS2 low  -> for high speed
' 1/16th stepping - MS0, MS1, MS2 high - for tracking speed
' 1/8th stepping - MS0 high, MS1 high, MS2 low - for low speed slew

setfreq m16

let dirsB = %00000000

Setpinslow:
pwmout C.2,off
let dirsC = %10111111
let pinsC = %00000001
goto keyscan:

Symbol BB = w5

keyscan:
Do
for BB = 1 to 50000 step 1
pause 100
if pinsB = %00000000 then scan2

scan2:
if pinB.3 = 1 then highCW
if pinB.4 = 1 then HighCCW
if pinB.5 = 1 then LowCW
if pinB.6 = 1 then LowCCW
if pinB.7 = 1 then TrackCW
if BB = 10000 then goto slp
next BB
Loop

slp:
sleep 0


HighCW:
pauseus 5000
if pinB.3 = 0 then Setpinslow:
let pinsC = %00111000 'set enable low and DIR low, 1/16 step
gosub pwroutine
pauseus 500
Do
if pinB.3 = 0 then Setpinslow:
pwmout C.2, 110, 222
Loop


HighCCW:
pauseus 5000
if pinB.4 = 0 then Setpinslow:
let pinsC = %00111010 'set enable low and DIR high, 1/16 step
 gosub pwroutine
pauseus 500
Do
if pinB.4 = 0 then Setpinslow:
pwmout C.2, 110, 222
Loop



LowCW:
pauseus 5000
let pinsC = %00111000 'set enable low and DIR low, 1/16th step
Do
  if pinB.5 = 0 then Setpinslow:
  Toggle C.2
  PauseUs 10
 Loop

LowCCW:
pauseus 5000
let pinsC = %00111010 'set enable low and DIR high, 1/16th step
Do
if pinB.6 = 0 then Setpinslow:
Toggle C.2
 PauseUs 10
Loop


TrackCW:
pauseus 5000
let pinsC = %00111000 'set enable low and DIR low, 1/16th step
Do
if pinB.7 = 0 then Setpinslow:
 Toggle C.2
 Pauseus 500
Loop


pwroutine:
pwmout pwmdiv16, C.2, 249, 500
pauseus 3000
pwmout pwmdiv16, C.2, 124, 250
pauseus 3000
pwmout pwmdiv16, C.2, 82, 167
pauseus 3000
pwmout pwmdiv4, C.2, 249, 500
pauseus 3000
pwmout pwmdiv4, C.2, 199, 400
pauseus 3000
pwmout pwmdiv4, C.2, 166, 333
pauseus 3000
pwmout pwmdiv4, C.2, 142, 286
pauseus 3000
pwmout pwmdiv4, C.2, 124, 250
pauseus 3000
pwmout pwmdiv4, C.2, 110, 222
pauseus 3000
pwmout pwmdiv4, C.2, 99, 200
pauseus 3000
pwmout pwmdiv4, C.2, 90, 182
pauseus 3000
pwmout pwmdiv4, C.2, 99, 200
pauseus 3000
pwmout pwmdiv4, C.2, 90, 182
pauseus 3000
pwmout pwmdiv4, C.2, 82, 167
pauseus 3000
pwmout pwmdiv4, C.2, 76, 154
pauseus 3000
pwmout pwmdiv4, C.2, 70, 143
pauseus 3000
pwmout pwmdiv4, C.2, 66, 133
pauseus 3000
pwmout C.2, 249, 500
pauseus 3000
pwmout C.2, 234, 471
pauseus 3000
pwmout C.2, 221, 444
pauseus 1500
pwmout C.2, 210, 421
pauseus 1500
pwmout C.2, 199, 400
pauseus 1500
pwmout C.2, 189, 381
pauseus 1500
pwmout C.2, 181, 364
pauseus 1000
pwmout C.2, 173, 348
pauseus 1000
pwmout C.2, 147, 296
pauseus 500
pwmout C.2, 166, 333
pauseus 500
pwmout C.2, 159, 320
pauseus 500
pwmout C.2, 153, 308
pauseus 500
pwmout C.2, 147, 296
pauseus 500
pwmout C.2, 137, 276
pauseus 500
pwmout C.2, 132, 267
pauseus 500
pwmout C.2, 128, 258
pauseus 500
pwmout C.2, 124, 250
pauseus 500
pwmout C.2, 120, 242
pauseus 500
pwmout C.2, 117, 235
pauseus 500
'pwmout C.2, 110, 222
'pauseus 1000
'pwmout C.2, 107, 216
'pauseus 1000
'pwmout C.2, 104, 211
'pauseus 1000
'pwmout C.2, 102, 205
'pauseus 1000
'pwmout C.2, 99, 200
'pauseus 1000
'pwmout C.2, 97, 195
'pauseus 1000
'pwmout C.2, 94, 190
'pauseus 1000
'pwmout C.2, 94, 190
'pauseus 1000
'pwmout C.2, 92, 186
'pauseus 1000
'pwmout C.2, 90, 182
'pauseus 1000
'pwmout C.2, 88, 178
'pauseus 1000
'pwmout C.2, 86, 174
'pauseus 1000
'pwmout C.2, 84, 170
'pauseus 1000
'pwmout C.2, 82, 167
'pauseus 500
'pwmout C.2, 81, 163
return
 
Last edited:

alistairsam

Senior Member
I've modified the code to one that calculates pwmout and duty values rather than use a static list.
this is working better and acceleration is quite smooth. code below ramps from 500Hz approx to 25Khz approx in around 80 stages. takes around a second and a half for the stepper to reach full speed. I chose a duty cycle of 20%.
I found the formulae for calculating period and duty from this forum.
I found that with no load, 25Khz at 1/16 ustepping is the max step freq after which the motor stalls, but with load, the step freq can go upto 46Khz.

It has some flexibility where the max freq can be varied and defined with the duty cycle initially, and it changes between pwdiv16,4 depending on the maxfreq chosen.
have'nt noticed any discernable glitches when switching from pwdiv16 to 4
have verified these values using the values from the wizard, and they're very close.

only bit left is the sleep and hint.
if i use the hint pins for the 28X2, B.0 and B.1 instead of B.3 and B.4 as input pins, once the mcu has entered sleep state, can B.0 or B.1 be used to reset or revert to active state by momentarily pulling it high? will it work in the simulator?

that way, my handheld controller won't need a seperate reset switch to wake it.


Code:
'28x2
' picaxe pin assignment for stepper driver inputs
' Stepper Driver - Allegro A4983 driver 
' High speed slew below uses 1/16 micro stepping
' enablepin = pinC.0
' Dirpin = pinC.1  -> High - CCW, Low - CW
' Clckpin = pinC.2
' MS0pin = pinC.3
' MS1pin = pinC.4
' MS2pin = pinC.5

' Full stepping - MS0,MS1,MS2 low  -> for high speed
' 1/16th stepping - MS0, MS1, MS2 high - for tracking speed
' 1/8th stepping - MS0 high, MS1 high, MS2 low - for low speed slew

setfreq m8

Symbol BB = w0
'Symbol percal1 = w1
Symbol percal2 = w2
Symbol perd = w3
Symbol Fmin = w4
Symbol Fmax = w5
Symbol F = w6
Symbol Dutyreq =w7
Symbol Duty = w8 
Symbol dutycal1 = w9
Symbol dutycal2 = w10
Symbol F2 = w11
Symbol Fdiff = w12


'Enter max freq as max freq / 10 kHz
'Enter duty as duty % * 10

let dirsB = %00000000
let Dutyreq = 300
let Fmin = 50
let Fmax = 2400


Setpinslow:
pwmout C.2,off
let dirsC = %10111111
let pinsC = %00000001
goto keyscan:


keyscan:
Do
for BB = 1 to 40000 step 1
pause 100
if pinB.3 = 1 then highCW
if pinB.4 = 1 then HighCCW
if pinB.5 = 1 then LowCW
if pinB.6 = 1 then LowCCW
if pinB.7 = 1 then TrackCW
if BB = 40000 then goto slp
next BB
Loop

slp:
sleep 0



HighCW:
pauseus 5000
if pinB.3 = 0 then Setpinslow:
let pinsC = %00111000 'set enable low and DIR low, 1/16 step
gosub pwroutine
Do
if pinB.3 = 0 then Setpinslow:
pwmout C.2, perd, duty
Loop


HighCCW:
pauseus 5000
if pinB.4 = 0 then Setpinslow:
let pinsC = %00111010 'set enable low and DIR high, 1/16 step
gosub pwroutine
Do
if pinB.4 = 0 then Setpinslow:
pwmout C.2, perd, duty
Loop



LowCW:
pauseus 5000
let pinsC = %00111000 'set enable low and DIR low, 1/16th step
Do
  if pinB.5 = 0 then Setpinslow:
  Toggle C.2
  PauseUs 10
 Loop

LowCCW:
pauseus 5000
let pinsC = %00111010 'set enable low and DIR high, 1/16th step
Do
if pinB.6 = 0 then Setpinslow:
Toggle C.2
 PauseUs 10
Loop


TrackCW:
pauseus 5000
let pinsC = %00111000 'set enable low and DIR low, 1/16th step
Do
if pinB.7 = 0 then Setpinslow:
 Toggle C.2
 Pauseus 500
Loop



pwroutine:

 sertxd ("Div16")
 F = Fmin
Do
 Select Case F
 Fdiff = F >> 2
 Case > 192  goto Div4
 Case < 192 : F = F + Fdiff
 End Select 
percal2 = 12504 / F
perd = percal2 - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 /10
sertxd (#w6,",",#w3,",",#w8)
pwmout pwmdiv16, C.2,perd,duty
Loop


Div4:
sertxd ("Div4")
Do
 Select Case F
 Fdiff = F >> 3
 Case > Fmax  Return
 Case > 782 goto NoDiv
 Case < 783 : F = F + Fdiff
 End Select 
percal2 = 50000 / F
perd = percal2 - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 / 10
sertxd (#w6,",",#w3,",",#w8)
pwmout pwmdiv4, C.2,perd,duty
Loop


NoDiv:
sertxd ("NoDiv")
Do
 Select Case F
 Fdiff = F >> 4
 Case > Fmax  Return
 Case < Fmax : F = F + Fdiff
End Select 
percal2 = 20000 / F 
perd = percal2 * 10
perd = perd - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 / 10
sertxd (#w6,",",#w3,",",#w8)
pwmout C.2,perd,duty

Loop

return
 
Last edited:

alistairsam

Senior Member
There is an issue with PWMOUT in that the frequencies obtainable are limited so it may not be possible to get a frequency which increases or decreases linearly and smoothly over the range you want. Switching between different PWMDIVx settings may also introduce some 'glitching' as may changing PWMOUT frequency. The underlying hardware is really designed for static frequency with variable duty rates rather than fixed duty and variable frequency.

There's also the issue that duty value must change with period value so that may have an impact on how quickly you can move from one frequency to another.
Hi hippy,

I remembered your comment on pwmout and its limitations before going down the pwmout path, but from tests, the limitations are not practically noticeable in the motor as each step freq does not have to be accurate. just the difference between each step should'nt vary too much from the previous difference.
 

hippy

Technical Support
Staff member
only bit left is the sleep and hint.
if i use the hint pins for the 28X2, B.0 and B.1 instead of B.3 and B.4 as input pins, once the mcu has entered sleep state, can B.0 or B.1 be used to reset or revert to active state by momentarily pulling it high? will it work in the simulator?
Yes, any of the HINTx pins should wake the 28X2 from SLEEP 0. Just set HINTxFLAG=0, a HINTSETUP command, then SLEEP 0.

When woken up the PICAXE will continue after the SLEEP 0 so just add a GOTO to where you want to continue from.

#Picaxe 28X2
#Terminal 9600
Do
SerTxd( "Sleeping ..." )
hInt0Flag = 0
HIntSetup %00010001 ' Wake on B.0 (HINT0) going high
Sleep 0
SerTxd( "... Awake", CR, LF )
Loop

Unfortunately that doesn't seem to work in the Simulator so we will investigate that but in the meantime, for simulating, you can replace SLEEP 0 with -

Do : Loop Until hint0Flag = 1

Glad to hear that switching PWMDIVx mode works okay. The motion of the motors is probably carrying it through the very brief glitch unnoticed which is good news.
 

alistairsam

Senior Member
Yes, any of the HINTx pins should wake the 28X2 from SLEEP 0. Just set HINTxFLAG=0, a HINTSETUP command, then SLEEP 0.

When woken up the PICAXE will continue after the SLEEP 0 so just add a GOTO to where you want to continue from.

.
Thanks. will rewire and try it out.

have modified the code to include deceleration. works well.

is it better to use the timer routine to wait for a certain period with no activity and then set to sleep rather than a for next loop like I have now? (BB in my code). from what I understood, the timer counts in the background.



Code:
'28x2
' picaxe pin assignment for stepper driver inputs
' Stepper Driver - Allegro A4983 driver 
' High speed slew below uses 1/16 micro stepping
' enablepin = pinC.0
' Dirpin = pinC.1  -> High - CCW, Low - CW
' Clckpin = pinC.2
' MS0pin = pinC.3
' MS1pin = pinC.4
' MS2pin = pinC.5

' Full stepping - MS0,MS1,MS2 low 
' 1/16th stepping - MS0, MS1, MS2 high - for tracking speed, hi and low speeds
' 1/8th stepping - MS0 high, MS1 high, MS2 low

'pwmdiv ranges @ 8Mhz
'pwmdiv 16 -> 500 - 1940 Hz
'pwmdiv 4 -> 1950 - 7800 Hz 

setfreq m8

Symbol BB = w0
Symbol percal2 = w2
Symbol perd = w3
Symbol Fmin = w4
Symbol Fmax = w5
Symbol F = w6
Symbol Dutyreq =w7
Symbol Duty = w8 
Symbol dutycal1 = w9
Symbol dutycal2 = w10
Symbol F2 = w11
Symbol Fdiff = w12


'Enter max freq as max freq / 10 kHz
'Enter duty as duty % * 10

let dirsB = %00000000
let Dutyreq = 300
let Fmin = 50
let Fmax = 2400


Setpinslow:
pwmout C.2,off
let dirsC = %10111111
let pinsC = %10000001 'Turn LED on C.7 on, Enable off
goto keyscan:


keyscan:
Do
for BB = 1 to 10000 step 1
pause 100
if pinB.3 = 1 then highCW
if pinB.4 = 1 then HighCCW
if pinB.5 = 1 then LowCW
if pinB.6 = 1 then LowCCW
if pinB.7 = 1 then TrackCW
if BB = 10000 then goto slp
next BB
Loop



HighCW:
pauseus 5000
if pinB.3 = 0 then Setpinslow:
let pinsC = %10111000 'set enable low and DIR low, 1/16 step
gosub pwroutine
Do
if pinB.3 = 0 then Decel:
pwmout C.2, perd, duty
Loop


HighCCW:
pauseus 5000
if pinB.4 = 0 then Setpinslow:
let pinsC = %10111010 'set enable low and DIR high, 1/16 step
gosub pwroutine
Do
if pinB.4 = 0 then Decel:
pwmout C.2, perd, duty
Loop



LowCW:
pauseus 5000
let pinsC = %10111000 'set enable low and DIR low, 1/16th step
Do
  if pinB.5 = 0 then Setpinslow:
  Toggle C.2
  PauseUs 10
 Loop

LowCCW:
pauseus 5000
let pinsC = %10111010 'set enable low and DIR high, 1/16th step
Do
if pinB.6 = 0 then Setpinslow:
Toggle C.2
 PauseUs 10
Loop


TrackCW:
pauseus 5000
let pinsC = %10111000 'set enable low and DIR low, 1/16th step
Do
if pinB.7 = 0 then Setpinslow:
 Toggle C.2
 Pauseus 500
Loop



pwroutine:

 sertxd ("Div16")
 F = Fmin
Do
 Select Case F
 Fdiff = F >> 2
 Case > 186  goto Div4
 Case < 187 : F = F + Fdiff
 End Select 
percal2 = 12504 / F
perd = percal2 - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 /10
sertxd (#w6,",",#w3,",",#w8)
pwmout pwmdiv16, C.2,perd,duty
Loop


Div4:
sertxd ("Div4")
Do
 Select Case F
 Fdiff = F >> 3
 Case > Fmax  Return
 Case > 758 goto NoDiv
 Case < 759 : F = F + Fdiff
 End Select 
percal2 = 50000 / F
perd = percal2 - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 / 10
sertxd (#w6,",",#w3,",",#w8)
pwmout pwmdiv4, C.2,perd,duty
Loop


NoDiv:
sertxd ("NoDiv")
Do
 if pinB.3 = 0 and pinB.4 = 0 then Decel
 Select Case F
 Fdiff = F >> 5
 Case > Fmax  Return
 Case < Fmax : F = F + Fdiff
End Select 
percal2 = 20000 / F 
perd = percal2 * 10
perd = perd - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 / 10
sertxd (#w6,",",#w3,",",#w8)
pwmout C.2,perd,duty

Loop

return


Decel:
sertxd ("decel")
Do
 Select Case F
 Fdiff = F >> 4
 Case < 790 goto Setpinslow
 Case > 790 : F = F - Fdiff
End Select 
percal2 = 20000 / F 
perd = percal2 * 10
perd = perd - 1
dutycal1 = Dutyreq / 25
dutycal2 = perd + 1
duty = dutycal1 * dutycal2 / 10
sertxd (#w6,",",#w3,",",#w8)
pwmout C.2,perd,duty
Loop


     
slp:

hInt0Flag = 0
HIntSetup %00010001 ' Wake on B.0 (HINT0) going high
let pinsC = %00000001
disablebod
Sleep 0
'Do : Loop Until hint0Flag = 1
enablebod
goto setpinslow
 
Last edited:

hippy

Technical Support
Staff member
It doesn't really matter whether you are counting time or using the background timer, so I'd go with what you have as it's working.
 

alistairsam

Senior Member
#Picaxe 28X2
#Terminal 9600
Do
SerTxd( "Sleeping ..." )
hInt0Flag = 0
HIntSetup %00010001 ' Wake on B.0 (HINT0) going high
Sleep 0
SerTxd( "... Awake", CR, LF )
Loop
Hi,
the syntax of the Hintsetup command in the manual shows the input mask can be either one or more of the 3 hint pins, but in your code above, the 5th pin is 1. what does this do? is it possible to wake on interrupt from either pin B.0 or pin B.1 ?

if I set an output pin high for an LED at the start of the program, will it turn off when in sleep? manual says timers, servo and pwmout will be disabled. what happens to output pin states?

I have a 15V supply for my motor, was thinking of using a resistor to step it down to 7V and then use a 7805 regulator for the picaxe supply.
can the max current be taken as 90ma? in that case the resistor value would be
R = 8 / 0.09 (15v - 7v = 8v)
R = 90 ohm

P = 8 x 0.09 = 1watt approx.

would this be correct?
problem would be if the current drawn varies, then voltage drop would also vary and the 7805 will start heating up. else I can calculate based on a lower current draw, and if the draw increases, the voltage drop would also increase, but should be within limits of the 7805.

can I use an external 8Mhz resonator? if so, would the setfreq command be
setfreq em32
manual 1 says external resonators can be 4(=14), 8(=32) or 10(=40), but the setfreq syntax says external starts from em16 for a 16Mhz external resonator. since setfreq defines internal clock and it has a 4XPLL, would'nt an 8Mhz external require an em32 command?
 
Last edited:

hippy

Technical Support
Staff member
the syntax of the Hintsetup command in the manual shows the input mask can be either one or more of the 3 hint pins, but in your code above, the 5th pin is 1. what does this do?
The lower 4-bits define which HINT pins are enabled, the upper 4-bits define whether rising edge or falling edge sets the appropriate HINTxFLAG.

is it possible to wake on interrupt from either pin B.0 or pin B.1 ?
Yes, any of the enabled HINTx pins will cause a wake-up.

if I set an output pin high for an LED at the start of the program, will it turn off when in sleep? manual says timers, servo and pwmout will be disabled. what happens to output pin states?
Off-hand I cannot recall; I'd have to test that, or you could.

I have a 15V supply for my motor, was thinking of using a resistor to step it down to 7V and then use a 7805 regulator for the picaxe supply.
can the max current be taken as 90ma? in that case the resistor value would be
R = 8 / 0.09 (15v - 7v = 8v)
R = 90 ohm

P = 8 x 0.09 = 1watt approx.

would this be correct?
That sounds correct.

problem would be if the current drawn varies, then voltage drop would also vary and the 7805 will start heating up.
That's correct. Simple resistors are not recommended for dropping voltages.

can I use an external 8Mhz resonator? if so, would the setfreq command be
setfreq em32
Yes, that's correct.
 

alistairsam

Senior Member
if I use an external 8Mhz resonator, what clock frequency should I choose while calculating values using the pwmout wizard, 8 or 32 Mhz?
 

hippy

Technical Support
Staff member
The Wizards should be set for chip operating speed, so 8MHz external crystal with 4 x PLL means it's actually 32MHz, so 'SETFREQ EM32" and 32MHz in the Wizards.
 
Top