simple SX/B example of timed use?
Ok, I'm lost again as usual trying to update my project and bring it to a final clean state of being. What I want to do is take the pause statements out of a program and just use timing to continiously loop through. I understand the concept in theory to the point where I can get·a 10hz signal without pausing but what I need to do is turn a solenoid on and off while continiously increasing the on time, and decreasing the off time so that it maintains 10hz frequency but the duty cycle increases with time.
So, 10 cycles per second starting with say a 10% duty cycle, and ending with a 95% duty cycle at which point it simply locks on as long as input signal is maintained. On top of all that I need to be able to adjust the rate that it changes duty cycle so that I can control the period that it takes to transit from 10-95% over a range of .5 seconds or 5 pulses to 7.5 seconds or 75 pulses without pausing the program.
I'm not asking anyone to solve this for me, just point me in the right direction to an example that may help if you could.
Thanks in advance,
Chris
So, 10 cycles per second starting with say a 10% duty cycle, and ending with a 95% duty cycle at which point it simply locks on as long as input signal is maintained. On top of all that I need to be able to adjust the rate that it changes duty cycle so that I can control the period that it takes to transit from 10-95% over a range of .5 seconds or 5 pulses to 7.5 seconds or 75 pulses without pausing the program.
I'm not asking anyone to solve this for me, just point me in the right direction to an example that may help if you could.
Thanks in advance,
Chris

