math dependant program questions
krazyideas
Posts: 119
Hello all,
Ok well A little while ago I made a RPM gage using the propellor, but it is not very accurate. It jumps by about 60 RPM up and down. It was a while ago that I made that program and it worked suffencently.
But now I want to build a program that I can use time to mark 1/3 degree marks for a entire rotation at 2500 RPM.
And with my past experince with the propellor (which is very limited), this is not possible, because I need a seperate cog to run (I think) floating point math to get accurate multiplication and division and that would take too long for me to get a 1/3 degree map of the motor's rotation each rotation.
I expect that I am underestimating the abilities of the propellor as I have before, but I just wanted to know if what I want to do is doable.
The program would
1)·measure the number of counts in a rotation
2)(Using Floating Point Math) divide the number of counts by 1080 (360 * 3),·calling it Mark
3)then wait for my mark to signal·the zero·mark (which only shows once a rotation)
4)from which I can·(using Floating Point Math) use Mark times whichever 1/3 of a degree I want to execute a command on.
I would have 2 cogs running the above program just off set by one rotation and therefore still being able to execute commands every rotation
More or less I'm trying to make a decoder wheel with only one mark on it.
I'm I barking up the right tree, is the idea decent?
Is Floating Point Math Fast enough?
I'd just like to know if I should give it·a whirl.
Thanks so much
·
Ok well A little while ago I made a RPM gage using the propellor, but it is not very accurate. It jumps by about 60 RPM up and down. It was a while ago that I made that program and it worked suffencently.
But now I want to build a program that I can use time to mark 1/3 degree marks for a entire rotation at 2500 RPM.
And with my past experince with the propellor (which is very limited), this is not possible, because I need a seperate cog to run (I think) floating point math to get accurate multiplication and division and that would take too long for me to get a 1/3 degree map of the motor's rotation each rotation.
I expect that I am underestimating the abilities of the propellor as I have before, but I just wanted to know if what I want to do is doable.
The program would
1)·measure the number of counts in a rotation
2)(Using Floating Point Math) divide the number of counts by 1080 (360 * 3),·calling it Mark
3)then wait for my mark to signal·the zero·mark (which only shows once a rotation)
4)from which I can·(using Floating Point Math) use Mark times whichever 1/3 of a degree I want to execute a command on.
I would have 2 cogs running the above program just off set by one rotation and therefore still being able to execute commands every rotation
More or less I'm trying to make a decoder wheel with only one mark on it.
I'm I barking up the right tree, is the idea decent?
Is Floating Point Math Fast enough?
I'd just like to know if I should give it·a whirl.
Thanks so much
·
Comments
2500 RPM is roughly 40 revolutions per second or 25ms per revolution. That's roughly 25us per 1/3 of a degree rotation. The Propeller can execute about 2000 instructions in that amount of time. If you call the floating point routines from assembly language, you could do a couple of simple operations in 25us, but it sounds like what you want to do doesn't need floating point.
Why not calculate ahead of time how many system clock ticks are needed from the "zero mark" to when you want to execute something? You'd have an assembly routine running in a cog waiting for the "zero mark" using a WAITPNE instruction, then do a WAITCNT instruction with the number of system clock ticks to wait. When the WAITCNT is over, your "command" routine would execute. When the "command" is done, your cog program would jump back to wait for the "zero mark" again.
If you want to run two cogs so there's time for the "command" to run, it's easy enough to compute the time just before the next "zero mark" will come up and wait for that before waiting for the "zero mark".
Post Edited (Mike Green) : 2/13/2010 11:15:28 PM GMT
It's not so much that I need to do commands every 1/3 degree but more I need to execute a command that lasts for X number of 1/3 degrees and it needs to occur at A 1/3 degrees, B 1/3 degrees , C 1/3 degrees, etc... after the "zero mark" each rotation.
So how I was going to have the program adjust for the RPM flucuations was to measure the time it takes for a rotation on one rotation and then execute on the following rotation, that leads to the problem of only being able to execute on every other rotation, which I hoped to remedy that was have two programs running off set like I mentioned before.
So it sounds like this shouldn't really be all the hard to do, and that the propeller is plently able to do what I am wanting.
Though Assembly and I don't get along very well. Knowing more of what I want to do would Spin be suffencent?
Also just wondering how much faster is Assembly then Spin?
Thanks a ton Mike
80_000_000 / 2500 = 32_000 clock ticks per round
32_000 / 1080 = ~30 clock ticks per 1/3 degree
You can not wait for 29,629 ticks, so the prop can't be accurate with waiting for 1/3 degrees.
Floating point arithmetic won't help with that!
30 - 29,629 = 0,371 => deviation of ~1,25% (at this speed)
Bigger problem might be that you need a full turn until you can correct the value.
You should have a look at the bresnham algorithm. It's usually used for drawing lines, but it draws lines with integer arithmetic by keeping track of the deviation.
Maybe you can tell a bit more about your project, so that we can see more clearly what's the reason behind.
One other idea might be to use 3 marks per round and maybe run 3 COGs to create the 1/3 degree marks.
@crazyideas - I suspect that you and assembly language will need to get acquainted. Spin may be sufficient, but it'll be a close thing and will depend on details of what you're trying to do that you haven't shared yet.
There hasn't be a detailed comparison of Spin speeds vs assembly speeds, but it's roughly 200:1. It depends a lot on what you're trying to do. Have a look at Bean's (Hitt Consulting's) new PropBasic. This is a subset of integer Basic that compiles into Propeller assembly language. It's still in development, but far enough along to be very useful. It'll be integrated into BST, a very good 3rd party Spin compiler / Propeller assembler, downloader, and IDE that runs under Windows, Linux, and the MacOS. There's a recent forum thread that you can download it from.
But still it's true that a modification of the bresnham algorithm will be sufficient for the problem. No need to use floats.
I think the decoder wheel can help to improve accuracy. For example you can have 3 marks instead of one. Or you can use a mark which is exactly ... say 1 degree or 5 degrees ... and use a counter to measure the actual speed. And still use the old way to measure the average speed. With some math you can find out if speed is increasing or decreasing.
At 2500rpm you are talking about updating your gauge ~42 times per second. Assuming that this is supposed to be a human readable gauge and the rate of change of rpm is not super high then you could do it much less frequently and still get smooth and accurate operation.
You could measure the time for one rotation and then take more than a rotation to process it, just hold the gauge at the previous measurement while the calculation takes place. Even if it takes 3 or 4 rotations you will not notice it. But if you wanted to you could use multiple cogs, in assembly this would be simple for one cog, updating every revolution.
I also think that you don't really need to use floating point math, you have 1080 divisions on your scale, if you treat these as your fundamental unit (even though they represent 1/3 of a degree) no floats are needed.
Your calculation is this:
T2500 = 1/(2500/60) ' Time period at 2500rpm (full scale)
ticks@2500 = T2500*clkfreq ' Number of clock counts in a revolution at 2500rpm
point on scale = (1080/ticks@2500)*ticks ' This will be 1080 at 2500rpm
The important thing to notice is that (1080/ticks@2500) is a constant you can calculate either on a calculator or at compile time. You can ignore the fractional part because what does it matter if you are out by a single clock cycle (12.5ns), it will make no difference to your reading.
Hope that helps and I didn't drop any clangers
Graham
point on scale := (ticks*1080)/(ticks@2500)
2500 RPM is the max., he talked about a min of 500 RPM. So, your multiplication will bust the 32 bit size of a long.
500 RPM = 8.3333 RPsec => 1/8.3333 = 120ms => 80_000_000 / 8.3333 = ~9_600_000 => 9_600_000 * 1080 = 10_368_000_000
where 4_294_967_294 is the max.
But you can divide both values by 10 and you're back in the allowed range. (1080/10 and [url=mailto:ticks@2500/10]ticks@2500/10[/url])
Just for the records, because I think he does not want to do a gauge again.
Post Edited (MagIO2) : 2/14/2010 5:24:46 PM GMT