I'm attempting to read simple (read cheap stuff from eBay) encoder, wired into button matrix. I've connected two outer pins from encoder to separate rows, and middle pin in a column. I actually managed to get some readings (still not very stable, but fixable in software), however, that's not the issue. I have a 8-column button matrix. Each column is active for 1ms. Given that there are 8 of them , it takes 8ms to read encoder again, which is too slow, and it skips lots of turns (code worked while I limited code to only one column).
My matrix input rows are connected directly to Arduino, as well as output rows, and columns are controlled via 74HC238/ULN2803. What approach should I take to connect multiple encoders in button matrix? Do note that I also have LEDs on same columns as buttons.
I was thinking of separating LEDs to other columns, and then to swich columns with inputs much faster (in microseconds). What do you suggest?
What approach should I take to connect multiple encoders in button matrix?
Sorry but the approach I would take would be to forget it.
Polling rotary encoders is tricky at the best of times so adding the further complication of a matrix into the mix is going to make it impossible.
If you can scan the matrix fast enough for the encoder then it is way too fast for the LEDs.
It depends what the rest of the system is doing but if you do not want to use interrupts, which is the normal way then you could pole repeatedly between matrix refreshes.
Grumpy_Mike:
Polling rotary encoders is tricky at the best of times so adding the further complication of a matrix into the mix is going to make it impossible.
If you can scan the matrix fast enough for the encoder then it is way too fast for the LEDs.
I realize that. That's why I asked would be a good idea to have two separate matrices - one for buttons, other for LEDs. The button matrix would work by keeping one column active 125us - or 1ms in total for entire matrix.
I can't see any benefit in that. You would waste time setting up the matrix so I would just use one and make other arrangements for the rotary encoders.
Since it is important, dedicate two specific MCU pins to it.
While there is no "too fast" for multiplexing LEDs, the actual code "loop()" should if correctly written, take far less than a millisecond to execute, polling the encoder on every cycle; interrupts should not be necessary at all but (and particularly because) you do need to debounce the encoder for a few milliseconds anyway using a proper debounce routine, not just reading it only every few milliseconds.
Your delay code, working by polling millis(), can step the multiplex on your matrix every two milliseconds or so, a refresh of 60 Hz or so will be just fine for LEDs and buttons though you probably want the buttons fully debounced as well.
Paul__B:
Since it is important, dedicate two specific MCU pins to it.
While there is no "too fast" for multiplexing LEDs, the actual code "loop()" should if correctly written, take far less than a millisecond to execute, polling the encoder on every cycle; interrupts should not be necessary at all but (and particularly because) you do need to debounce the encoder for a few milliseconds anyway using a proper debounce routine, not just reading it only every few milliseconds.
Your delay code, working by polling millis(), can step the multiplex on your matrix every two milliseconds or so, a refresh of 60 Hz or so will be just fine for LEDs and buttons though you probably want the buttons fully debounced as well.
Did I understand you correct - 8 column matrix with inputs/outputs can run just fine with 2ms cycle around all columns?
EDIT:
Ah, 2ms per column. Isn't that way too slow for encoders? Also, you're saying you can't multiplex LEDs too fast, Mike says you can. I agree that interrupts are a bit crazy to use directly on encoder since that assumes I debounced it using hardware, which I haven't.
No i didn't say you could not multiplex the LEDs too fast, I said you were multiplexing them faster than you need to. That wastes time setting up the matrix addressing.
Interrupts are not crazy, if you write your code correctly debouncing happens automatically due to the code the encoder produces.
No, I said as Mike did, that you really need to dedicate two pins to the encoder alone, and forget about using it in a matrix.
Unless you plan to poll that specific part of the matrix on every cycle of the loop(), meaning many times per millisecond, which is going to be very painful as you would need to immediately revert to the "current" state of the matrix scan without introducing "phantoms" on the LEDs.
It is clearly fine to poll single buttons in a matrix as you simply cannot change their state very quickly at all. The rotary encoder is a tricky matter as it will have contact bounce, so you need to determine an optimum debounce time.
"Proper" debounce as I describe is not merely polling it every few ms, but polling it on every cycle of the loop() and determining whether it maintains a given new state consistently for the entire chosen debounce interval (determined by polling millis()). Much the same applies to the buttons in the matrix though you can actually only poll them as often as you cycle through it - you might require them to be the same say, four times in a row. A convenience of the matrix is that you can hold the state of eight buttons in a single byte and debounce by requiring that byte to stay unchanged for the predetermined number of polls.
Software debounce is substantially superior to hardware debounce (except for the "R-S" gate form) as it effects a much "sharper" filter.
Grumpy_Mike:
Interrupts are not crazy, if you write your code correctly debouncing happens automatically due to the code the encoder produces.
No what makes you say that?
You can make any pin into an interrupt pin by using the pin change interrupt, or any other number of techniques.
You can't say it has to be multiplexing.
Paul - yes you can action every click, the ones you don't action are the false debounced ones.