Im under no illusions that this is the ideal way to code this, but Im curious as to why its so slow. Any thoughts and what is the best way to recode this 2x7?
Thanks,
void loop() {
// Read the button matrix
for (int col = 0; col < COLS; col++) {
pinMode(colPins[col], OUTPUT); // Set current column pin to LOW
digitalWrite(colPins[col], LOW);
for (int row = 0; row < ROWS; row++) {
buttonState[row][col] = digitalRead(rowPins[row]); // Read button state
if (buttonState[0][0] == LOW) {
Joystick.pressButton(0);
}
if (buttonState[0][0] == HIGH) {
Joystick.releaseButton(0);
}
if (buttonState[0][1] == LOW) {
Joystick.pressButton(1);
}
if (buttonState[0][1] == HIGH) {
Joystick.releaseButton(1);
}
if (buttonState[0][2] == LOW) {
Joystick.pressButton(2);
}
if (buttonState[0][2] == HIGH) {
Joystick.releaseButton(2);
}
if (buttonState[0][3] == LOW) {
Joystick.pressButton(3);
}
if (buttonState[0][3] == HIGH) {
Joystick.releaseButton(3);
}
if (buttonState[0][4] == LOW) {
Joystick.pressButton(4);
}
if (buttonState[0][4] == HIGH) {
Joystick.releaseButton(4);
}
if (buttonState[0][5] == LOW) {
Joystick.pressButton(5);
}
if (buttonState[0][5] == HIGH) {
Joystick.releaseButton(5);
}
if (buttonState[0][6] == LOW) {
Joystick.pressButton(6);
}
if (buttonState[0][6] == HIGH) {
Joystick.releaseButton(6);
}
if (buttonState[1][0] == LOW) {
Joystick.pressButton(7);
}
if (buttonState[1][0] == HIGH) {
Joystick.releaseButton(7);
}
if (buttonState[1][1] == LOW) {
Joystick.pressButton(8);
}
if (buttonState[1][1] == HIGH) {
Joystick.releaseButton(8);
}
if (buttonState[1][2] == LOW) {
Joystick.pressButton(9);
}
if (buttonState[1][2] == HIGH) {
Joystick.releaseButton(9);
}
if (buttonState[1][3] == LOW) {
Joystick.pressButton(10);
}
if (buttonState[1][3] == HIGH) {
Joystick.releaseButton(10);
}
if (buttonState[1][4] == LOW) {
Joystick.pressButton(11);
}
if (buttonState[1][4] == HIGH) {
Joystick.releaseButton(11);
}
if (buttonState[1][5] == LOW) {
Joystick.pressButton(12);
//delay(25);
}
if (buttonState[1][5] == HIGH) {
Joystick.releaseButton(12);
}
if (buttonState[1][6] == LOW) {
Joystick.pressButton(13);
//delay(25);
}
if (buttonState[1][6] == HIGH) {
Joystick.releaseButton(13);
}
}
digitalWrite(colPins[col], HIGH); // Set current column pin to HIGH
pinMode(colPins[col], INPUT_PULLUP); // Set column pin back to input mode with internal pull-up resistor
}
Hello, @Slythy - I can see this is for a buttonbox. I think you shuold move pinMode(); to the setup() section. Would you post the complete sketch with setup()loop(), definitions and all functions?
My guess would be all those calls to Joystick.pressButton() and Joystick.releaseButton(). 99% of the time, nothing has changed, no buttons have been pressed or released, but the Arduino is constantly sending "updates". Perhaps if you only call Joystick.pressButton() when a button changes from not being pressed to being pressed and only call Joystick.releaseButton() when a button changes from being pressed to not being pressed, it would be much faster.
... of course, you can use any reference, and even try other libraries, like this library (with the same name, but different usage)... (A0 = x, A1 = y, 13 = button)
#include <Joystick.h>
Joystick_ Joystick(0x05, JOYSTICK_TYPE_GAMEPAD, 42, 0);
const int ROWS = 2; // Number of rows
const int COLS = 7; // Number of columns
int rowPins[ROWS] = {14, 15}; // Pins connected to rows
int colPins[COLS] = {8, 7, 6, 5, 4, 3, 2}; // Pins connected to columns
int lastButtonState[ROWS][COLS];
void setup() {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
pinMode(rowPins[row], INPUT_PULLUP); // Set row pins as input with internal pull-up resistors
pinMode(colPins[col], OUTPUT); // Set column pins as output
digitalWrite(colPins[col], HIGH); // Set column pins to HIGH
lastButtonState[row][col] = HIGH; // Initialize last button state to HIGH
}
}
// Initialize Joystick Library
Joystick.begin();
}
void loop() {
int b = 0;
// Read the button matrix
for (int col = 0; col < COLS; col++) {
digitalWrite(colPins[col], LOW);
for (int row = 0; row < ROWS; row++) {
int buttonState = digitalRead(rowPins[row]); // Read button state
if (buttonState == LOW and lastButtonState[row][col] == HIGH) {
Joystick.pressButton(b);
}
else if (buttonState == HIGH and lastButtonState[row][col] == LOW) {
Joystick.releaseButton(b);
}
}
lastButtonState[row][col] = buttonState;
b++;
digitalWrite(colPins[col], HIGH); // Set current column pin to HIGH
}
}
Once the buttonState[row][col] changes to LOW, it never goes back to HIGH. Eventually this will cause many (all) joystick button presses even if the buttons are released.
Oops, sorry for that. Move that line up one line (and adjust the indentation). Move the line b++; also.
The line with the error isn't in the loop that defines row. The } on the line above is the end of that loop. If you move the line with the error up by one line, then it will be in the loop.
Your original sketch was not checking when your buttons changed state, it sent the state of each button each time loop() executed, even for buttons that had not changed. Now, it only sends those updates when they are needed because a button has changed.
buttonState was a global array, but it didn't need to be. All the values in the array got overwritten each time loop() executed, and no part of the code was reading them, except one part which only read the array element for the current button. So the memory space taken up by that array was a waste, and I replaced it with a single, local, int variable. Only lastButtonState needed to be a global array because all 16 button states needed to be saved from one execution of loop() to the next to check which buttons had changed.
The button order in your original code is the natural order if the buttons were scanned row-by-row. But your original code scans the buttons column-by-column. That is one reason why your original code was so long, complex, and slow.
Using the shorter and faster code I gave, the button order is the natural order for column-by-column scanning.
Is this different order truly a problem? Can the application/game on the PC/laptop be configured to use this button order?
If not, the Arduino code can be fixed to give the original button order by changing it to scan row-by-row. Is there any reason why this could not be done? For example does your circuit have any external pull-up/down resistors or diodes?
Try this. It will be slightly slower because it uses digitalWrite() more frequently (28 times rather than 4 times for each scan), but I don't think the speed difference will be noticed, and it should change the button order to match your original code.
#include <Joystick.h>
Joystick_ Joystick(0x05, JOYSTICK_TYPE_GAMEPAD, 42, 0);
const int ROWS = 2; // Number of rows
const int COLS = 7; // Number of columns
int rowPins[ROWS] = {14, 15}; // Pins connected to rows
int colPins[COLS] = {8, 7, 6, 5, 4, 3, 2}; // Pins connected to columns
int lastButtonState[ROWS][COLS];
void setup() {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
pinMode(rowPins[row], INPUT_PULLUP); // Set row pins as input with internal pull-up resistors
pinMode(colPins[col], OUTPUT); // Set column pins as output
digitalWrite(colPins[col], HIGH); // Set column pins to HIGH
lastButtonState[row][col] = HIGH; // Initialize last button state to HIGH
}
}
// Initialize Joystick Library
Joystick.begin();
}
void loop() {
int b = 0;
// Read the button matrix
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
digitalWrite(colPins[col], LOW);
int buttonState = digitalRead(rowPins[row]); // Read button state
if (buttonState == LOW and lastButtonState[row][col] == HIGH) {
Joystick.pressButton(b);
}
else if (buttonState == HIGH and lastButtonState[row][col] == LOW) {
Joystick.releaseButton(b);
}
lastButtonState[row][col] = buttonState;
b++;
digitalWrite(colPins[col], HIGH); // Set current column pin to HIGH
}
}
}