Italy
Offline
Newbie
Karma: 0
Posts: 14
|
 |
« Reply #15 on: July 07, 2008, 05:48:38 am » |
I don't think I loose ms on each loop. Let's see the first code I post: current_millis_value = millis(); m += current_millis_value - previous_millis_value; seconds += m / 1000; m = m % 1000; minutes += seconds / 60; seconds = seconds % 60; hours += minutes / 60; minutes = minutes % 60; hours = hours % 24; previous_millis_value = current_millis_value; If you think about it, you will notice that m is a "cumulative-ms" variable. On every loop, I increase seconds by m / 1000, but then I do m = m % 1000 in order to not loose left-over ms... Right?
|
|
|
|
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #16 on: July 07, 2008, 02:17:38 pm » |
Joe, you are quite right that its not your code that is causing time errors but I remain surprised that your crystal is so inaccurate. I have just completed a test using a third arduino board (as I mentioned, two other boards were tested to be accurate to within a few seconds per day measured over many days) to see if I could reproduce the kind of results you posted.
My test on the third board has been running for over 7 and a half hours and the arduino is within on second of internet checked atomic time. So I am not sure why your results are so different to mine, and why they seem to be outside the spec for a 30ppm crystal.
|
|
|
|
« Last Edit: July 07, 2008, 02:19:01 pm by mem »
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #17 on: July 08, 2008, 10:43:32 am » |
Hi Joe, update on the arduino time test: My test has been running for over 24 hours with the arduino clock remaining within two seconds of an external time reference over that period. Thats three different boards verified as keeping time within about 2 secs per day.
Is your board using a resonator instead of a crystal?
|
|
|
|
|
Logged
|
|
|
|
|
Italy
Offline
Newbie
Karma: 0
Posts: 14
|
 |
« Reply #18 on: July 08, 2008, 12:29:13 pm » |
Is your board using a resonator instead of a crystal? Umh, I don't know... Mine is an Arduino Diecimila...
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 1
Posts: 41
Arduino rocks
|
 |
« Reply #19 on: September 08, 2008, 09:46:50 am » |
Do you know what the specs say for the accuracy of the crystal used on Arduinos? No, I don't know. I've only measured time difference with a stopwatch, looking at Arduino and an atomic clock via internet. I can be a little imprecise, but over 6 hours of measuring, results are clear: 0h 0.00s 1h -0.70s 2h -1.10s 3h -1.60s 4h -2.00s 5h -2.40s 6h -3.00s 7h -3.50s This morning I read result of the overflow test from my Arduino EEPROM. It's exactly the value you calculate: 34359737 before overflow, 0 after overflow. So I will use: #define MAX_MILLIS_VALUE 34359738 ... if (current_millis_value < previous_millis_value) m += MAX_MILLIS_VALUE - previous_millis_value + current_millis_value; else m += current_millis_value - previous_millis_value; On the simpler overflow (from 34359737 to 0): MAX_MILLIS_VALUE - previous_millis_value + current_millis_value = 34359738 - 34359737 + 0 = 11 millisecond is elapsed. Thank you Ben!  Nice post indeed. I though I could understand the question in snap... no way  Question is: why nobody uses the modulo function in order to have a smooth constant elapsed time calculation? Kind of: elapsed_time=(max_counts+this_tick-last_tick)%max_counts ? Am I misleading?
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX USA
Offline
God Member
Karma: 3
Posts: 992
Arduino rocks
|
 |
« Reply #20 on: September 08, 2008, 10:52:18 am » |
Joker,
The express you propose,
elapsed_time = (max_counts + this_tick - last_tick) % max_counts;
is indeed more succinct and readable than the equivalent
if (this_tick < last_tick) elapsed_time = max_counts + this_tick - last_tick; else elapsed_time = this_tick - last_tick;
However, I think you'll find that many programmers opt for the latter for the simple reason that in most computer architectures the modulus operation is much more costly in terms of CPU consumption.
Cheers,
Mikal
|
|
|
|
« Last Edit: September 08, 2008, 10:58:12 am by mikalhart »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 1
Posts: 41
Arduino rocks
|
 |
« Reply #21 on: September 08, 2008, 11:43:40 am » |
I see, thanks for the hint. See, I am still from the memory greedy VB.NET, and I have to get used to smaller environments (that I love anyway); takes me back to the early 80's and HP1000 running progs in 32K! :o
How many ticks for a mod?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 1
Posts: 41
Arduino rocks
|
 |
« Reply #22 on: February 08, 2010, 03:47:49 am » |
Thanks for the example. Finally, I jumped out the frying pan (millis function :-/ ) into the fire (Timers  ). It took me a little time :  before being confortable about them, but it's OK now and find them muuuuch more handy: now I can really control time accuracy and forget about roll-overs, changes in versions, etc. And they are accurate: heavily tested on functions generators http://forums.adafruit.com/viewtopic.php?f=25&t=14149 
|
|
|
|
« Last Edit: February 08, 2010, 03:48:30 am by joker »
|
Logged
|
|
|
|
|
Madison, WI
Offline
Newbie
Karma: 0
Posts: 48
Exploring Electrons. . .
|
 |
