Timing/Using a Propeller as a stopwatch
ryfitzger227
Posts: 99
Hello.
I'm moving up from the BASIC Stamp for a project that I'm working on. I'm very new to this type of programming language and I'm looking for some help with getting to learn it.
My project is a stopwatch/timer that is accurate up to 1 microsecond (.000001 sec). This leads to my first question. Is the Propeller capable of doing that (I know the BS2 isn't!!)?
I think I understand what a cog is, but just to make sure I'll explain my plan for this. My stopwatch actually consist of 4 different timers.3 of them start at the same time. So here's how I've layed out my cogs.
Cog 1 - Main (controller). Get's I/O's status and starts/stops the necessary timers.
Cog 2 - Serial Communication. After the time is calculated (I'm not going to be doing any math on the Prop. The computer program will calculate the final time. I just need it to calculate how long - in Prop time - it took for me to press Button A and then Button .
Cog 3 - Timer 1. The main timer. It will have the longest Elapsed Time.
Cog 4 - Timer 2. Starts at the same time as Timer 1, but will end with the shortest Elapsed Time. (Stops separately from Timer 1)
Cog 5 - Timer 3. Starts at the same time as Timer 1, and will have the "middle" Elapsed TIme. (Stops separately from Timer 1)
Cog 6 - Timer 4. Starts at a special time, but will end with Timer 1.
Can the Prop have 4 timers going at the same time and still keep an accurate resolution of 1 microsecond??
I don't see where this code will be very complex, but I could be wrong. All I'm doing is just calculating the ticks it was from the start of a timer to the stop. If I need to account for some overhead, or dividing by 10,000 to get a time in seconds, this will all be done in the program on the computer.
I read somewhere that I should use assembly rather than Spin because it's faster. Is that statement true?
Basically I'm just asking for some help/advice/resources on how to get started on timing in this resolution with the Prop.
If you have any questions, just ask.
Ryan
I'm moving up from the BASIC Stamp for a project that I'm working on. I'm very new to this type of programming language and I'm looking for some help with getting to learn it.
My project is a stopwatch/timer that is accurate up to 1 microsecond (.000001 sec). This leads to my first question. Is the Propeller capable of doing that (I know the BS2 isn't!!)?
I think I understand what a cog is, but just to make sure I'll explain my plan for this. My stopwatch actually consist of 4 different timers.3 of them start at the same time. So here's how I've layed out my cogs.
Cog 1 - Main (controller). Get's I/O's status and starts/stops the necessary timers.
Cog 2 - Serial Communication. After the time is calculated (I'm not going to be doing any math on the Prop. The computer program will calculate the final time. I just need it to calculate how long - in Prop time - it took for me to press Button A and then Button .
Cog 3 - Timer 1. The main timer. It will have the longest Elapsed Time.
Cog 4 - Timer 2. Starts at the same time as Timer 1, but will end with the shortest Elapsed Time. (Stops separately from Timer 1)
Cog 5 - Timer 3. Starts at the same time as Timer 1, and will have the "middle" Elapsed TIme. (Stops separately from Timer 1)
Cog 6 - Timer 4. Starts at a special time, but will end with Timer 1.
Can the Prop have 4 timers going at the same time and still keep an accurate resolution of 1 microsecond??
I don't see where this code will be very complex, but I could be wrong. All I'm doing is just calculating the ticks it was from the start of a timer to the stop. If I need to account for some overhead, or dividing by 10,000 to get a time in seconds, this will all be done in the program on the computer.
I read somewhere that I should use assembly rather than Spin because it's faster. Is that statement true?
Basically I'm just asking for some help/advice/resources on how to get started on timing in this resolution with the Prop.
If you have any questions, just ask.
Ryan
Comments
Yes. The timers use the same clock.
This is fairly simple if the start/stop signals for the timers are clean (no debouncing required) and less than 56 seconds apart. If the elapsed time is more than that it is only a bit more complex. Then you need to take the counter rollover into account.
Yes. Assembly is much faster than spin. Under some circumstances this might be do-able in spin, but may need assembly.
Will the elapsed time between starting and stopping the timer be more than 56 seconds?
What type of signal will be used to start and stop the counters?
Running at 10MHz (PLLx2) will allow you almost 8 minutes before you have to worry about roll-over.
Bean
Execution times on the Prop even in Spin are much faster than the BASIC Stamp, and there are commands such as WAITPEQ that would allow the program to synchronize to the bream breaker or to the start signal. The advantage of the Prop there is that it can be timing the one interval at the same time that it is transmitting the previous interval over the serial port.
Another option for timing on the Prop are the COG counters. They can measure pulses down to sub-microsecond resolution, and in the logic modes they can be started/stopped by the levels on a couple of input pins. A spin or pasm program would observe the levels in parallel and capture the intervals to send to your central processor.
I learn better with code, and I haven't seen anything that has really showed me how to do anything.
Can someone give me an example (in Assembly) how to create 3 cogs. 1 for serial port, 1 monitoring the pushbutton output - and starting/stopping the timer, and the last for the timer? (I just want to start off easy. This way I'll learn how to create cogs and time something.. Then I can expand that to more than 1 timer.) I hate asking people to write me code, but I seriously have no clue about this language. Remember. All I really want is clock cycles (I guess). Then I'll send that number to the computer program, which will convert those clock cycles into time. You don't have to worry about accounting for overhead, I'll do that.
- Ryan
I've not bothered with a serial driver yet.
Haven't had the need.
So this won't be what you may have hoped for.
But it might be useful as an example of a couple of things.
Like How to start other cogs. How to pass information around.
This runs on a QuickStart, so it uses the capacitive touch buttons instead of real switches.
Those take quite a bit of fiddling with to make them work.
Not a problem, but it takes clock cycles.
This button driver is written in Spin, so it takes even more clock cycles.
But it's more understandable for first time coders, I think.
The Touchpad button driver runs in the second cog.
I'm setting a flag in the first cog and watching for it in the third.
Anyway, the main routine:
The button driver:
And the flag monitor:
Again, this is just a start. Brush strokes, if you will. It's up to you to paint the masterpiece. :-)
This is PASM portion of the object. Pretty easy.
A little more detail on how the timers will be started and stopped would be of help.
Will there be a signal on one pin to start the timer and a signal on another pin to stop it, or will a pin go high (or low) to start the timer and low (or high) to stop it?
Will the start/stop method be the same for all 4 timers? It sounds like this will be so based on post 1, so two start signals (timers 1, 2, 3) and (timer 4) and three stop signals (timers 1, 4), (timer 2), and (timer 3). Is this correct?
The simplest approach may be to have a PASM program that monitors 2 pins (start and stop), starts a counter when the start signal is true, stops the counter when the stop signal is true, and writes the 32 bit counter value to a hub location. The program could then be loaded into 4 cogs with the pin numbers and hub locations passed as parameters. The main spin program would send the data to the PC.
Ryan, you're really biting off quite a lot with that request, as you move up from the BASIC Stamp.
Here is a snippet that starts a serial port at 9600 baud, and then simply spits out the time between two presses of a button. It is all in Spin. Well, not quite. When it starts the serial port object (Parallax Serial Terminal), that in turn does start up another Cog that does the heavy lifting, but you don't have to know the details. In PBASIC, the serial commands are built in, but in Spin, the program has to initialize the serial port. Also in PBASIC, the Pause command is built in, but in Spin, it is a method that is written into your own program code by referring to the Prop's clock frequency and its global counter. You should understand thoroughly how the Pause method works.
The Main program loop goes just as you might write the same thing in PBASIC. It waits for the button on p0 to go low, captures the global counter value, then waits for the button to go up and then down again. At that point it sends the difference between the current value of the counter minus the starting value, out as a decimal ascii number to the serial terminal. Then it waits for the button up again and repeats the whole process. Is all that already completely clear to you? If so, the next step may be to start timers running in parallel in different Cogs. However, I'd echo Kwinn, "A little more detail on how the timers will be started and stopped would be of help."
Super easy. Since you only need one long for the timing result I wrote the pasm such that the start and stop pins are passed in it -- put the start pin in byte0 and the stop pin in byte1; pass the address of your result variable in the cognew() call. Again, easy-peasy.
Super easy. Since you only need one long for the timing result I wrote the pasm such that the start and stop pins are passed in it -- put the start pin in byte0 and the stop pin in byte1; pass the address of your result variable in the cognew() call. Again, easy-peasy.
First off, before I get too far into PASM - if I use Spin how accurate will the timing be? For example. If I create a timing program in Spin, find out how long it takes for the commands, and add that back to the final time will that overhead be the same EVERY time? Or will it vary? If it does, then I guess I'll use PASM. (I'm assuming you would still have to account for overhead, but that it would have a static overhead when using PASM).
I'm leaning towards using/learning PASM for this project because it seems so simple. I like the idea of the copying and pasting the same program and then passing the pin numbers as paramaters. But you mention that I would use the main program for serial port communication. Is it possible for me to write the main program in Spin and then the rest of the objects in PASM (timing)?
This might seem kinda crazy, but I have no clue. How do you save PASM files? Will they still be .spin?
Honestly, the starting and stopping is fairly complex. It consist of (mainly) 2 Props. Prop 1 for starting/reaction times and controlling the lights that tell the person when to go and getting their reaction time. Prop 2 will be timing that person until he gets to the end of the track (with multiple times at different feet intervals - ex. 60ft, 330ft, and finally 660ft.) I'm going to ignore Prop 1 for now because it's pretty complex. It involves a bunch of different timers starting/stopping at different times. Prop 2 is just (practically) one timer starting and stopping like a stopwatch. Remember Timer 1 (the main, or Elapsed Time, timer)? That timer is what every timer after it (except the last) goes off of by when it's time to start. Prop 1 will do it's timing and when the guy leaves, it will get his reaction time. Well at the same time it will set the base of a transistor that's connected to a pin high. The emitter/collector will be connected to a Pin on Prop 2. This will be the signal that Timer 1 starts by. Therefore, Timer 1, 2, & 3 all start off of that. This will be the only time a transistor is being used. The rest will be started/stopped by an infrared. View the table below for more in depth information.
Starting Line
60 feet
330 feet
MPH Start
MPH/ET End (660 feet)
Started by
Transistor
connected to
Prop 1
Ended
by
infrared
Ended
by
infrared
Started
by
infrared
Ended
by
infrared
Starts Timer 1,
2, & 3
Ends
Timer 2
Ends
Timer 3
Starts Timer
4
Ends Timer 1, 4
If you have anymore questions, just ask. I'm always open for suggestions. Thanks for everything so far!
The precision of a WAIT command is the same in Spin and PASM, what PASM allows is faster re-arm, and it could time between edges very close together.
However, if you want to resolve to 1us, but never have edges closer than a few ms, then Spin could be quite ok.
Human Reaction times, and running times, will be > 100ms, and you may need to worry more about the other end of the scale: timer roll-over.
Slowing the Prop down a little from the 80MHz will probably do for that.
If you are interested in a solution maybe a little more powerful than spin, and maybe a little easier than PASM:
http://code.google.com/p/propforth/wiki/Logger1Simple
This is the logging package from propforth. It has microsecond resolution and can comfortably log once per second (counter, date time stamp, and data). It requires no addition hardware besides the SD card for logging (you copuld log to EEprom instead). There is a one time calibration, once the drift setting is input, its nut dead on. If the temperature is stable, there is about 3-4 microsecond variance. It uses double math, and the time stamp won't roll over for just over seven thousand years.
It's seems its fine for day to day logging, as the temperature changes, the clock drifts in then back out again, so over 24 hours, it averages out. If you are going to put it outside for an extended period of time of in varying temperature environment, you can use a temperature compensated crystal, but it hasn't been necessary yet for the testing performed.
The current test is a torture test designed to wear out the SD card, but is has logged 110 gig of data once per second to the same file. The SD has not failed yet even though the head header is constantly being rewritten. To make off loading the data easier, the lgger was changes to create a new file when the Day rolls over, this should never fail the SD.
The logger continues loggin even when the log is accessed or the time is set. If power is lost, the system restarts with default time of 2000, January 1, 12:00 AM; but after you set the correct time (manually) you can easily back fill the correct date stamps.
If you don't use forth, you might be able to use the same method in the language(s) of your choice.
Im new to this, so what happens after 56 seconds? Does the timer just stop, or does it become inaccurate? I shouldn't be timing for that long under any circumstance, but in case the stop infrared is missed I want to know what I should do.
~56 seconds( 2^32/80e6 = 53.6870912) is just the 32 bit number wrap-around, and that is for a 80MHz SysClock.
80MHz gives a 12.5ns LSB, so you may decide to just drop the 80MHz, to move that 53 seconds.
eg 10MHz SysClk gives 32 bits to 428 seconds, and still can edge sense to 100ns.
Or, you could choose to drive a spare Pin as a Counter-Clock, and then you can freely scale to any time you want, but still have a faster CPU processing speed.
The COG counters can be set to tick at that Pin-Rate using POSEDGE or NEGEDGE modes.
Here, 80MHz divided by 80 to a 1us pin-rate, would overflow in 71 minutes, and you could easily change to 10us, or 100us.
If you are serious about the 1us LSB, then you might want to also capture a GPS 1pps signal, and use that as a calibrate reference.
If you use 64 bit numbers (2^64 / 80e6 ) it rolls over after 7,311 years. The way the counters works, they just operate in the back ground and count time for free, and you can do other stuff with the cogs.
Back to post 6, if you log when the beam was broken, and whether it was at the start or end of the track, you could log not only each race, but the intervals between races, and the interval between race days, for the entire season, and for multiple seasons, all on one SD.
What are you going to use as a display? The prop can also run a VGA display, and a keyboard. And propforth can of course do this, with the logger running on on a separate cog.
(I'm kind of excited about this logger stuff, can you tell?).
I kinda jumped ahead a little since cavelamb showed me how to create cogs, etc. But this code for the timing I just can't get to work. What am I doing wrong? For testing purposes I'm using a QuickStart board. Are the pushbuttons on it a little different?
Here's the code.
main.spin
timer.spin
The Serial Terminal keeps saying "Timer 1: 0".
The type of pushbuttons does make a difference. The code I provided as well as quite a bit of the other code here has assumed that the signal is a solid ON or OFF as you would typically get from an industrial electronic timer or control. A mechanical button or the buttons on the quickstart are a different matter. They will bounce and the code will race through its states. You'll need to add code to debounce the buttons to be sure that they are solidly in one state or another, and the debouncing can be done either in line with the timer, or as a separate routine running in its own cog.