All, I can't seem to figure out what I'm doing wrong here. Probably I will kick myself when one of you points it out to me!
I have 14 pushbuttons arranged as a matrix of 2 rows of 7 columns.
I need to monitor these while the Arduino is busy performing calculations, so I'm trying to use interrupts to detect when a button is pressed. For the moment I'm assuming only one button will be pressed at a time.
The 2 rows are attached to the 2 Arduino interrupt pins (digital pins 2 and 3), which are set to INPUT_PULLUP.
The 7 columns are attached to 7 more digital pins, which are set to OUTPUT and LOW.
If any switch is pressed, it connects one if the input pins (2 & 3) to one of the output pins. This pulls the input pin to LOW and fires an interrupt routine.
There are 2 interrupt routines. Which is called depends on which row the closed switch is in. The interrupt routine then has to determine the column that the closed switch is in.
Remember, one of those 7 column pins is pulling the row pin LOW because the switch is closed. So the interrupt routine needs to test each of the 7 column pins in turn. To test each column pin, it sets the column pin to INPUT* and re-reads the row pin. If the switch in that column is closed, the row pin is no longer pulled low (because the column pin is no longer LOW) and so it reads high (because it it set to INPUT_PULLUP).
-
- I am setting the column pin back to INPUT rather than HIGH, just in case buttons from 2 columns do accidentally get pressed at the same time. This avoids a short-circuit.
So that's my algorithm. But either my code is not correctly implementing it, or my algorithm is wrong, because, when a button is pressed, the code correctly reports the row, but always reports the column as 7, no matter which button was pressed.
Can anyone spot my error please?
const byte btnRow[2] = {2, 3};
const byte btnCol[7] = {4, 5, 6, 7, 8, 9, 10};
volatile byte rowTrig = 0;
volatile byte colTrig = 0;
void setup() {
Serial.begin(57600);
pinMode(btnRow[0], INPUT_PULLUP);
pinMode(btnRow[1], INPUT_PULLUP);
for (byte col=0; col<=6; col++) {
pinMode(btnCol[col], OUTPUT);
digitalWrite(btnCol[col], LOW);
}
attachInterrupt(0, readBtnRow1, FALLING);
attachInterrupt(1, readBtnRow0, FALLING);
}
void readBtnRow0() {
readBtn(0);
}
void readBtnRow1() {
readBtn(1);
}
void readBtn(byte row) {
delayMicroseconds(20000);
for (byte col=0; col<=6; col++) {
pinMode(btnCol[col], INPUT);
delayMicroseconds(20000);
if (digitalRead(btnRow[row]) == HIGH) {
rowTrig = row+1;
colTrig = col+1;
}
pinMode(btnCol[col], OUTPUT);
digitalWrite(btnCol[col], LOW);
}
}
void loop(){
if (colTrig != 0 || rowTrig != 0) {
Serial.print("Row ");
Serial.print(rowTrig);
Serial.print(" Col ");
Serial.println(colTrig);
rowTrig = 0;
colTrig = 0;
}
}
(I have tried the code with and without those delayMicrosecond() calls).
Serial monitor looks like this, when I press a random sequence:
Row 2 Col 7
Row 1 Col 7
Row 2 Col 7
Row 1 Col 7
Row 2 Col 7
Row 2 Col 7
Row 2 Col 7
Row 1 Col 7
Row 1 Col 7
Thanks!