« Reply #23 on: February 09, 2010, 01:26:31 am » |
Alright, things aren't working so hot :-( I'm running this code: #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
unsigned long current_millis_value = 0; unsigned long previous_millis_value = 0; unsigned long m = 0; unsigned int seconds = 0; unsigned int minutes = 0; unsigned int hours = 0;
void setup() { lcd.begin(2, 16); lcd.clear(); } void loop() { cli(); current_millis_value = millis(); sei(); m += current_millis_value - previous_millis_value; seconds += m / 1000; m = m % 1000; minutes += seconds / 60; seconds = seconds % 60; hours += minutes / 60; minutes = minutes % 60; hours = hours % 24; previous_millis_value = current_millis_value; lcd.clear(); lcd.print("t:"); lcd.print(hours); lcd.print(":"); lcd.print(minutes); lcd.print(":"); lcd.print(seconds); delay(150); }
on a Duemilanove and am able to watch the Arduino run too slowly (loses 1/2 a second in the first minute). Anyone have any thoughts? Are there delays/interrupts in the LCD library? I just need a timer that counts up accurately when some event is true, it only needs to run for about an hour max so the overflow isn't an issue at all for me. Is there a better/more precise way to be doing this? I've dug through the code and stripped it down to what you see, there isn't much left except for the LCD screen writes that could be losing/taking time but I shouldn't matter how long the program since that's all accounted for. Any thoughts? > 
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #24 on: February 09, 2010, 06:05:00 am » |
More questions than answers, really. Why are disabling interrupts before calling millis?
Why are you calling delay?
There are more efficient ways of computing new values for minutes and hours. minutes only needs to be updated if seconds has reached 60. An if test (if seconds == 60) and two assignments (seconds = 0; minutes++;) is faster than the call to the modulo function. The same hold true for hours. hours only needs to change when minutes equals 60. hours can be reset to 0 faster using an if test than a modulo function call, too.
|
|
|
|
« Last Edit: February 09, 2010, 06:05:18 am by PaulS »
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #25 on: February 09, 2010, 07:44:57 am » |
perhaps try something like this: void loop() { while( millis() - previous_millis_value >= 1000){ elapsedSeconds++; previous_millis_value += 1000; } seconds = elapsedSeconds % 60; minutes = (elapsedSeconds / 60) % 60; hours = elapsedSeconds / 3600; }
|
|
|
|
|
Logged
|
|
|
|
|
Madison, WI
Offline
Newbie
Karma: 0
Posts: 48
Exploring Electrons. . .
|
 |
« Reply #26 on: February 09, 2010, 09:20:45 am » |
Why are disabling interrupts before calling millis? That's covered further up this thread, someone suggested that an interrupt would corrupt data from the millis call, doesn't seem to have any effect in my testing. Why are you calling delay?
Delay is so the screen flicker on the LCD display isn't terrible. If you run it any faster than 150 milliseconds it starts to blend things together (when the milliseconds readout is running, which isn't in this code). There are more efficient ways of computing new values for minutes and hours. I agree that when possible the most efficient path to the objective should be used, but fundamentally does it matter in this loop losing time? Since the loop is just counting up how many milliseconds have iterated between loops and adding it to a value I don't think it has any effect on the loss of time (which is what I'm worried about before beginning to optimize anything). mem says: perhaps try something like this: . . . I ran this, after about 3 minutes the Arduino was off by exactly a second, it again is running too slowly. The only way this could be happening is if the millis() call isn't returning the correct time, which is a function directly of the processor crystal right? Can anyone else test this code (mem's) and see if they're having similar results? I'll run this code on a mega later today and see if I have similar issues or if things clear up; until then any other ideas? Thanks everyone for help!
|
|
|
|
« Last Edit: February 09, 2010, 09:21:41 am by Waterppk »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #27 on: February 09, 2010, 09:31:31 am » |
I ran this, after about 3 minutes the Arduino was off by exactly a second, it again is running too slowly. Compared to what?
|
|
|
|
|
Logged
|
|
|
|
|
Madison, WI
Offline
Newbie
Karma: 0
Posts: 48
Exploring Electrons. . .
|
 |
« Reply #28 on: February 09, 2010, 09:53:20 am » |
It's now been running for: 33 minutes 43 seconds clock time, arduino says: 33 minutes 30 seconds I'm using a stopwatch for comparison, I previously tested the stopwatch against http://www.time.gov/timezone.cgi?Central/d/-6/java for ~8 hours without losing a second, so for now the stopwatch is much more accurate than the Arduino 
|
|
|
|
|
Logged
|
|
|
|
|
Madison, WI
Offline
Newbie
Karma: 0
Posts: 48
Exploring Electrons. . .
|
 |
« Reply #29 on: February 09, 2010, 10:23:18 am » |
Alright, I switched over to using Serial.print and watching on the console and it's running spot on at 4 minutes.
I'll figure out who wrote the LCD library and follow up with them, obviously there's something in that library messing up a timing routine.
Thanks for your help guys.
|
|
|
|
|
Logged
|
|
|
|
|
|