// status = HIGH
}
else if (digitalRead (inputA) == HIGH && digitalRead (inputB) == LOW) {
// status = LOW
}
}
... that's it. Fully debounced.
That wastes another GPIO and requires a minimum of one if statement to be evaluated. Even worse, in some cases it might require two if statements to be evaluated. That's wasting precious processing time. Everyone knows that hardware is cheaper than CPU time, right?
GoForSmoke:
What did you use to generate that? Is it IDE output?
ds.cmd ...
@Echo Off
C:\Python32\python C:\Path32\ds.py
ds.py ...
import fnmatch
import os
import subprocess
import string
pathok = False
pathlist = os.environ['PATH'].split( os.pathsep )
for path in pathlist:
testme = os.path.join(path,'avr-objdump.exe')
if os.path.exists(testme):
pathok = True
break
if not( pathok ):
arduinoroot = 'C:\\Arduino\\arduino-1.0.1\\'
pathlist.append( arduinoroot + 'hardware\\tools\\avr\\utils\\bin' )
pathlist.append( arduinoroot + 'hardware\\tools\\avr\\bin' )
pathlist.append( arduinoroot + 'hardware\\tools\\avr\\etc' )
pathnew = os.pathsep.join( pathlist )
os.environ['PATH'] = pathnew
tempdir = os.environ.get('TEMP')
tempfile = os.path.join(tempdir,'Junk.cpp')
matches = []
for root, dirnames, filenames in os.walk(tempdir):
for filename in fnmatch.filter(filenames, '*.elf'):
matches.append(os.path.join(root, filename))
matches.sort( key=os.path.getmtime )
if len(matches) > 0:
f = open(tempfile, 'w')
subprocess.call(['avr-objdump.exe','-S',matches[len(matches)-1]],stdout=f)
f.close()
os.system( 'start ' + tempfile )
Run "ds" in a command shell. The file is opened using the default editor for .cpp files. Python must be installed. ds.cmd will very likely have to be updated with the location of Python on your computer. The most recently compiled sketch is processed.
@Jiggy-Ninja: Yes, right. Especially if monitoring the upper left hand box here.
@GoForSmoke: I like your approach ... waiting for a period of stability rather than ignoring a "guessed" period of instability. Also debouncing both state change transitions. +1
However 2000 usec measure requires 2 bytes and at least twice as long to process as 1 byte and millis.
What if you used this:
msNow = (byte) micros() >> 10; // get bits 10-17 of micros
Would not miss any counts but would increment every 1.024ms.
dlloyd: @GoForSmoke: I like your approach ... waiting for a period of stability rather than ignoring a "guessed" period of instability. Also debouncing both state change transitions. +1
With decent buttons and a fast loop I can get the debounce period down to 2ms after the last detected bounce.
Notice that every other detected change turns the timer off (clears the bounce bit) since it puts the button back at the original pre-detect state. The whole read-the-time-then-subtract-and-compare process only goes on when the outcome may be a switched end state. It saves cycles even as it filters possible spikes from detected as valid input... which btw is the newest part of the process.
But with a cap across the same button, as Nick Gammon's blog shows, 2ms total could be possible.
If I'm making one to a few of whatever the project is, I'd go with the cap across the button.
If I'm making 100+; the cap and all it takes to have it in place may become a cost to cut.
What if you used this:
msNow = (byte) micros() >> 10; // get bits 10-17 of micros
Would not miss any counts but would increment every 1.024ms.
Even if I use the 2nd byte of micros, the debounce value would only be 4x millis and fit just fine.
microsUL = micros();
msNow = *(byte *)((µsUL) + 1); // I think that this should get the 2nd byte
But would it be faster or slower?
@Coding Badly:
I don't know if I had any luck with Python. I'm stubbornly running WinXP because of some games I like.
I don't remember how that ended up except for me not doing something or other I didn't have to.
I did screw around with Perl before. It's pretty friendly to do text processing with.
But now there's a reason to want. Ain't it "the way"?
I don't believe the digital inputs are Schmidt triggered or just
normal inputs.
If so, the inputs will draw extra crossover current with a
slow changing input.
If Schmidt triggered there is no issue.
Dwight
dwightthinker:
I don't believe the digital inputs are Schmidt triggered or just
normal inputs.
If so, the inputs will draw extra crossover current with a
slow changing input.
If Schmidt triggered there is no issue.
Dwight
Don't go by belief. Get the datasheet for an AVR and see. Digital read is heavily impeded.
I'm late to this party, but it's generally bad practice to look for a time that's equal to something.... It's better to look for greater than or equal to...
Imagine we are driving down the road and you ask me to drive one mile (or one kilometer) and then stop. If I look down at the odometer and see 1.1 miles, what am I supposed to do? If I'm a dumb computer program I'm going to see it's not equal to 1 mile and I'm just going to keep driving forever... But, if I'm smart I'm going to stop, and I might even tell you that we've gone a little too far...
I would bet that millis() is not deterministic in all but the simplest cases. That is, if the lower bits equal 0x00 at one point in a program loop they will not equal 0x00 at that point again until here are several rollovers. That is because other parts of the program will probably take different times to execute for various reasons.
Of course there is no reason to believe that the code is timed that perfectly anyway, so even if the same instructions were executed it wont read 0x00 at that point again until the code execution time again sync's with the millis() function when the lower bits are 0x00.
I would bet that millis() is not deterministic in all but the simplest cases. That is, if the lower bits equal 0x00 at one point in a program loop they will not equal 0x00 at that point again until here are several rollovers. That is because other parts of the program will probably take different times to execute for various reasons.
Of course there is no reason to believe that the code is timed that perfectly anyway, so even if the same instructions were executed it wont read 0x00 at that point again until the code execution time again sync's with the millis() function when the lower bits are 0x00.
Try writing some code that demonstrates what you say. Take what I posted and add tasks to it, you will need to disable interrupts badly to cause any such problems and you will still find the micros timer works.
The number-skipping that this thread is about is a different thing, it is not happening due to lack of CPU cycles... micros and millis are interrupt-driven.
There are solid proven reasons to believe that Arduino clocks aren't perfect, starting with the tolerance of the crystal or resonator and including the temperature during run-time.
But that does not verify speculation which is why I posted my questions as questions.
Thankfully I did get answers that addressed what is really happening in the chip. The millis timer skips the same values because of how it works, period. It could fix that at a cost in code and cycles that is not worth having when micros doesn't do that and covers close timing so much better.
My not-exactly-critical issues boiled down to:
expecting more from millis() than I should have.
not expecting the compiler to force int conversions where it did.
If you want to be more sure about time-keeping on AVRs then try
GoForSmoke:
Try writing some code that demonstrates what you say. Take what I posted and add tasks to it, you will need to disable interrupts badly to cause any such problems and you will still find the micros timer works.
The number-skipping that this thread is about is a different thing, it is not happening due to lack of CPU cycles... micros and millis are interrupt-driven.
There are solid proven reasons to believe that Arduino clocks aren't perfect, starting with the tolerance of the crystal or resonator and including the temperature during run-time.
But that does not verify speculation which is why I posted my questions as questions.
Thankfully I did get answers that addressed what is really happening in the chip. The millis timer skips the same values because of how it works, period. It could fix that at a cost in code and cycles that is not worth having when micros doesn't do that and covers close timing so much better.
My not-exactly-critical issues boiled down to:
expecting more from millis() than I should have.
not expecting the compiler to force int conversions where it did.
If you want to be more sure about time-keeping on AVRs then try
read up on a few different threads on Arduino timing.
write code and post a new thread.
Hi,
If you want to see how this works, write some code and test it. You'll learn about what i was talking about vs what you are talking about. You can learn a lot my writing your own code.
Something I never do, apparently, is write my own timing code or read datasheets.
Oh... wait....
From the first post of this thread:
Here below is the simplest sketch of the last few. I even made it collect then print to get print out of the way and it doesn't help. I've printed results on the fly and scrolled through 1000's of lines and never do the last hex digits equal FF.
From Reply #1:
The timer overflows every... (64*256)/16000000 = 0.001024 seconds ...so there is a bit leftover.
When the leftover reaches a full millisecond the count is increment by 2 instead of 1. This occurs roughly every... 1000/24 = 42 ...milliseconds.
Yup, it's rounding up the difference between 1000 and 1024 which makes every 42nd or 43rd value 1 higher than it should be the same way every time.
It's not being late or even early, it is a round-up.
That is consistent with the sketches I ran printing polled outputs, about 3 per ms that go up to FE FE FE and then show a double-wide set of 00's. When I lightened the code by removing the printing during collection it made no difference. I made a simpler sketch with less output to show just one point just for the first post on this thread and given that I got real answers quickly, it was the way to go.
Yes you can bung up a sketch that will do as you say but anyone can wreck a car too, that doesn't mean the car is defective.
Earlier, we'd said that we believed that millis() would average
out over some longer time.
If it only skips the 6 values, there is still a small error accumulated
every millisecond of about +0.144 milliseconds or .05625 percent.
Is millis() really doing the math and occasionally skipping an extra value
every 1777.77... miliseconds? or is it just skipping the fixed 6 values?
Dwight
dwightthinker:
Earlier, we'd said that we believed that millis() would average out over some longer time.
It does.
Is millis() really doing the math and occasionally skipping an extra value every 1777.77... miliseconds?
Each overflow interrupt the millis value is incremented by 1 and the numerator part of a fraction is incremented by 3. When the numerator reaches 125 (a whole number) the millis value is incremented by two and the numerator is reduced by 125.
1 + 3/125 = 1.024 which is precisely how often the overflow interrupt occurs.
dwightthinker:
Earlier, we'd said that we believed that millis() would average
out over some longer time.
If it only skips the 6 values, there is still a small error accumulated
every millisecond of about +0.144 milliseconds or .05625 percent.
Is millis() really doing the math and occasionally skipping an extra value
every 1777.77... miliseconds? or is it just skipping the fixed 6 values?
Dwight
It doesn't skip. Every 42.some ms it returns a value that is +1 to what it should be.
Poll millis and see for yourself, use the highest baud rate you can if you print while polling.
I used 250000.
............
FE
FE
FE
00
00
00
00
00
.............
Some of those 00's should have been FF's and the rest really were 00 but those and the following 01's, 02's, were right until the next time the return value was +1 then the very next value was +NOTHING.
MrAl:
I would bet that millis() is not deterministic in all but the simplest cases. That is, if the lower bits equal 0x00 at one point in a program loop they will not equal 0x00 at that point again until here are several rollovers. That is because other parts of the program will probably take different times to execute for various reasons.
There are two issues here:
Will millis() ever be wrong? - for example due to some ISR taking a long time, or interrupts being turned off
Will millis() always skip the same values?
The first one is easy. Yes, millis() can be wrong. If you turn off interrupts for 5 seconds then it will be out by 5 seconds. Plus there is the issue of the accuracy of the hardware clock.
However: It will always skip the same values. Regardless of when the ISR is called, on-time or not, it will always do the same maths, and always skip the values shown in earlier posts.
You mean wrong from the standpoint of real time? Yes i cant agree more. I made a clock timer with one Arduino and found the time was off by several seconds within a mere 24 hour period. The calculated crystal frequency however matched as close as i can get with a short wave radio measurement. So it looked like the millis() function was following the clock nicely, but since the crystal was off by a small amount the time of course would be off by a small amount. After software calibration it was better, but of course wont match a Real Time Clock module.
This other issue is new to me however. I was not aware that the millis() function would actually skip some counts, if that is what you are saying. I guess i never thought about it. So i guess it could go as: 1,2,3,5,6,7 etc., and never show that '4', but what about after more time has passed, i guess it just skips other counts then? Any reason for this?
In spite of that, it appears that if in that example it does skip the '4', when it contains the '7' it is still valid that there have been 7 ms passed, at least within the limits of the crystal accuracy.
What i was talking about previously was the synchronization of the millis() with the program code address location at any given time. Not important at this point though
As long as you do unsigned subtraction of start time from end time, you get a positive difference regardless of rollover between the two.
With 32 bit unsigned longs you can time differences up to 49.71-some days.
With 16 bit unsigned ints you can time to 65.535 seconds.
With 8 bit bytes you can time 0 to 0.250 seconds in all cases. 0.255 in most.