Comments
what you describe can also be seen as a PWM (Pulse Width Modulated) signal, starting with a relatively short duty cycle, increasing along a timed ramp until a 95% or even 100% duty cycle (for aways on) is reached.
Usually, PWM signals are generated at higher frequencies but there is no reason why you should not generate one at 10 Hz - it is just a matter of timing. I'm not an SX/B expert but to my understanding you can't use SX/B's PWM function for this purpose as its frequency is too high and it can't be contolled by a parameter (besides the port pin, there are only parameters for the duty cycle, and the duration of the PWM signal).
So you will have to "hand-code" this one. In principle, you would need a counter (let's call it the PWM accumulator, or PWMA). In a constant timed loop, or better within an ISR, starting with 0, the PWMA would be incremented every 391 µs. That is, after 256 * 391 µs it would roll over to zero, i.e. after 100.1 µs which is the period of approx. 10 Hz.
Another variable is used to hold the duty cycle - let's call it DUTY. Whenever the PWMA is incremented, its new contents is compared against DUTY. When it is greater than DUTY, the PWM output pin is cleared to low otherwise, the output pin is set to high. The greater the value in DUTY is, the longer will the PWM output pin stay high. After the PWMA has rolled over, the next PWM cycle automatically begins.
In order to implement a ramp, you need to set DUTY to 0 at start-up, and then increment it periodically until it holds the value for the maximum duty cycle you need.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Greetings from Germany,
Günther
Have a look in the Projects section on the forums, and see Beans SX/B Servo/PWM controller.
Might help
James
I thought your requirements to be an excellent example of how to use a simple (non-preemptive) RTOS, so I coded up your program for you so others could see the benfit of using such a time-structured approach.
But because I am somewat SX/B illiterate and for efficiency,·I wrote it in my favourite......assembler.
Please do understand this is just one particular implementation; there are MANY ways to skin this cat....only one example is given. And not necessarily the best or fastest or shortest, just something with LOTS of comments so many people can more easily follow it.
The main thing to understand is the scheduler. The interrupt sets a flag every 5 uSec, and the main loop simply waits for that to occur. Then all heck breaks loose. I have somewhat arbitrarily·chosen the scheduler to have 100 uSec, 1mSec, 10 mSec, 100 mSec and 1 Sec time ticks to run the various tasks that are required in·THIS rendition. Actually some of those ticks are not directly used, so they might be combinable with other time ticks. However, their inclusion does not hurt, and for generality it demonstrates the RTOS better.
Each of those ticks is triggered by counting off the decade of faster ticks above it. They need not necessarily be what I chose, but, hey, I like nice numbers.
So, every 1 millisecond I call the·RAMPER that controls how fast the duty cycle changes from minimum to maximum; I call the CYCLERUNCHECK to see if the input conditions (rb.2) asks that the duty cycling should operate at all; and I call the CYCLER which actually calculates and puts out the relay duty cycle on rc.0.
Then every 10 milliseconds the RAMPADJUST is called to accept push button input (rb.0 and rb.1) to·adjust the·ramping speed slower or faster. These have limit sets from 5 units to 75 units.
Every 100 milliseconds the CYCLETRIGGER is called to initiate yet another complete duty cycle, and it is this trigger of course that sets the 10 Hz cadence.
So for fun, you could relocate the·1·second·LED flasher (rc.1) to·the 100 millisecond tick level and see what happens.
The beauty of this scheme is that all these tasks are (apparently) simultaneous and independent, and one need not concern (much) about timings of one event affecting another event. That said, though NO task may hog all the processor time and lock up the system. Delay loops are an ABSOLUTE NO-NO!!!!! After all, that is why we use an RTOS!
Run it through Guenther's simulator, and single step it in "debug" it with your SX-Key until you really get the hang of it.
Holler if you have questions.
Cheers,
Peter (pjv)
Sorry about the screen image quality, I'm still experimenting on the best way to tackle that!
Post Edited (pjv) : 1/9/2006 3:46:29 AM GMT
PJV, Even though assembly is still a mostly foreign language to me your code example goes a long way to giving structure to what Guenther was describing and how to accomplish of what I am looking for. The commands I mostly dont understand but the structure and program layout seems like it would be the same in SX/B at least I didnt see anything that couldnt be implemented. Between the layout and the comments its a tremendous help, and I'm sure will go a long way toward helping me accomplish my eventual goal of getting more into assembler. Just sat and went through it for the last hour getting a feel for what its doing. It looks like the key I was missing was selecting units of time that fit in with how I wanted to ramp the duty cycle and the fact that I could basicaly run a clock not in absolute time but tailored to what I want to do, and the light hits as I sit here and reply, I was looking for the math to calculate absolute constants for the steps in percent of duty cycle to acheive the ramp rate I was looking for when in actuality all I need to do is increment a variable from 5-95 one increment at a time over a set time period and snatch the duty cycle variable from that count as time passes...... Thanks again for the example, I'm not sure of thats exactly what your doing but it helped a lot.
Javalin,·Thanks for pointing this out, I'm off to search for his project and see what I can glean from it, if I remember right though it was controlling duty cycle through external commands via serial and the part that was stumping was basicaly ramping through a scheduler. Either way I'm sure I'll pick up something useful from it. If nothing else maybe I can puzzle out the scheduling now that its considerably later with much more reading since the last time I looked.
Your presunption is absolutely correct, the interrupt occurs, it does its thing, then it comes back to the main code and executes the next line of code. I believe the definition of an interrupt is that all other processing stops, the interrupt code runs, and then it comes back to full processing and executing the next line of main code.
The interrupt is a very powerfull tool, but takes some time and learning before you can really use it in a pwerfull way. I am in the same situation·as you, I would like to code within SX/B, but as you probably have noticed, all the experts use asm.
But, if we keep asking the questions·in terms of SX/B, maybe somewhere along the line we will have a break through, and get a response like ... and here is the SX/B version of the asm example.
Ray
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Ray
Thank you for posting that code with description and comments.· I am very much a beginner with SX and I am trying to learn assembler.· It is a long process for me as I have very little time to devote and very little programming background.· Studying these types of examples (with an elementary description and comments)goes a long way toward gaining an understanding about how the SX can be used.
My primary interest is to control LED brightness with PWM.· Simple in concept, difficult in implementation.· I could probably get something started more quickly with SX/B but I know that ultimately, assembly language is what I need.· I'm working my way through Gunther's book right now.· I leave the blinky LED on my desk 24 hours a day to remind me of my goal.
Ray, you inspire me.· Thanks.
Chris I.
·
I just read(and this helped me alot with my own program) that the ST and PLP registers use 1 to disable, 0 to enable.
From one SX'er to another,
RoboGeek
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
There are·3 kinds of people in the world,
the dreamers, the do-ers, and the "Oh, what's this button do"-ers.
Formerly bugg.
www.parallax.com
www.goldmine-elec.com
www.expresspcb.com
www.startrek.com
·