[solved]Q8 switch debouncing-time (A hardware property of the switch that I wanted to know)

So, playing with alternative software for the Q8, I'm getting some instabilities.

(but removing that as they were described out of frustration and not the issue or question)

I'd like to put one distraction to rest so, the original one and only question, that was always in bold like this:

One question : What kind of timescales are other e-switch lights using for debounce? I'd like to make sure that I've at least really licked the debounce problem. Trying to rule things out. At the moment I have 8ms. 1ms already seemed like enough. I don't think increasing to 8 helped, but I'd like feedback from others on that, again to rule this part of things out.

In my latest firmware I use a timer interrupt of 16 ms to poll the switch pin. I use pin change interrupt only to wake up from sleep. A changed level at switch pin is only accepted if detected in 2 consecutive calls of the timer interrupt - which means a debouncing window of 16 - 32 ms. Works flawless in Q8 and D4 up to now, not a single bounce problem occured. My firmware also uses the watchdog interrupt, in order to flash the switch LED each 4 seconds in lockout mode.

I guess you know that watchdog has to be reset (wdt_reset) after firing if you don’t want it to cause a complete mcu reset. And a WDT interrupt function has to be there even if you don’t have any code in it, otherwise you will get a mcu reset too. An empty WDT interrupt is declared with “EMPTY_INTERRUPT(WDT_vect);”. But since you disabled WDT interrupt this shouldn’t be the cause for the problems.

In order to recognize if a mcu reset happens unintentionally I would blink out some long specific pattern at program start.

This might apply:

There are at least three different solutions in the firmware repository. Use the source, Luke.

The content is way above my level of understanding, but from other posts you made I gathered this is not Narsil but a reworked version of Bistro you made yourself right?
Maybe good to mention that in OP and title so not to confuse people with a Q8 running the good functioning Narsil?

The title of this post is very misleading and thus verging into rude territory. The OP and title need to be more clear that these issues are using alternatives to Narsil.

