stepper control with acceleration and variable freq square wave output

alistairsam

Senior Member
Hi,

I needed help with writing code for a stepper control application that includes acceleration and deceleration, and the option of different square wave outputs to send to a seperate stepper driver depending on keypad selections.

(I'm completely new to picaxe's)

I need the picaxe to just output square waves as I have a dedicated stepper driver.

Is it an incorrect approach to use a simple for next loop to increase the time as a variable in a pulsout command thereby providing linearly increasing pulse freq to an external stepper driver.


for example,

for a 1Hz square wave, the o/p pin would have to be high for 500msec and low for 500msec.

so for 30Hz, that would be 500/30 = 16600 usec (pulsout 1,16600)
and for 1500Hz, that would be 500/1500 = 330 usec (pulsout 1,330)

so if a variable is used for the value of "time", would something like the following work?

Code:
FOR PL=16600 to 330 step -10
pulsout 1,PL
next PL
pulsout 1,330
so the pulsewidth would start at 16600, and then reduce to 330usecs in steps of 10. thats 50 steps. might be too small. but just trying to understand the concept.

I'll be using a 14M Picaxe at 4MHz

I have a keypad encoder that can output 5 bit nibbles, so if that is connected to the picaxe input pins, can the bits at 3 pins be monitored every few msecs to call 3 different subroutines, with each subroutine coded to output a set freq with acceleration?
 

lanternfish

Senior Member
Hi Alistai

Have a read up on the PWM command (which I haven't had to use other than the most basic experimentation) in Manual 2 . And have search of the forums for PWM. Lots of good info there.
 

lanternfish

Senior Member
Missed the last question.

Shouldn't be a problem. And you can use the SELECT CASE command to select the appropriate actioning routine.
 

alistairsam

Senior Member
Thanks. will check PWM.

But how can I monitor the state of 3 inputs simultaneously.
for eg.

if i/p pins are 5 to 0,
for state 00001, call subroutine1,
for state 00010, call subroutine2,
for state 00011, call subroutine3

I'd need to check the state of these pins every 50msecs or so, just not sure how to arrive at a decision based on the states of 3 pins at any one instant.

I can't have it check pin by pin as after checking pin1, whilst checking pin2, the value of pin1 can change.
 

donrecardo

Senior Member
But how can I monitor the state of 3 inputs simultaneously.
for eg.

if i/p pins are 5 to 0,
for state 00001, call subroutine1,
for state 00010, call subroutine2,
for state 00011, call subroutine3

I'd need to check the state of these pins every 50msecs or so, just not sure how to arrive at a decision based on the states of 3 pins at any one instant.

I can't have it check pin by pin as after checking pin1, whilst checking pin2, the value of pin1 can change.

How about something like

If pin1= this and pin2 = that and pin3 = the other then
do something
elseif
pin1 = that and pin2= this and pin3 = the other then
do something else
elseif
etc
etc etc

Don
 

alistairsam

Senior Member
thanks. will check it out.
I have'nt got delivery of the chip as yet but I'm guessing it can be simulated.

Can we use an external crystal with the 14M instead of the internal clock, just that my application needs reasonably high accuracy and I read here that there will be slight variation if using the internal clock.
 

MPep

Senior Member
Use the simulator, works well.

In the simulator, I quickly conjured this up :). A simple example showing how to read input PINs, masking (so only those pins you are interested in reading are indeed being read), and displaying the result in the serial terminal.
Code:
#picaxe 14m

