Hello,
I am trying to make a custom tv remote using an ATmeta328p microcontroller. It contains 28 buttons which are wired in a matrix configuration, resulting in 5 outputs (columns) and 6 inputs (rows). Before ordering a PCB, I want to make sure electrical the circuit which I came up with is going to work, so I have made a similar circuit with only 4 buttons (2 rows and 2 columns) on a piece of perf board to which I can test with an Arduino Uno.
Now I have written the code for it, but the program gives an incorrect correct output when do not I serial print a message at some line which I have used for debugging. If I do not print at a specific line, two buttons on the same row will sometimes not be detected correctly when I press them simultaneously. I have tried to put a delay on the line instead of serial print, but this does not help.
I have put my code below. The message which I need to print for the program to work correctly is on line 35 (Serial.print("\ntest");
)
#include <stdint.h>
#define NR_OF_COLS 2
#define NR_OF_ROWS 2
int main() {
init();
Serial.begin(9600);
for (uint8_t i = 0; i < NR_OF_COLS; i++) {
//make pins 8 - 8+i low (cols)
PORTB &= ~(1 << i);
//make pins 8 - 8+i outputs (cols)
DDRB |= (1 << i);
}
for (uint8_t i = 0; i < NR_OF_ROWS; i++) {
//make pins A0 - A(0+i) = digital inputs (rows)
DDRC &= ~(1 << i);
}
//make pin 2 input (interrupt)
DDRD &= ~0x4;
while(1) {
//if interrupt pin became low
if (!(PIND & 4)) {
uint8_t btnArray[NR_OF_COLS] = {0};
uint8_t rows = 0;
//the row pins need some time to change after the interrupt has been triggered
delay(1);
for (uint8_t i = 0; i < NR_OF_ROWS; i++) {
//read rows, store inverted bits (rows are active low)
rows |= (PINC & (1 << i)) ^ (1 << i);
}
Serial.print("\ntest");
for (uint8_t i = 0; i < NR_OF_COLS; i++) {
//set col pin i
PORTB |= 1 << i;
//the row pins need some time to change based on thew new value of the col pins
delay(1);
uint8_t newRows = 0;
for (uint8_t j = 0; j < NR_OF_ROWS; j++) {
//read rows again
newRows |= (PINC & (1 << j)) ^ (1 << j);
}
for(uint8_t j = 0; j < NR_OF_ROWS; j++) {
//check if row pins have changed based on thew new values of the col pins
if (rows & (1 << j) && !(newRows & (1 << j))) {
//store row values in col i
btnArray[i] |= (1 << j);
}
}
//clear col pin i
PORTB &= ~(1 << i);
}
//print debug information
Serial.print("\nButtons:\n");
for (int i = 0; i < NR_OF_ROWS; i++) {
for (int j = 0; j < NR_OF_COLS; j++) {
Serial.print((btnArray[j] & (1 << i)) != 0);
Serial.print(' ');
}
Serial.print('\n');
}
delay(1000);
}
}
}
When I press for example the two buttons on row 0 simultaneously with the printing message in between, I see this on the serial monitor:
test
Buttons:
0 0
1 1
And when I remove the message, I get this on the serial monitor:
Buttons:
0 0
0 0
I am not sure if this problem arises because of the hardware or the software, so I have also put the schematic of the circuit below:
Can someone see what I'm doing wrong?