My First Obex ;) Timer32
jmspaggi
Posts: 629
Hey!
I just published my first OBEX!
http://obex.parallax.com/objects/670/
It's a timer object based on the Javelin Timer object idea.
Working that way:
Few options available too, like using a cog instead of calling tick on the main loop, implementing multiple timers but calling only one time tick for all, etc.
Ok, maybe far from the best Spin code you will have ever see, but at least, it can be useful. It's something which I was really missing on the propeller. Very useful when you want to have one single loop and multiple actions planned in it.
JM
I just published my first OBEX!
http://obex.parallax.com/objects/670/
It's a timer object based on the Javelin Timer object idea.
Working that way:
OBJ timer : "Timer32" PUB main timer.Mark repeat timer.Tick if (timer.TimeOutMS(500)) timer.Mark '' Perform a periodic action.
Few options available too, like using a cog instead of calling tick on the main loop, implementing multiple timers but calling only one time tick for all, etc.
Ok, maybe far from the best Spin code you will have ever see, but at least, it can be useful. It's something which I was really missing on the propeller. Very useful when you want to have one single loop and multiple actions planned in it.
JM
Comments
Sorry, but your object looks overcomplicated to me. And it's hard coded for 80MHz, which is never a good idea.
Spin and the Propeller can do this much better, simpler and clock independent:
As long as the clkfreq is a multiple of 1000, the periodes are very accurate (12.5ns resolution). There is a jitter from the loop duration, but this is compensated every time because of the way the marks are increased.
Andy
I appreciate the work you did.The code might be simple but it gave me new ideas to work with.
@Ariba: Thanks for your comment. The dependency to the frequency is something I was thinking about and I will (try to) address soon in the next "release".
Regarding your code, let's take 2 situations.
1) My goal is to monitor the outside temperature every 5 minutes. Will that work with your example?
2) What will happen when CNT whill be $FFFFFFFF? 2 things. Since spin code integer are signed, are yout not going to wait for a while instead of just 500ms?
I agree, you can add some test conditions to get rid of that. But the goal of my object is to remove all those test conditions and calculations from the main class to make is lighter, to allow a timer which work on all conditions (even when CNT is $FFFFFFFF), and allow longer delays compared to what CNT alone allow.
JM
But I was looking at the comments in your code and there's something odd about the numbers. Shouldn't that be 12.5us (every 1000 clock cycles at 80MHz)?
I think 1ms should be 80, 1s 80,000, etc.
Timer objects are always handy, but if your goal is just to measure something every five minutes and your measurement takes less than a millisecond, you can do it in Spin (I have). One of the many clever programmers in the forum posted this header that is default in my programs:
Note that I added the MS_001 and US_001 constants. With this you could create a "background" Spin cog like this (launch with cognew):
For low-resolution events I've been coding like this -- easy to code, update, and modify.
Hi Mark,
Oups. Comments are wrong. I will fix that too. It's every 1024 clock cycles. This is to have faster tick method. That's why it's 12.8 and not 12.5. I will fix that. And thanks for the kudos
@JonnyMac:
Hi Jonny,
When CNT will move from $FFFFFFFF to 0, will you not have an issue whith this line? I'm not 100% sure, because t is signed.
Also, if the same loop is used for other purposes, you not necessary want to delay everything by one MS.
In my application, I already have one main loop for all the recuring processess. Like reading the input devices (switchs, etc.), updating the display if required, etc. Adding a tick in this loop save me a cog, and allow me to add timers to few options (display the time, get the temperature, etc.). This can take more than 1ms. Wich mean I will loose the CNT target and have to wait for a full circle.
In my timer, I can call the tick only once every 2 seconds and I should still be correct. Since tick take about 5us, I can call tick between 5us and 2 seconds. Quit flexible.
I don't say all the options proposed on this thread are bad, I'm just saying that they are differents. Me, I need multiple timers (One to get the temperature, one to display the time, one to log the values, one to ping the distance, etc.). The purpose of this object is to simplify and clear the main loop.
I'm not very good with signed numbers, but I think the behaviour of t += MS_001 might not be what's exected to be when we reach the limits.
JM
Same thing applies if you use something like that;
if (cnt-t)>0
doyourcode
being continuous and wrapping around everything is safe.
If you are unsure test a small counter. When in doubt I use a 4-8 bit test number.
Mechanics is the same, but it is easier to follow..
Massimo
Thanks.
I will try to spend sometime on the Propeller documentation this evening to look at the signed numbers.
So the only risk with waitcnt(t += MS_001) is to take more than 1ms to execute the code instruction and then miss the target.
Thanks,
JM
2) is already answered.
to 1) My example works up to ~27 seconds at 80MHz (half the rollover time of cnt). So if you need times like 5 minutes your object makes a bit more sense.
I would just add a prescaler like this: So you have still the high resolution but also very long intervalls.
Andy
You can always change your timing resolution. For example, if 5ms resolution works an you need the time for measurement you could change that line to:
waitcnt(t += constant(5 * MS_001))
I've done this, too. Of course, you also need to update the line that increments your milliseconds counter that triggers the measurement.