Manipulating a pushbutton matrix - Page 1
Forum section: electronics / general

author: Stinos
author_rank: Newbie
timestamp: August 25, 2021, 10:39:45 am
content: Hello all,I am currently working on designing a force feedback steering wheel for sym racing. I am almost finished with the mechanical design but I have a hard time figuring out how to implement the button matrix that the stm32 blackpill I use. The blackpill uses a matrix like shown in the picture below:When reading the blackpill will pulldown pins PB13 to PB9 sequentially and then read pins PB0 to PB11 in order to know which buttons are pressed. Nothing weird here. The crux is that for my wheel I am limited to four pins that go from the base to the wheel because I use a slipring design in order to have no wire fatigue. My plan was to use an Arduino nano in the wheel which reads the buttons, Then send it via IIC to a second nano which decodes the signal and then sends that signal to the blackpill.The second nano will read pins PB13 to PB9 and manipulates pins PB0 to PB11 in order to simulate a button press on the blackpill.The problem is that the pulldowns on the blackpill happen seemingly randomly, differ in length, and the reading on the blackpill happens at the beginning of the pulldown. This means that the nano needs to respond within a microsecond in order to fire on time. I tried to use port manipulation on the nano in combination with interrupts but even when only using one read pin instead of five it is still to slow. I hope that there is maybe a faster way. Maybe a 16 or 32-bit development board would work.I hope you guys have some tips.Greetings,Stinos

author: DavidAlfa
author_rank: Super Contributor
timestamp: August 25, 2021, 01:17:30 pm
content: Scanning 24 buttons and have microsecond responseYou're asking too much, you have capacitive and inductive loads that will limit the reading speed.Instead turning the pulldowns on and off, just leave them always on.Remember you have a capacitance, you must wait few uS after turning on the output or you'll have inconsistent readings, so at best you might scan the whole matrix on 50-100us.Instead of another mcu, why don't use a dedicated i2c keypad matrix scanner, ex. TCA8418?Oh, won't you actually believe that 1000Hz gaming keyboards actually refresh the whole matrix at that speed?It's marketing crap, the USB might update at that speed, but by no way the keypad can update so fast!

author: Stinos
author_rank: Newbie
timestamp: August 26, 2021, 04:54:56 pm
content: First of all. Thank you for replying on my post. The tip to use a matrix scanner is really good. To be honost I didn't knew that it existed and I am probably going to use it in the final design in someway. Unfortunately this is not the solution for the real problem. See, the blackpill is precoded and setup to directly connect to a button matrix like in the picture. An IIC bus wouldn't work for that reason.Furthermore, I don't need to scan for 24 buttons. I need to scan for 5 pins and digitally write 5 other pins in order to simulate 25 button presses. The 5 input pins fire sequentially after each other but the length of the pulses differ allot between cycles making it hard to predict when a certain pin is going to be active.Also capacitive or inductive loads are not a problem to me. I'm used to worse cases then 1us in class :p.Lastly I cant leave the pullups turned on al the time because that would trigger 5 buttons when i only press one.

author: RES
author_rank: Regular Contributor
timestamp: August 28, 2021, 08:04:34 pm
content: With 4 i/o pins you scan 16 buttons max. by using diodes like this.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 28, 2021, 10:17:00 pm
content: Quote from: Stinos on August 26, 2021, 04:54:56 pmIf you cannot change the code in one location (the blackpill), then you need to directly emulate a matrix,thus you may need two MCUs whose code you can control, on each side of the slip ring.They can be identical, and you could even have one hex file for both, by using a pin to select RX or TXQuote from: Stinos on August 26, 2021, 04:54:56 pmThat may be due to the MCU running other interrupts, and usually keypad scan does not care about ms of jitter.If you run a pin change interrupt on every line, you should be able to auto-sync to any jitter.Assembler should be faster, but if even assembler is not fast enough, another approach is to delay from the earlier edge, long enough so that the first sense point is ignored, and the desired (next) one is caught. ie you pull lowearlierthan the keyboard checks.

author: Stinos
author_rank: Newbie
timestamp: September 01, 2021, 10:06:50 am
content: In my current setup I'm planning to use two MCUs and indeed at either side of the slipring. The bad thing is that because of the jitter I can't delay an earlier edge as the time to the next one is not constant. Even worse, it varies by a factor two or three ish. My next approach can be either of two things:I can just use two nano's in combination with or gates. Because a button press is an active low I can use or gates. The two inputs of the OR-gates are connected to the nano's output and the blackspills 'output'. And the output of the OR-gates are connected to the blackpills input. I tested this and it works a charm. bad thing is I need around 16 buttons and thus 4 quad channel OR-gates which is bulky and ugly. Also because every button needs a pin on the nano for this to work.The next approach is more complicated but way nicer. I will use a teensy for the matrix manipulation. A teensy, depending on which variant, can run up to 600MHz clock speeds. That is about 38x the clockspeed of the nano. If I can manage to program port manipulation into the teensy it should run 38x faster (very theoreticly). Because I only need around a 3-5x faster response compared to the nano to get a stable button press it should work for sure. The only problem is that coding a teensy will be a bit of a headache. But I am going to try it non the less. If someone has some tips on how to use interrupts and port register manipulation it would be much appreciated.