Hi all,
I'm experiencing an unexpected slow response when converting an old String-based function to a char array.
Years ago I wrote a function to scan a keyboard matrix of 160 buttons. It was based on a String vector which was being populated with the state of each button (i.e. "0000100001111.....").
At each cycle, the old string would be compared to the new one and if a button was pressed (value 0) or released (value 1) the microcontroller would send the code (XabcZ) where abc is the number of the button whose status had changed and Z is the status (0 or 1).
As I learned afterwards (I'm not a native programmer) using such a massive amount of strings was consuming the memory and this explains why the microcontroller would eventually hang in a couple of hours, then I decided to switch to char arrays.
The new algorithm works but it's surprisingly so slow than the micro takes now seconds to execute the other functions while with the previous algorithm everything was working almost in real-time. I tested this with my Arduino Due but also with Arduino Uno (using less buttons due to reduced number of DIN/DOUT) and different versions of Teensy. All of them behave in the same way.
For the sake of clarity, other functions (which have not been changed) are related to a MAX7219 led displays matrix whose input is received through the serial port.
Here below I paste the two versions, the older one with Strings and the newer one with char arrays.
Any help or clarification no what I'm doing wrong would be much appreciated.
Old Version:
[code]
#define activerows 10
#define columns 16
byte rows_pin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
byte columns_pin[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
String newState, oldState, newPinState, oldPinState, out;
int mapping[] = {1, 3, 6, 11, 13, 15, 17, 52, 55, 65, 63, 61, 59, 71, 87, 85, 83, 116, 123, 99, 151, 145, 142, 140};
void scan_buttons_old() {
newState = "";
for (int j = 0; j < activerows; j++) {
for (int i = 0; i < columns; i++) {
//update_encoder();
digitalWrite(columns_pin[i], LOW);
newPinState = String(digitalRead(rows_pin[j]));
digitalWrite(columns_pin[i], HIGH);
oldPinState = String(oldState.charAt(i + j * columns));
if (newPinState != oldPinState) {
if (newPinState == "1") {
for (int k = 0; k < (sizeof(mapping) / sizeof(int)); k++) {
if (((i + j * columns) == mapping[k]) && (oldState.charAt(-1 + i + j * columns) != "0") && ((i + j * columns) != 0)) {
out = "X";
out += (-1 + i + j * columns);
out += String(oldState.charAt(-1 + i + j * columns));
out += ":";
Serial.println(out);
skip_routine = true;
break;
}
}
}
if (!skip_routine) {
out = "X";
out += (i + j * columns);
out += newPinState;
out += ":";
Serial.println(out);
}
}
newState += newPinState;
skip_routine = false;
}
}
oldState = newState;
}
[/code]
and the new version...
#define String_State_Size 161
#define activerows 10
#define columns 16
byte rows_pin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
byte columns_pin[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
bool stringnewstate[String_State_Size], stringoldstate[String_State_Size];
bool pinStateSTR, oldpinStateSTR;
char strout[6];
int mapping[] = {1, 3, 6, 11, 13, 15, 17, 52, 55, 65, 63, 61, 59, 71, 87, 85, 83, 116, 123, 99, 151, 145, 142, 140};
void scan_buttons() {
for (int j = 0; j < activerows; j++) {
for (int i = 0; i < columns; i++) {
digitalWrite(columns_pin[i], LOW);
pinStateSTR = digitalRead(rows_pin[j]);
digitalWrite(columns_pin[i], HIGH);
oldpinStateSTR = stringoldstate[i + j * columns];
if (pinStateSTR != oldpinStateSTR) {
if (pinStateSTR == 1) {
for (int k = 0; k < (sizeof(mapping) / sizeof(int)); k++) {
if (((i + j * columns) == mapping[k]) && ((i + j * columns) != 0) && (stringnewstate[-1 + i + j * columns] != 0)) {
strcpy(strout, "");
strcat(strout, "X");
strcat(strout, (char *)integerToString(-1 + i + j * columns));
strcat(strout, (char *)integerToString(stringnewstate[-1 + i + j * columns]));
strcat(strout, ":");
Serial.println(strout);
skip_routine = true;
break;
}
}
}
if (!skip_routine) {
strcpy(strout, "");
strcat(strout, "X");
strcat(strout, (char *)integerToString(i + j * columns));
strcat(strout, (char *)integerToString(pinStateSTR));
strcat(strout, ":");
Serial.println(strout);
}
}
stringnewstate[i + j * columns] = pinStateSTR;
skip_routine = false;
}
}
for (int i = 0; i < String_State_Size; i++) {
stringoldstate[i] = stringnewstate[i];
}
}
If I call scan_buttons() in the loop() then the response is really slow. If I call scan_buttons_old() it's fast.
Thanks everyone for the support.
Best Regards