benblazak / ergodox-firmware

firmware for the ergoDOX keyboard
Other
596 stars 294 forks source link

Min time value to repeat the same key #60

Open Thanatermesis opened 9 years ago

Thanatermesis commented 9 years ago

I don't remember if this was finally posted in an issue or was just a comment somewhere long time ago but in any case let me open an issue for it...

Sometimes my keys are pressed twice "by an unknown reason", sometimes even 3 times, these keys are random based on time (seems like it can some possible dust in the connector that stalls for some days and then other keys can have it too), the only known solution is to increase the debounce time, but this causes major issues:

In my last test I needed to increase it to 40, and the spacebar continued to be pressed more than one time, very annoying, this value is not good because there starts to failing the keys in another way, for example you can type things like "welcome" and having results like "wlecmoe" (some keys are send before to other ones)

So the best solution could be to save in a temporal variable the name of the key that was last pressed, and if the firmware wants to send the same key before x-min milliseconds passed, then ignore it (a value in milliseconds that is not humanly-possible to type, on such case should be connector-errors)

Thanks Thanatermesis

pnickolay commented 9 years ago

I have similar problem after re-soldering different LEDs (maybe i screw something else up in the process). Do you have a change list for this change? If not, I can implement it and share, but not sure when I'll have time.

Thanks

Thanatermesis commented 9 years ago

This is simply speculation but I don't think that the problem is because you re-soldered it, I think that is just micro-dust that exists in the air and the key connector has sometimes more "multi-micro-clicking" while sliding (pressing/releasing)

Yeah this is probably the most annoying and wanted thing on the firmware right now :)

benblazak commented 9 years ago

@Thanatermesis: I remember you mentioning it (along with a lot of other interesting stuff) but it's good to have it as an issue here. I think the best way to fix it would be to copy something I saw somewhere, probably in Hasu's firmware. What they were doing was scanning as fast as possible (much faster than 200Hz), and if the scan for a key was the same 5 or 7 or something times, then it would register a change to that state. This wouldn't be hard to do: currently, I'm using two bool arrays, IIRC, one to store the previous state, and one to store the currently scanned one; it would be much better to use one array of uint8_t's, and updating the array by shifting the current value left and then or'ing in the bool value of the current state. Then we could examine the last few bits, and if they were all the same we could trigger a state change.

This wouldn't work quite as well in our case, because I2C slows things down a lot, so we can scan at a max rate of ~3ms -- and it will be unpredictable how long a scan will take, once i get the macro code working (if i ever have time...). But this method would probably work pretty well :-) . If only I had time to work on it...

Thanatermesis commented 9 years ago

@benblazak how we can give you some time ? :)

The other's firmware thing sounds interesting, but im not fully convinced... it sounds like a solution that that they found for a normal problem (at that speed, the keys would have been pressed multiple times for sure, so they needed to skip some cycles), but on real world if a key is pressed multiple times along its sliding-movement (micro-pulsations caused by dust), it is even possible that from that "5-7 times scanned the same key" could include 1 or more cycles without it pulsated (let's say, during the traveling of the key it could be on each of these extra-fast scanning cycles: ON, ON, ON, OFF, ON, ON...), on such case we would still having the same problem

By other side by saving the last key pressed in a variable, which is also inmediately printed, the next time a key is pressed is checked against this one and if is the same, it will be simply skipped. Or even better (not sure how hard is to do this in C), an array of keys stored dynamically that lives "per time", where the key is removed after an X amount of micro-seconds has been passed (an amount that is not human-possible to type at that speed), so if a key pressed exists on this array will be skipped... in any case the first solution sounds good enough.

What is the thing that you want to do about macro exactly? I personally wrote my own macros like here: https://github.com/Thanatermesis/ergodox-firmware/commit/ec4dddbae967a73569f2eb8e31d90d527721bd4a , maybe can be useful for somebody :)

benblazak commented 9 years ago

@Thanatermesis: lol -- by reorganizing the universe so that work and school are either completely unnecessary, or at least not time-contained :-)

I'm not sure we understand each other correctly about the alternative method of debouncing... Sadly, I can't find where I originally read about it (it must have been a forum thread). As an example though, say a key hasn't been pressed for a while; its position in the scan matrix would look like "00000000". Then it gets pressed. On the first scan, it's position now reads "00000001", then "00000011" and so on. But maybe there's some jitter, so we eventually end up with "00111011", similar to your example. If we were considering the key pressed (or released) after any three consecutive consistent readings, the first "111" would have triggered a press, the "0" in the middle there would have been ignored (since there's only one consecutive "0"), and the "11" at the end would just be continuing the "press" from the leftmost "111". On then other hand, if we were only considering the key pressed or released after any 8 consecutive consistent readings, this byte would not trigger anything at all: they key would only be pressed after reading "1" for 8 consecutive scan cycles, and only be released after reading "0" for 8 consecutive scan cycles.