Main:
    b0 = pins & %00000111
    sertxd (#b0, CR, LF)
    pause 500
goto Main
MPep

Edited: How you use the value in B0 is upto to you.
 
Last edited:

hippy

Ex-Staff (retired)
Using PULSOUT should work for generating a pulse between 16600us and 330us, however that will only generate the high of the square wave. To generate the low part you need to have a delay of the same width. Notionally a dummy PULSOUT to an unused pin will do that but there are a few problems.

Each PICAXE command takes time to execute so the period of this dummy pulse has to be less than the real PULSOUT, and at slow (4MHz) speeds the PICAXE commands can add up to a longer period than the required low period time. That can be compensated for by running the PICAXE faster but 14M is limited to 8MHz.

To keep stepping you need to continually generate the square wave and if doing that any handling of button pushes etc will extend the low period of the square wave and alter its frequency. To generate a perfect square wave will probably require PWMOUT but that does not extend down to 30Hz. You may therefore need a means of bit-banging the square wave for low frequencies then switching to PWMOUT for higher frequencies. Switching between the two seamlessly may create some issues and may take a bit of effort to avoid any glitches.

The 14M cannot use a crystal, you'd need to go to a 28X1 or 28X2. That will also provide for a larger memory capacity which may be required if you need more code to handle switching between bit-banged and PWMOUT square waves. Those also provide the PAUSEUS command which may allow a completely bit-banged solution.

I'd personally consider using a 28X1 or 28X2 as a smart peripheral to generate the square wave from a serial byte sent to it from another PICAXE which handles button pushes. That would simplify the software side of things.

It's perhaps a quite challenging project for a first time user of PICAXE and a decent scope or logic analyser will likely be essential to get the timing spot-on.
 

alistairsam

Senior Member
hi,

thanks for that.

I read that the 14M cannot go below 240Hz with the pwmout command, but that should be fine as I can use an external frequency divider to reduce it down.
but i noticed that the lower frequencies need the pwdivide command. not sure upto what value the pwdivide is required for.
i have'nt really understood the pwmout command, so will do some more reading.

I'm using an external key encoder chip to handle button selection, debounce etc, so all that is presented to the picaxe input pins would just be a 2 bit nibble which can be used to select one of 3 appropriate pwmout subroutines.

one thing I could do (if possible) is that I can dedicate a seperate input pin as an interrupt input, and when that pin goes high (high as long as the button is held down), the pwmout routine would stop and check the state of the 3 pins.
(not sure if this requires a periodic check of any register or flag)

my key encoder can output a 5 bit nibble. if i'm using 2 bits for selecting subroutine selection (which in turn designate a freq selection), one bit can be used for interrupt.

given this scenario, if a key is pressed, the 2 i/p pins are set to a 2 bit word and start executing a subroutine. once it starts, it should'nt need to do anything else.
if another key is depressed, that would raise an interrupt, i/p pins checked again and the appropriate subroutine executed.

not sure how practical this is, but it seems straightforward enough. any suggestions?
 

alistairsam

Senior Member
Use the simulator, works well.

Code:
#picaxe 14m

Main:
    b0 = pins & %00000111
    sertxd (#b0, CR, LF)
    pause 500
goto Main
MPep

Edited: How you use the value in B0 is upto to you.
Hi,

do the bits in b0 correspond to the state of the input pins, if so, does'nt the 14M have only 5 inputs?
so would it be
b0 = pins & %00111
?
 

hippy

Ex-Staff (retired)
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.

The input pin handling, though it may impact on the solution, is a secondary issue at the moment with how to generate the variable frequency square wave the main issue. We don't really have the 'big picture' overview so it's a bit hard to give more detailed advice. What is the actual frequency range required, how accurate must that be, how smoothly and quickly must it change frequency, is the square wave continuous or does it ramp up and down and then cease etc ?
 

alistairsam

Senior Member
Hi,

to answer your questions

"What is the actual frequency range required, how accurate must that be, how smoothly and quickly must it change frequency, is the square wave continuous or does it ramp up and down and then cease etc ? "
the actual freq range reqd is from 30Hz to 2Khz. but as mentioned, I can use frequency dividers, so if a multiple of 8 is used, that would be from 240 Hz to 16khz.

the linear ramp from low to high is to accelerate a stepper motor, so ideally it would need to go from 0 to 2Khz in around 2 seconds.

the acceleration is so I can drive the stepper to higher revs from standstill as its inertial load in my application is high.
the ramp up does not need to be very smooth. as long as its not too far apart, mechanical inertia (with a flywheel), should compensate.

so one button depress would accelerate from 0 to 2Khz and stay at 2 as long as its depressed. deceleration would be good when released, but its not critical.

second button would just output a fixed low frequency of around 250Hz.

third button would again be a low frequency of around 500Hz.

all this is for a telescope drive.

I've posted a video of a working circuit I designed using discrete digital components here.

http://www.youtube.com/watch?v=ldKXewyt7X8

I've attached a block diagram of this circuit. I'm using a keypad encoder for the Mux channel selection (not shown in diag, ignore dir circuit).

I know this is not an electronics forum, so won't delve too deep, but basically while the circuit is working fine, I don't have acceleration, so I can't get the motor to rev at higher speeds than with 1.5Khz clock pulses.

I've seen videos on youtube where steppers are driven at very high speeds with acceleration, hence the change to microcontrollers, and I'm new to mcu's, hence the picaxe.

if the pulsout or pwmout commands have problems in this application, can a simple loop as below be used.
i have'nt done any calculations, just an idea.

for b0= 16600 to 330 step -10
high 1
pause b0
low 1
pause b0
next b0
 

Attachments

alistairsam

Senior Member
found a site with a pic based program but dont undersand the concept and whether the same principle with accumulators can be used with a picaxe in a smaller scale



http://www.buildlog.net/pic/pic_basic_motion.html

"Before each move, you pre-calculate a bunch of things to keep the math very simple inside the engine. You will then have values of acceleration and maximum speed per engine tick. Inside the engine you have an accumulator that counts the distance to move at each engine tick. You just add the acceleration to the current speed and add the current speed to the distance. The move per tick is always less that one, so it will take several ticks before you add up to a full step. At that point you take the step. To avoid using floating point values which will be too slow to calculate, these numbers are all multiplied by an offset. It chose 2^24 for this. Therefore the accumulator must get to 2^24 before a step is taken. The offset is then subtracted from the accumulator and the process repeats until you reach the target.

The only two other issues the engine must deal with are max speed and deceleration. Before it add acceleration to the current speed it checks to see if it is at the maximum. It also check to see if we got to a pre calculated deceleration point and subtracts speed rather than adding it at each engine tick.
"
 

hippy

Ex-Staff (retired)
@ alistairsam : Thanks for the overview and it does help. In a 'move to here' type application certain compromises can be acceptable where they wouldn't be in a CNC machine or for a tracking telescope and that can simplify things.

The FOR-NEXT with a PAUSE is the fundamental software PWM generator, but limited by the speed of the PICAXE. At 8MHz you can probably get close to 1kHz. This also shows the non-linearity of frequency possible; at 8MHz with a PAUSE 1 you can generate a 1kHz signal, the next step up is PAUSE 2 which halves to a 500Hz signal, 333Hz for PAUSE 3 etc.

The X1's and X2's with PAUSEUS can generate much finer frequency resolutions.

In this particular application I don't think using an on-chip oscillator instead of a crystal will present you with any problems.
 

boriz

Senior Member
In principle this:
Code:
for b0= 16600 to 330 step -10
  high 1
  pause b0
  low 1
  pause b0
next b0
Should work. But the pauses will be way too long. PAUSE 1 will pause for 1 millisecond (plus a little bit for processing the command), PAUSE 16600 will pause for over 16 seconds! And the two pauses together make a cycle time of over 32 seconds!

PWMOUT would be a more practical solution, however the problem there is when you change the frequency (issue a new PWMOUT command), there will be a small glitch in the signal amounting to an extended LOW or HIGH while the command is processed, possibly causing a physical bump or twitch during the movement. And this will happen every time the frequency is changed. So for a smooth acceleration, with frequent changes, you will get frequent glitches. Also, the lowest PWMOUT frequency is about 4Khz. However there might be a solution.

See this post: http://www.picaxeforum.co.uk/showpost.php?p=40695&postcount=10

You can slow the internal Picaxe PWM clock and reduce the PWM frequency to as low as 250Hz by POKEing the T2CON register. And (I think) this can be further reduced by POKEing another register that slows the whole Picaxe clock. So you may be able to synthesise the correct frequencies directly without the need for an external divider. Also, with lower frequencies, the ‘glitch’ during PWMOUT command processing should become less significant. Allowing something like this:

Code:
For w0=10000 to 500 step -50
  Pwmout 2,250,w0
  Pause n*
Next w0
I’m guessing at the figures. You’ll have to experiment. The pause is the delay between frequency updates. It does not effect the PWM frequency. The n* figure will also need to be experimented with, EG, if the clock is divided by 16, then PAUSE 1 will take 16 milliseconds.
 

hippy

Ex-Staff (retired)
Here's a 20X2 version using PAUSEUS to ramp frequency from slow to fast. This increases frequency by a percentage (1/16th) of what the frequency was but could be any acceleration function. The numbers might need to be tweaked but it's just proof of concept.

Code:
#Picaxe 20X2
#No_Data
#No_Table

Symbol pauseTime = w0
Symbol decTime   = w1

Do
  Gosub FrequencySweep
  Pause 5000
Loop

FrequencySweep:
  pauseTime = 1660
  Do
    Toggle C.0
    PauseUs pauseTime
    decTime = pauseTime >> 4
    pauseTime = pauseTime - decTime
  Loop Until pauseTime <= 33
  Return
 

Attachments

MPep

Senior Member
Hi,

do the bits in b0 correspond to the state of the input pins, if so, does'nt the 14M have only 5 inputs?
so would it be
b0 = pins & %00111
?
Yes, the value stored in B0 does indeed = the 3 input pins. Correct on 5 inputs, you mentioned requiring 3 inputs only.
The line
Code:
b0 = pins & %00000111
indicates that it is the first 3 inputs that you want to test/check.
If you wanted inputs 0, 1, and 4 then change the binary section to %00010011.

Run it through the simulator, you'll see the value change as you enable/disable inputs. Also check what happens to the value if you toggle a pin that isn't selected in tthe bit-mask.
 

westaust55

Moderator
Not sure exactly how far you are already advanced with hardware selection, but to throw in a possible new option . . . .

Since you need acceleration and deacceleration, why not consider a Stepper Motor driver chip that includes these functions.
One such chip that I recently had a play with recently was the AMIS-30622 from ON Electronics.
See this thread: http://www.picaxeforum.co.uk/showthread.php?t=15071

A very versatile chip. It does have a max current capability of 800mA and you would need to step up to say an 18X for i2c comms.
You set the run and hold currents, the accel and deaccel rates, what position (even multiple turns in one movement) to move to and the chip does the rest for you.
 
Last edited:

alistairsam

Senior Member
Thanks for the replies. will try out all suggestions.

Is it also possible to store say 30 or 40 numerical values, possibly for a pwmout variable and read them and execute.
apparently, the acceleration profile for a stepper is not linear and there's a complex calculation involved, especially to avoid harmonics of the resonant frequency.
so if values are precalculated (including compensation for processing time) and stored in eeprom as integers and they're read and executed, the ramp up should be very smooth in theory. precalculating values will also reduce math calculation overheads.

as far as changing frequencies on button depression, I need to interrupt whichever routine is running when a particular pin goes high. can this be achieved only by periodically checking the states of the pins or is there another way of recognizing interrupts.
 

alistairsam

Senior Member
Since you need acceleration and deacceleration, why not consider a Stepper Motor driver chip that includes these functions.
One such chip that I recently had a play with recently was the AMIS-30622 from ON Electronics.
See this thread: http://www.picaxeforum.co.uk/showthread.php?t=15071
Hi,
That looks like a very versatile solution, only issue is that the motor current required is between 1.5 and 2A.
unless I use additional transistors at the output.
The weight on my scope shaft is around 20Kg, and although there is gear reduction (around 400:1) and torque at motor shaft is low, an 800ma motor may stall. but will investigate other uses. thanks.
 

alistairsam

Senior Member
The NCV-70521 handles 1.2A continuous, and has SPI bus connections.
Datasheet here
Hi,
Had a look, don't think it has programmable acceleration and deceleration like the 30622, still looking.

i have downloaded Logicator, simulation studio, yenka. are these able to simulate basic code or do they require flowcharts to be created.
are there any other simulators?
 

alistairsam

Senior Member
Here's a 20X2 version using PAUSEUS to ramp frequency from slow to fast. This increases frequency by a percentage (1/16th) of what the frequency was but could be any acceleration function. The numbers might need to be tweaked but it's just proof of concept.

Code:
#Picaxe 20X2
#No_Data
#No_Table

Symbol pauseTime = w0
Symbol decTime   = w1

Do
  Gosub FrequencySweep
  Pause 5000
Loop

FrequencySweep:
  pauseTime = 1660
  Do
    Toggle C.0
    PauseUs pauseTime
    decTime = pauseTime >> 4
    pauseTime = pauseTime - decTime
  Loop Until pauseTime <= 33
  Return
Hi,

This works quite well in the simulator (just figured out how to use it).
but can we see the value of w0 in the simulator?
I'm using ver 5.2.11. I can see the value of b0 changing, but that ranges from 0 to 255.
I will try and modify it to continue toggling at the last value below 33 instead of the pause 5000.
but is the 20x2 the lowest chip that will support pauseus?
 

hippy

Ex-Staff (retired)
20X2 is the physically smallest chip that supports PAUSEUS, 28X1, 28X2 plus 40X1 and 40X2 support PAUSEUS.
 

alistairsam

Senior Member
i guess this should toggle C.0 at the last value of pausetime below 33

Code:
#Picaxe 20X2
#No_Data
#No_Table

Symbol pauseTime = w0
Symbol decTime   = w1

  pauseTime = 1660
  Gosub FrequencySweep
Do
  Gosub FinalFrequency
Loop

FrequencySweep:
   Do
    Toggle C.0
    PauseUs pauseTime
    decTime = pauseTime >> 4
    pauseTime = pauseTime - decTime
  Loop Until pauseTime <= 33
  Return 

FinalFrequency:
    Toggle C.0
    PauseUs pauseTime
Return
 

westaust55

Moderator
Hi,

This works quite well in the simulator (just figured out how to use it).
but can we see the value of w0 in the simulator?
I'm using ver 5.2.11. I can see the value of b0 changing, but that ranges from 0 to 255.
When you start the PE simulator mode, you will have the window with the PICAXE chip arrangement or a table of the IO.
When you click the ">>" button in the bottom right, you can see the variables.

By virtual of your statement that you can "see b0 changing", I presume you are at this stage.

To see word variables there are some tick boxes at the bottom of the variables part of the window. One is for Byte and the other for Word. Check the "Word" box and you will see word variables instead of byte variables.

Think I have all that described right (I am currently not at a PC with the PE installed).
 

hippy

Ex-Staff (retired)
Your code will work and keep the output toggling. What you can do, and is often preferable, is to have a single loop and adjust the pauseTime towards a targetTime. That way the frequency will move towards the target required, up or down. Just the sekeleton for the code ...

Code:
Do
  targetTime = ???
  Select Case targetTime
    Case < pauseTime : pauseTime = pauseTime - ?
    Case > pauseTime : pauseTime = pauseTime + ?
  End Select
  Toggle C.0
  PauseUs pauseTime
Loop
Where "targetTime=?" appears you can call a subroutine or read pins to determine what the target is.
 

alistairsam

Senior Member
Hi,

I worked it out to the following code
is this what you meant

Code:
Symbol pauseTime = w0
symbol targetTime = w2


  pauseTime = 1650
  targetTime = 33


Do
    Select Case targetTime
    Case < pauseTime : pauseTime = pauseTime - targetTime
    Case > pauseTime : pauseTime = pauseTime + targetTime
  End Select
  Toggle C.0
  PauseUs pauseTime
Loop
I guess the only thing is that the target time has to be a multiple of the pausetime, then pausetime stays at the target time.

I also found the option to view contents of w0, thanks.

this is getting very interesting.


once I get this working and I know my way around, I'd like to couple this stepper motor controller, a picaxe based optical encoder that will "know" the position of the x and y axis stepper motors using quadrature encoding, and a dedicated eeprom that can store around 60000 integer values.
objective is to choose an absolute address in the external eeprom using a keypad, retrieve that value which will be an x,y co-ordinate, and send that to the microcontroller to slew motors till that x and y co-ordinate is reached.
i know this is similar to cnc operations, but I'm looking at building a dedicated hand held controller.


most of the picaxe's have internal eeprom's. can they be used to store values and be retrieved and used as values for a variable in sequence?
if so, what is the limit in terms of number of bits that can be stored per location and number of such locations or values?
 

hippy

Ex-Staff (retired)
Your modified code isn't quite right; targetTime is the time you want, pausTime is the time you currently have, in changing pauseTime you'll want to add/subtract some constant or value derived from pauseTime rather than adding/subtracting targetTime. For example ...

Code:
Do
  ReadAdc10 0, targetTime : targetTime = targetTime + 1
  Select Case targetTime
    Case < pauseTime : pauseTime = pauseTime - 1
    Case > pauseTime : pauseTime = pauseTime + 1
  End Select
  Toggle C.0
  PauseUs pauseTime
Loop
This will change the frequency depending on what a pot connected to ADC input 0 is, giving a time of 1 to 1024.

If you are adding/subtraction of more than 1 you'll want to add some over and underflow prevention ...

Case < pauseTime : pauseTime = pauseTime - ? Min targetTime
Case > pauseTime : pauseTime = pauseTime + ? Max targetTime

You'll probably want to add some means to stop the square wave as well. It's not particularly hard to do all this and more but as things are added the project grows considerably. This is why I noted it was perhaps an ambitious project for someone with no prior PICAXE experience.

It should be possible to use an opto-encoder to position to where you want but that's another level of complexity. It's also possible to store settings in Eeprom. Internal Eeprom usually gives 256 bytes, but you can store more in external I2C eeprom.

If you want X and Y control I'd suggest two separate PICAXE, one per axis. Bit-banging two channels in parallel on one PICAXE will be a lot more difficult and complex though perhaps not impossible.
 

alistairsam

Senior Member
Hi,

you're right. I should'nt be adding/subtracting targettime.
I just wanted to understand the concept first. I can then play around with what operations I need to perform to the initial value to eventually get to the target value, as that operation has to span around 1500ms, and reduce the duty cycle down to 50% once the target value is reached, and reach the target value with a certain minimum number of steps for the motor to gain sufficient angular momentum.

thats why I thought it would be more accurate to read values stored in eeprom in around 50 or more steps and use that to decrease the pause duration. those values would be based on electrical characteristics of the motor to get the right acceleration profile.
I found a link with mathematical formulae to calculate the acceleration profile values.

this is indeed ambitious for a first timer, but i've learnt so much from just this forum in two days ago where I had zero knowledge about picaxe's when i started and now I'm atleast on my way to understanding concepts first and can see how i can apply it practically in my project.

The autonomous controller that I mentioned can have two or more dedicated mcu's, and may require different mcu's. but thats part of the learning process.

I will try out this last code, see if I can upload some values to eeprom and test it out once i get the 20x2 that i've ordered.

I've modified the code to include the variable dectime

Code:
Symbol pauseTime = w0
Symbol dectime = w1
symbol targetTime = w2


  pauseTime = 1650
  targetTime = 33


Do
    Select Case targetTime
    decTime = pauseTime >> 4
    Case < pauseTime : pauseTime = pauseTime - decTime
    Case > pauseTime : pauseTime = pauseTime + decTime
  End Select
  Toggle C.0
  PauseUs pauseTime
Loop
 

alistairsam

Senior Member
These links explains calculation of different parameters to create a stepper motor acceleration profile

http://www.embedded.com/columns/technicalinsights/56800129?_requestid=535204

http://www.atmel.com/dyn/resources/prod_documents/doc8017.pdf

While these are meant to generate profiles in real time, they require fairly complex calculations.

since my acceleration profile need not be very accurate and as I'd like to keep it as simple as possible, i thought it would be easier to compute these values, store them in eeprom, and read them in sequence for the pausetime variable using a loop. this would also reduce processing overheads.
moreover, once these values are established, they would not need to change even with varying motor load as gear reduction and flywheel compensate for slight variations in torque requirement.

not sure how practical this approach would be though.
 

hippy

Ex-Staff (retired)
The maths is beyond me but, yes, it's certainly possible to have an array of pauseTime's and step through them for acceleration and deceleration.

When going from point A to point B it should be fairly easy to keep track of where you need to read from in that array and to determine whether you should be accelerating or decelerating.

Even with less than optimal acceleration and deceleration curves it should be possible to produce proof of concept code which works.
 

westaust55

Moderator
If you understand some basics of the C language then manual conversion to PICAXE BASIC is possible.

But here is a thread on the PICBASIC website that may be easier for you to understand and work from:
http://www.picbasic.org/forum/showthread.php?t=4900

There are the usual problems of links to externale websites that are now broken but there are some BASIC program extracts that may help you in the above referenced thread.
 

alistairsam

Senior Member
Hi,

Following the last working code, I came up with the code below.

just to warn you'll, its based on an understanding of BASIC programming learnt in 3 days, so please pardon the stone age approach. just trying to improvise slowly.

I'm basically planning on connecting 5 momentary spst switches to 5 input pins C.0 to C.5, and as long as each is depressed and held, it will execute the routine meant for that button.
But once the button is released, it should go to a deceleration routine which at this stage is an attempt to reverse the acceleration routine, and then disable all outputs and keep scanning for key presses.
I have'nt accounted for keybounce as yet.

I read through and tried interrupts, but that would require a seperate input to be toggled. in my case, there is only one input at any time, hence I'm checking the state of the input pins at the end of each loop.

is there any way to simplify or optimize this code.

is it possible to mathematically reverse the value of pausetime as its progressively decreasing toward targettime from any step?



Code:
' enablepin = pinC.0
' Dirpin = pinC.1
' Clckpin = pinC.2
' MS0pin = pinC.3
' MS1pin = pinC.4
' MS2pin = pinC.5


Symbol pauseTime = w0
Symbol dectime = w1
symbol targetTime = w2
Symbol Pauseinit = w3
Symbol targetinit = w4

Pauseinit = 1650
targetinit = 33  
pauseTime = Pauseinit
targetTime = targetinit

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

goto keyscan:

HighCW:
let pinsC = %00000011
Do
    Select Case targetTime
    decTime = pauseTime >> 4
    Case < pauseTime : pauseTime = pauseTime - decTime
    Case > pauseTime : pauseTime = pauseTime + decTime
  End Select
  Toggle C.0
  PauseUs pauseTime
  if pinB.3 = 0 then Decel:
Loop
goto keyscan:

HighCCW:
let pinsC = %00000100
high C.4
pause 400
low C.4
goto keyscan:



Decel:
let pinsC = %00000011
Do
    Select Case targetTime
    decTime = pauseTime << 4
    Case < pauseTime : pauseTime = pauseTime + decTime
    Case > pauseTime : pauseTime = pauseTime - decTime
  End Select
  Toggle C.0
  PauseUs pauseTime
  Loop until pauseTime = pauseTime
  let pinsC = %00000000
  pauseTime = Pauseinit
  targetTime = targetinit
 goto keyscan:
 

westaust55

Moderator
is it possible to mathematically reverse the value of pausetime as its progressively decreasing toward targettime from any step?
do you mean something like this:

Code:
FOR b0 = 0 TO 255
b1 = 255 - b0
PAUSE b1 ; the pause time reduces as b0 increases. b0 could be acceleration/speed
NEXT b0
 

alistairsam

Senior Member
Hi,

thats a simple but effective method.
what i meant was that in looped calculation below, the values generated can't be "traced back" in the opposite direction by reversing the operation.

in this case, pausetime goes through the following values

1650 1547 1451 1361 1276

so, if the button is released before it reaches target time, pausetime needs to increment to the same values in each step.
it does'nt work by shifting by 4 bits left which should not be too surprising.

I guess an easy way out is to store the values i want in eeprom and read them. that way, i can have a simple for next loop like in your code just to change the address bit and retrieve the code, and to decelerate, just read the values in the opposite direction. that way, no math operation, and i can have two sequences, one for acceleration and one for deceleration as both profiles are different.

will try it out.

I need to handle keybounce as well.


Code:
Pauseinit = 1650
targetinit = 33  
pauseTime = Pauseinit
targetTime = targetinit
 Do
    Select Case targetTime
    decTime = pauseTime << 4
    Case < pauseTime : pauseTime = pauseTime + decTime
    Case > pauseTime : pauseTime = pauseTime - decTime
  End Select
  Toggle C.0
  PauseUs pauseTime
  Loop until pauseTime = targetinit
pausetime is
 

alistairsam

Senior Member
eeprom values

Hi,

I'm trying to store numbers using the eeprom command.
but is the largest number that can be stored 255?

the manual says

EEPROM {location},(data,data...)
- Data are constants (0-255) which will be stored in the EEPROM.

so can "Data" range only from 0 to 255? how do I store numbers from 0 to 65535 in eeprom

Thanks
 

westaust55

Moderator
A byte (8-bit) variable (eg b5 ) can only hold values from 0 to 255
A word (16-bit) variable (eg w3) can hold values from 0 to 65535.

As byte and word variables overlap, for example from the start
W0 = b1:b0 and w1 = b3:b2

So if you have a value like 32456 in w1 then to save to EEPROM
WRITE <location>, (b2, b3)​
Which will put the least significant byte (b2) in the EEPROM location specified and the most significant bytes (b3) in the next EEPROM location

now with 32456 in w1, you will find that b3 = 126 and b2 = 200. (b3 * 256 + b2 = w1 :) )
 
Last edited:
Top