Displaying millisecond resolution with DS1307 RTC
Don M
Posts: 1,653
For a data logging project. Is it possible to get the 1307 to display hours:minutes:seconds:milliseconds or hours:minutes:milliseconds? If so how would it be done?
Comments
The DS1307 does not make milliseconds available to the user.
The resolution of the seconds edge is accurate enough though.
DS1307 Real Time Clock
You may be able to setup a cog that maintains a mS counter synced to the seconds edge in the DS1307.
Duane J
CBD
The chip doesn't return anything less than seconds...
In pseudocode:
Actually, looking at the datasheet, the Hz pin can output several frequencies:
SQW/OUT (Square Wave/Output Driver) – When enabled, the SQWE bit set to 1, the SQW/OUT pin
outputs one of four square wave frequencies (1Hz, 4kHz, 8kHz, 32kHz). The SQW/OUT pin is open
drain and requires an external pull-up resistor. SQW/OUT will operate with either Vcc or Vbat applied.
So if you set it up to drive one of the counters in a cog, you could use the 4/8/32 KHz output and just shift it down appropriately to get your millisecond value.
I'm just getting started with the RTC code. Well, not exactly started yet - maybe tomorrow.
But when it gets up and running I'll try to determine latency.
We do that by reading the RTC chip twice and seeing how long it takes.
I don't know yet, but I'll bet it's a whole bunch of microseconds.
To include Jason's idea, you'd need to read the RTC and save that, then add your mSec count.
It would not be a straight "read the RTC" GetTime function.
Resolution would depend on how fast you could read the chip time + accumulate mSec counts.
But there are a LOT of microseconds in a millisec.
Given they all start with 32768Hz, that's asking for a fractional divider, of 32.768 ?
http://www.wolframalpha.com/input/?i=fraction+0.768
gives some integer ratio choices.
The Prop is easily capable of spitting your seconds into even sub-microseconds, if you do not mind running it all the time.
Assuming you can enable the counter in less than 1 millisecond (which should be trivial) you now know exactly where you are within the second, and you know what millisecond time it was when you started. From there, you can do this:
As soon as you begin reading the time from the RTC it latches all the values. Waiting for the Hz pin to transition is so you catch the time at the start of the millisecond so the MS ticker doesn't change just before you read the time. You could also read the counter before and after reading the time. If the counter has changed, use the latter value, otherwise use the former (it'll be more accurate).
Does that make sense?
What is the advantage of using the 1s signal from RTC over using the propeller clock or a propeller counter?
For my understanding the RTC is usefull to keep the time when whatever uC attached to it is switched off. So, when switching the uC on it would read the time. In interrupt-driven uCs the 1s signal is very usefull, because you'd simply attach it to an IRQ-input and the uC can easily count the seconds and it's usefull because the available overflow-interrupts would need a chrystal with odd frequencies (f=2^x) to allow internal timer interrupts to happen with a one second-resolution. But the propeller has no interrupts. So, you have to code something anyways. So, why not read the initial clock, sync with the sencond signal once (which in the end only makes sense if you have a radio controlled clock) and then let a COG take care of all the rest. If you also log the date, you could re-read the RTC each night around 0:00 which will update the date part without the need to code an overflow of hours to day, day to month, month to year with the additional need to have a calendar function.
I'd do it this way:
Have a string which keeps the date string - initialized by reading RTC when switching on
Have a 32 bit variable which is used to count ms for 1 day. - initialized by reading RTC when switching on (32 bit in this case is enough to count for 49 days)
At 0:00 re-read date/time from RTC
Have a COG that keeps track of the ms
Plan B:
Use Jonnys Object ;o) Tztz ... so much time passed by between initially reading this thread and posting the response.
That's it.
You'd spend a few clock cycles counting milliseconds...
But not all that many.
waitpne, huh?
That's slick!
The deal is, even if you HAD interrupts you'd have to write code to service them.
So what's the difference between setting up for an interrupt verses setting up to poll for an event?
Either way you respond to the changing of the millisecond.
How much overhead would the rest of the task need?
Read data from something and log it - per millisecond?
Betcha there's a lot of standing around waiting for the millisecond to end...
For what it's worth, I haven't tried this...
But
That's part and parcel about what is so neat about this chip.
Worst case, use a counter to make a 5 megahertz clock and count THAT.
(if you can figure out how? Spin may not respond that fast, but assembly might)
That's only 200 nanoseconds per tick... - 1/5 Millisec per tick?
How 'bout it, oh ye spin gurus?
Can you increment a counter in 200 ns?
BTW- this IS plan B
The RTC uses a crystal that is (typically) more accurate than the ones spec'd for the Prop. That's it. If you used a crystal that was better than std spec, there'd be no reason to use the RTC beyond the startup read as you suggested. Well, that and not having to keep track of hours, mins, secs, date, etc. for your timestamps.
-- http://obex.parallax.com/objects/532/
Note that some method names have changed and the PASM portion is now compatible with other languages (i.e., it only uses par for access).
That said, I'd argue that locking single long access(es) isn't all that useful.
I agree that it's very cautious; that said, on the other side of things the RTC cog could be in the middle of the read-modify-write cycle for that register. By locking the "foreground" cog it ensures the background is not locked (busy with update) and the possibility of a collision -- I beleive -- is minimized.
You're right, though, about the construction of those methods -- I have fixed all. Not making an excuse, but I was updating two versions of the file and just fouled this part. This is why I like to post objects in the forums before moving to ObEx. Should have done it this time, too. Thanks, again.
What am I doing wrong?