Hello again all, I have a question. So I have several Arduino boards (1 Mega 2560 R3, 2 Uno R3, and one Leonardo to be specific). Anywho, I have used the Mega to make some random miniproject that uses a 4x4 matrix keypad in order to learn how matrix encoding works. The keypad interfaces with the Arduino using 8 wires, as you probably already know. For reading the keypresses, I am using the Keypad library written by Mark Stanley Alexander Brevig. So far, so good. But what I want to do now is use an Uno to act as it is the matrix keypad and somehow send signals to the Mega, simulating keypresses. And I want the Mega to not know that it isn't reading from an actual keypad, so I don't want to modify the code or any circuitry the Mega is running (not want to, but rather I am making this a requirement). Reading the code for the library, this is the function that actually scans the states of each button.
void Keypad::scanKeys() {
// Re-intialize the row pins. Allows sharing these pins with other hardware.
for (byte r=0; r<sizeKpd.rows; r++) {
pin_mode(rowPins[r],INPUT_PULLUP);
}
// bitMap stores ALL the keys that are being pressed.
for (byte c=0; c<sizeKpd.columns; c++) {
pin_mode(columnPins[c],OUTPUT);
pin_write(columnPins[c], LOW); // Begin column pulse output.
for (byte r=0; r<sizeKpd.rows; r++) {
bitWrite(bitMap[r], c, !pin_read(rowPins[r])); // keypress is active low so invert to high.
}
// Set pin to high impedance input. Effectively ends column pulse.
pin_write(columnPins[c],HIGH);
pin_mode(columnPins[c],INPUT);
}
}
So from what I understand, I would have the Uno listen for a specific column to go LOW, and then set the corresponding row pin LOW for the key I want to have pressed as well (it states in the comment "keypress is active low so invert to high") and leave the remaining rows HIGH. Is my understanding correct? And if not, could someone please explain the correct way to do this.
My second question is, other than the 8 wires that would connect the Mega to the keypad (or to the Uno if we're not using an actual keypad), would there be any other connections required (I can think of connecting the grounds of the Mega and Uno, but I'm not sure if this is a must). I want to keep the connections to as few as required, and also keep the components to nothing more than the wires and Uno if that is possible.
Your understanding is correct. On the Uno, the column pins will be inputs (INPUT_PULLUP) and you will have the row pins be outputs that you normally keep HIGH.
When you want to simulate a keypress, you have to set the correct row LOW. You don't really want the Uno watching the column pins since the Uno would have no idea if/when the mega is actually scanning the keypad. To simulate key presses, you would set the row(s) LOW, wait a small amount of time (~50-100 msec) and then return them HIGH. That is what a real keypress would look like. It is up to the Mega to scan in a timely manner and detect this.
ALSO - you must connect the grounds together or strange things may happen and you won't know why
I actually decided to switch the boards, and use the Mega to simulate keypresses (it'll be clear as to why in a moment). The method I came up with (it works currently, but I'm not sure if it'll be stable in the long run) is to use interrupts (specifically a FALLING edge on a column) to determine when the Uno (was the Mega in the original question) is scanning the column that has the key I want to simulate. Once the interrupt fires, it immediately pulls the corresponding row to LOW and switches the interrupt for that column to a RISING edge, which will bring the row back to HIGH. This of setting interrupts for a given column will continue until the Uno is done reading keypresses.
I decided to use the Mega for the simulating of the keypad as it has 6 pins that can be used for interrupts (2, 3, 18, 19, 20, and 21), whereas the Uno only has 2 pins (2 and 3). The original project functions 100% normally when running on the Uno, so that isn't a problem.
I guess my question is now will my current method be stable, and if not, what modifications can I make to make it stable?
The only concern I would have is that the scanning code pulls column LOW and then immediately starts reading the row values. You Mega is in a race condition when it receives the interrupt to get the row pulled low before the Uno reads it. Apparently, the Mega is winning the race. The shortest time would be whatever key corresponds to the first row.
blh64:
The only concern I would have is that the scanning code pulls column LOW and then immediately starts reading the row values. You Mega is in a race condition when it receives the interrupt to get the row pulled low before the Uno reads it. Apparently, the Mega is winning the race. The shortest time would be whatever key corresponds to the first row.
When I tested that idea, I did use the first row. And I think it worked (I emphasize think as the Uno responded as if it received the correct button, but I'm not sure how many times it scanned before it lost the race and caught the signal). I did think of just ignoring the column lines and pulling the required row LOW, but I was worried about the Uno reading it incorrectly by associating the row with the wrong column. This is why I thought using interrupts would be better, that way the Mega knew when the Uno was looking at the necessary column and the Mega could react accordingly
In a real 4x4 keypad, does the Uno know when the user is going to press a key? I don't think so. The software just has to poll from time to time to see if keys are pressed and that event happens whenever.
blh64:
In a real 4x4 keypad, does the Uno know when the user is going to press a key? I don't think so. The software just has to poll from time to time to see if keys are pressed and that event happens whenever.
But wouldn't pressing a key cause the LOW from a given column "bleed" over into the row of that button? While the other rows are HIGH, pressing a key connects the row and column. I wasn't sure how else to replicate that connection between rows and columns other than using interrupts.
As for the race condition, the Mega is losing 99.99999% of the time now. It's only beat out the Uno about 20 times over the course of the past hour and a half. And just holding a row LOW causes the Uno to only ever read a seemingly random key on that row (depending on where in the scanning process it is), but most of the time, the Uno isn't even catching any key. I'm at a loss at this point and not sure where to start looking again