It would be possible to keep the last key pressed in a variable, and check against that -- but what about when a user is trying to press two keys at a time, and actually succeeds? Especially with NKRO (if that ever happens) this approach could get complicated rather quickly (lol... kind of like keyboard firmwares in general...). It would even be possible to have the keypress records expire -- my firmware currently has the ability (at least in partial-rewrite?) to schedule function calls. The problem is that i've designed things based around the scan cycle (at about 200Hz, and we can't scan any quicker than every 3ms or so, because of I2C) as the basic unit of time. So, trying to handle keypresses based on real time might not be the best way.

As for macros, i was trying to make it so that they could be recorded onto the EEPROM from the keyboard without flashing anything to the Teensy from the computer (as in, press a special key sequence -> record a macro (and assign it to a key) -> press another sequence to end macro recording -> replay the macro as you like). I think I worked out most of the challenging parts (took forever!) but then school started again, etc., and i haven't had time to mess with it since.

Thanatermesis commented 9 years ago

It would be possible to keep the last key pressed in a variable, and check against that -- but what about when a user is trying to press two keys at a time, and actually succeeds?...

Well, Im not sure about how really the "send" code works but I was assuming some simple "validate before commit" key flushing

So, trying to handle keypresses based on real time might not be the best way.

I don't know how much it could affect in real-time speed, but if this info is useful, I can work up to 40 milliseconds in the "debounce time parameter" (more than this becomes annoying when typing, looks like sometimes a key is printed before another, when i feel to have pressed it after, not before). Yeah it can sounds too much but I have sometimes troubles with this exact issue about repeated keys that I need to set it to more than 40, I have even see it repeating at 60, but more than 40 is not very workable :)

benblazak commented 9 years ago

Pressed keys are collected in an array every scan cycle, and this array is sent to the host computer, which determines on its own which keys were pressed before and aren't now, or vice versa (and also tracks the amount of time keys have been pressed, for the purposes of auto-repeating, etc.). If more than one key changes state within the same cycle, both changes get sent to the host at the same time, and the host interprets them as being pressed (or released) in an arbitrary order.

Different people have different sensitivities to scan rates. You seem to be particularly tolerant, lol :-). Cherry lists the debounce time as 5ms though, so anything above that really means we have a problem somewhere... Even though these ideas might go a long way towards handling those problems in software :-).

Thanatermesis commented 9 years ago

Mmmh... that sounds complex

Well, I have noticed the ALPs keys (matias) to allow the debounce time to perfectly in 1 or 2 ms (i dont remember which was), they works without problems but by other side, in a random way (affected keys changes over time) some of the keys start to be very multi-pressing prone, for example some months ago I was very annoyed with the E key and another 2 ones (but specially the E), right now they works without problem but Im affected now (even more) by the spacebar, I need to work at a 30 debounce time to avoid as much as possible duplication of spaces :/

Yeah, a good solution would be to replace the affected keys :) but as said, they changes randomly, my speculation is that the cause is micro-dust that finds the slider contact pretty comfortable :þ

Thanatermesis commented 9 years ago

tomorrow im going to replace my space key with a different one, let's see if a different key makes it to have less double-pressings, I start to be unable to work with these too much keypresses :/

benblazak commented 9 years ago

Hope it works! Let me know :-). I've been curious whether these double pressings are more an artifact of the specific switch, switch type, or something about the rest of the board that I don't understand...

Thanatermesis commented 9 years ago

placed it for another day, I have not get the solderhere at work today

Well, it sounds to me a switch problem, i would say "dust", another possible things doesn't come to my head, except a welding problem, which can be another option too...

Note: this text is writed with the space problem, you can notice here the amount of "double space" affected and also sometimes it is not even pressed (hum... that can be my debounce at 24 (now), idk)

note2: seems like the wiki-github comments removes the double spaces so you cannot see them in fact on this text lol

Thanatermesis commented 9 years ago

Humm... desoldering not needed I just tried to move my debounce to "2" (actually im typing at 2), and noticed that i got between 4 and 8 repeated presses in the space switch, so i tried to know if is the contact of the welding, by simply moving the "piece" a little from the board while pressing, or by slowly sliding the switch... the problem is in the contact itself of the key (so the switch sliding, not the welding), I tried to open the key to see if i can "clean" it but it seemed to be not possible since its solded, so i just did a big blow (you can see holes in the slider that communicates directly to the contact) and... see! not even a single double-spaced pressed on this text at 2-ms debounce time :)

So yeah, the problem is random dust, confirmed lol

(omg i can work back nicely and without needed to change the key :))

benblazak commented 9 years ago

Lol, awesome!! Glad you got it working :-) . Must be a dusty environment you're in...? lol.

You can open the switches, by the way (or were you doing something non-standard with your board?), by prying a little (gently) at the four clips on the bottom side of each switch, through the four indents around each switch in the acrylic plate. It's a bit of a trick to get them all open at once (at least, with a paperclip), but it can be done :-).