@The Miller, yeah, wrote that a little quick, it does look confusing on second look, will clarify (although I'm not ruling out hardware issues here yet, and I'm not even 100% certain Narsil was more stable on this particular light, I didn't try to click it 150 times)
@stephen k, your response was certainly not "verging into" rude. Ok?
@TK, it's a two-line code fix -- wait, clear, and it seems to be working fine with the right wait time, so I think the lab with the right piece of input data worked.
Thanks flashy mike.
Yes of course I also don't rely on pin change interrupt to infer pin state. I don't think it's necessary to check for agreement of consecutive readings, just to wait long enough until it's sure to be stable, or stable assuming the finger itself isn't still indecisive, in which case stop wiggling your finger. My real concern here was stack overflow from nested interrupts (that should have been impossible anyway, but something is happening). I think my debounce quit working when I put stronger batteries in, but increasing the time seems to have fixed it again, but is uncorrelated to the lockup. I managed to find discussion elsewhere too that 8ms is probably a bit too short for typical switch hardware.
Yeah I know the watchdog can reset (HD-OTSM uses the same watchdog loop, and it never locked up, and my e-swtich test build didn't either.) Actually if the watchdog is used in interrupt only mode, it doesn't cause resets, but anyway, I wish I was getting a reset. Then I could carry debug info in noinit variables and blink that (and I long ago made a preproc define for just that).
Basically the appropriate action for short and med clicks is a soft reset of sorts anyway, although bypassing an initialization section, or for long press it stays in a sleep loop. However either of those re-lights the indicator, one goes to sleep, one turns on the light, and both leave the voltage output high, but it always locks awake (full power draw, definitely not in WD sleep loop), with the indicator off, and with the voltage pin floating.
So it's not restarting, but it's not sleeping in the button press loop either. It seems really locked up hard. The reason I suspected watchdog was potential problems restarting power, not concerns over resetting the code. If it was running into any normal code path, yeah, I'd detect that I think.

Not at home, so just a short remark:
I’d never “wait” inside a interrupt function. Best practise is to leave it as fast as possible.

Again, you title implies it is about stock Q8 with Narsil
Please add it is about your own software

I know you (almost anyone) wouldn't, but there's nothing wrong with it.

Bistro-HD is nothing like conventional. Bistro was not setup asynchronously from the start and being based on and still for clickly lights, it was originally designed to restart entirely, check the cap, restore last mode, change modes, and then go into a wait loop at the right mode, polling voltage and temperature in the loop, not by interrupt.

But for bistro HD OTSM I don't get power off, I get a pin detection, that needs an interrupt, and it needs to go to sleep fast, but in the end the simplest way to interface without completely rewriting bistro (likely at bigger size) is to measure click time (when it should wake up from a sleep loop), "save" it (in some way) and restart, and that's what it does. And if it's restarting anyway, why bother returning from the first interrupt? The first pin change interrupt calls a subroutine(in unreleased version) that is the sleep loop and you can just think of that as no longer an interrupt but as the new "main" until the end of the code. Pin change interrupts now break from within that and return to that, until the right time to restart. I can detect a short click, medium click, long click powered restart and power-off restart all independently. The last one is detected by using a code section in the binary called .init3 that happens before main and is skipped on the powered restart.

At the C code level it's a bit of a hack sure, that would make people who like to do what they're taught cringe, but there's nothing really wrong with it. (If you're really observant you'll notice that it's an infinite loop that can cause a stack overflow, but that's avoided simply by resetting the stack pointer to make the restart really just like a restart, minus that init3 section). I'm careful to initialize variables deliberately, not automatically.

So to me, the interrupt is just a code path that runs from first pressing the switch until restarting the light. And once e-switch came along, I already waited to count time there, in a low power state, so why not just keep waiting after a long press, and that longer wait is called "off". I just added state indicators that progress in the loop from standown to either short press restart or medium press stand-down, to either medium press restart or long press stand-down, to off, to standby (button pressed from off) to on (button released). In the next release it's even understandable.

Could I have broken the code intro into some setup() routine, had the interrupt set a flag, unroll, set conditionals to bypass all the next strobes and slow temperature checks (admittedly temp and adc should just then also be made asyncrounous, so really now you're writing Narsil) on the way back through, got the end of the loop, checked the flag, re-called setup() to make new mode decisions, including adding a new off mode, continue on the next loop iteration. Well sure, possibly at the expense of slower OTSM power-off, and I considered which way to go, but that would have been much more code I think and not clearly in any way simpler. HD fits a pretty good amount of code in an attiny25.

On the other hand, at the moment, something doesn't work, on this one light at least. I'm not ready to just say, bah.. it's all a mistake. Bugs happen. This one is frustrating though. I may just have to buy another switch light to test :).

Anyway, good comments, gives me things to think about.

As for empty dogs, I only read about after I "wrote" this:

// watchdog interrupt handler -FR
// gcc avr stacks empty interrupts with a bunch of un-needed initialization.
// do this in assembly and we get one instruction instead about 15.


__asm__ volatile("reti");

(which is the same thing). I also write the PWM and timer interrupts in asm though, also naked, and pass control bits in through the GPIOR register bits because they can be accessed in a naked interrupt without touching working registers. Unfortunately gcc uses a boilerplate interrupt template that wastes quite a few bytes protecting registers even if your interrupt only uses one. Of course if you write for attiny85, saving these few bytes maybe isn't worth it.

I though TK did the most thorough development and testing in this are of handling debounce. In the Narsil history chain, I simply used what others had already done, not knowing of any problem or issues, but TK's latest support in Anduril seems the most robust, thoroughly tested, best design, etc.

Not sure why you want to reinvent the wheel without looking around though. The switch mechanisms I'm sure have some variation, but the one the Q8 uses is pretty much the same as many other lights.

Thanks for the feedback.

"Q8 switch debouncing" doesn't imply anything about Narsil to me. And the first line of the post clearly says I'm playing with alternative firmware.

However I guess part of the confusion comes possibly from lack of familiarity with that subject line, which others may have more than you.

I added Q8 switch debouncing-time, to make it now clearly about the property of the switch and the amount of (de)bouncing time related to it. Hopefully that helps you a little. That's now a noun and it is certainly hardware property, not a software verb. As it is a hardware property, the software, any software simply must accommodate it.

Again, the question of necessary debouncing time is not dependent on choice of software. Whatever it is, that's what any software will need. The "instabilities" is something presently only manifested on non-stock software, so I removed that term.

For the record, Tom E had a theory that this is related to electronic noise more than actual switch noise. After a little reading and now this information, I have doubts. Electronics can fix it, by damping the effect, but the time scale seems to depend on the switch used, and time scales of 20ms seem kind of long for electronics noise, but I'm not sure.

It's two lines of codes, and one of those will probably need to end up being a watchdog sleep in the end to be compatible with OTSM if any OTSM or dual OTSM/switch light ever needs it (also driving a minimalist approach), and it's not in anything like a conventional interrupt environment anyway. Sorry, but I really don't see debouncing code as anything. It's like looking up code to count to 5 because somebody else already did it. The switch settles. Wait long enough and it's settled. That's it. I got it long enough now and I don't have a debouncing problem now. Done.

Although my other maddening bug that also contributed to my writing this is still not solved, that seems to be, and I marked the thread title accordingly.

I don’t care what is in the first part of the text, I care about having Q8 there in the title.
Please remove for just the thing I quoted here.
And knowing you the next change could very well be:
[solved]Help, e-switch like Q8 switch debouncing-time, etc
I will then ask for addition of “when flashing non Narsil/FSM firmware’
You got your traffic and attention of people who know about this stuff, please stop having this potentially very confusion title for the remaining 95%+ of Q8 owners :wink:

Though above my level of understanding it sure is interesting and probably very good to talk about, so removing the need for me to react and you to respond to me can only be good right?

I agree. It’s obviously a problem with this specific firmware and not with Q8.

The debouncing time is not a problem. It's just a debouncing time, and has nothing to do with any particular firmware. That is the subject. It's simple and I don't see it causing any undue hype and didn't intend it to. I shouldn't have mixed the other bistro-HD issues in the title or the probably the post at all, and already removed "instabilities" from the title after The Miller kindly pointed out concern the first time, and now removed it from the post too.

However, with all respect, I draw a line at making debouncing time into a software specifiic issue, because it's factually wrong. It is not a software specific issue.

After a certain time the voltage on the switch will be in, and unless the switch is moved again, will remain in a single state. That's a fact, a fact about the hardware. (It also happens to be a fact about why debouncing algorithms, don't need to be complicated, de-noising is another issue, ie if you have spurious spikes not related to bounce.)

For what it's worth, debouncing and noise rejection aren't the same thing. Noise is a signal that's not generated by a switch press at all but by something else. That requires more subtle rejection if it exists, but it shouldn't exist. I am NOT seeing any evidence for noise events. Only bouncing. For bouncing, the switch will settle after a certain time after which the voltage then will represent the switch state reliably until the switch is toggled again.


Flintrock, You seem to be fizzing with enthusiasm and energy, please don’t stop, it’s great, we need it, but maybe also think about how you project yourself to others.

Do a diff on Bistro-HD vs old bistro. I don't care what you think I did to it though.

It's a simple question, how long does it take a Q8 switch to settle to a constant digital value. I seem to have close to an answer. I don't need all the drama. Sorry for also opening up with another frustration. You these plots:


Those are all switches bouncing. They all stop bouncing after a certain time.

If you want to discuss the FACTS of debouncing, head over to my new thread on that. I'm not interested in the mudslinging. There are facts in that thread, and you know facts from other people, not all research has to come from BLF to be not going one's own way. And by they way, those facts are working out just fine.

I wanted to know how long THE Q8 switch bounces. It's my thread and that was MY question. Your response does not address it and is off topic.

Computer science? lol..

Flashy Mike for what it's worth your debounce time information was probably useful and your watchdog statement actually ended up at least the right idea. Better to post replies about that if any here:


Anyway, my dumb debouncer seems to be pretty solid. It's just a very different context though from most of them, a context that happens to lend itself well to, and benefit more from, this very simple solution.