Hello!
This is my first post here, so I am sorry if I am not sufficiently clear about the problem or if I don't post necessary information about the problem.
So, let me explain what I am doing:
I have a SparkFun's 4by4 RGB LED Button pad and I am using a Teensy 3.6 to multiplex both the RGB LEDs and to scan the button presses. I do have a bit more happening in my setup (MP3 player and LCD screen), but my question regards only the button press scanning of the pad (the code I will post also only regards that). How the button presses work in my current setup is that I have characters assigned to each position of the matrix, and whenever a button is pressed, I add the character corresponding to the pressed button to a 1by16 buffer array (this gets printed to the LCD in the complete setup). The problem I was encountering is that whenever I pressed a few specific buttons, the character added to the code would sometimes correspond to the button that was in the next column and in the same row as the pressed button (even if the next column button was not pressed OR connected to the teensy). For example, if I the pressed button with index [0][0] (this has the character 'R'), the character that would sometimes get stored in the buffer was the character corresponding to index [1][0] (the character was 'A'). This happened with 4 specific buttons, but did not happen with any of the others. Another interesting thing that I noted was that the pin corresponding to column 0 would read LOW when the teensy scanned [0][0] and [1][0], but not when it scanned [2][0] or [3][0].
It took me a long, long time to find the source of the problem. In order to scan the matrix, I set a row LOW and then checked each column to see if any of the columns were pulled low (the columns are connected to pins which are setup as input pullup). After I scanned the rows, I set the current column HIGH and moved on to the next column. Thus, I used digitalWrite to set a column HIGH and immediately moved to the next column and used a digitalWrite to set it LOW. It turns out that if I wrote a delay in between those digitalWrites the problem would go away, even with a delay as small as 1 microsecond. Although I am glad that the problem is fixed, it still bugs me that I don't understand why the problem happens. It seems to me that without the delay, the current row isn't set as HIGH until after the next row is scanned, but I am not sure. Might there be some interaction with calling two digitalWrites in succession? Or is there just a significant hardware delay for setting a pin HIGH? I would appreciate any help.
The code I used is below. I am using Arduino IDE for coding.
If more information is necessary for understanding the problem, just ask, I will happily provide it. Thanks!
This is my first post here, so I am sorry if I am not sufficiently clear about the problem or if I don't post necessary information about the problem.
So, let me explain what I am doing:
I have a SparkFun's 4by4 RGB LED Button pad and I am using a Teensy 3.6 to multiplex both the RGB LEDs and to scan the button presses. I do have a bit more happening in my setup (MP3 player and LCD screen), but my question regards only the button press scanning of the pad (the code I will post also only regards that). How the button presses work in my current setup is that I have characters assigned to each position of the matrix, and whenever a button is pressed, I add the character corresponding to the pressed button to a 1by16 buffer array (this gets printed to the LCD in the complete setup). The problem I was encountering is that whenever I pressed a few specific buttons, the character added to the code would sometimes correspond to the button that was in the next column and in the same row as the pressed button (even if the next column button was not pressed OR connected to the teensy). For example, if I the pressed button with index [0][0] (this has the character 'R'), the character that would sometimes get stored in the buffer was the character corresponding to index [1][0] (the character was 'A'). This happened with 4 specific buttons, but did not happen with any of the others. Another interesting thing that I noted was that the pin corresponding to column 0 would read LOW when the teensy scanned [0][0] and [1][0], but not when it scanned [2][0] or [3][0].
It took me a long, long time to find the source of the problem. In order to scan the matrix, I set a row LOW and then checked each column to see if any of the columns were pulled low (the columns are connected to pins which are setup as input pullup). After I scanned the rows, I set the current column HIGH and moved on to the next column. Thus, I used digitalWrite to set a column HIGH and immediately moved to the next column and used a digitalWrite to set it LOW. It turns out that if I wrote a delay in between those digitalWrites the problem would go away, even with a delay as small as 1 microsecond. Although I am glad that the problem is fixed, it still bugs me that I don't understand why the problem happens. It seems to me that without the delay, the current row isn't set as HIGH until after the next row is scanned, but I am not sure. Might there be some interaction with calling two digitalWrites in succession? Or is there just a significant hardware delay for setting a pin HIGH? I would appreciate any help.
The code I used is below. I am using Arduino IDE for coding.
Code:
int outputButton[4] = {19,18,17,16}; //row pins
char codeBuffer[16] = {
' ',' ',' ',' ',' ',' ',' ',' ',
' ',' ',' ',' ',' ',' ',' ',' '
}; //buffer for LCD
char buttonArray[4][4] = {{'R','E','Y','N'}, //character array for matrix
{'A','L','D','O'},
{' ','F','A','R'},
{'I','A','S','<'}};
int lcdCol = 0;
bool buttonSwitch = true;
int inputButton[4] = {24,25,26,27}; //column pins
#define MAX_DEBOUNCE (3)
static int8_t debounce_count[4][4];
uint8_t val;
void setup() {
Serial.begin(9600);
for(int i=0;i<4;i++){ // sets all column pins to output mode, button inputs to input pullups and button outputs to outputs
pinMode(inputButton[i], INPUT_PULLUP);
pinMode(outputButton[i], OUTPUT);
}
for(int i=0;i<4;i++){ // sets column pins to HIGH (closed switch) and buttonOutputs to HIGH
digitalWrite(outputButton[i],HIGH);
}
}
void loop() {
for(int i=0;i<4;i++){ //scanning for loops
digitalWrite(outputButton[i],LOW);
for(int j = 0;j < 4;j++){
scan(i,j); //scanning function taken from the SparkFun website. I added a few things to work with a buffer
}
digitalWrite(outputButton[i],HIGH);//this is the HIGH that sometimes isnt set as high.
delayMicroseconds(1); //<-- this is the delay that fixes the problem
}
for(int s = 0;s<16;s++){
Serial.print(codeBuffer[s]); //debugging print. prints the buffer that characters get stored in
}
Serial.println("");//debugging print
Serial.println(lcdCol); //debugging print
delay(10); // used to get a clean serial port reading (no weird jumping and the such)
}
void scan(int m, int n){
val = digitalRead(inputButton[n]);
Serial.println("Column " + String(m) + " and row " + String(n));
Serial.println("Input Value: " + String(val)); //debugging prints
if (val == LOW)
{
// active low: val is low when btn is pressed
if ( debounce_count[m][n] < MAX_DEBOUNCE)
{
debounce_count[m][n]++;
if ( (debounce_count[m][n] == MAX_DEBOUNCE)&&(buttonSwitch==true) )
{
buttonSwitch = false;
if(lcdCol<15){
if(buttonArray[m][n]=='<'){
codeBuffer[lcdCol-1] = ' ';
lcdCol--;
}
else{
codeBuffer[lcdCol] = buttonArray[m][n];
lcdCol++;
}
}
else if(lcdCol==15){
Serial.println("Max Size");
}
}
}
}
else
{
// otherwise, button is released
if ( debounce_count[m][n] > 0)
{
debounce_count[m][n]--;
if ( debounce_count[m][n] == 0 )
{
buttonSwitch = true;
}
}
}
}
If more information is necessary for understanding the problem, just ask, I will happily provide it. Thanks!