I am writing a code that, among other things, will allow me to turn on and off up to 24 relays. I currently have it working, but feel there should be a much more efficient way to achieve my goals here.
Currently, the app sends a string to a HC-05, and then I use the following code:
msg = Serial1.readString();
if (msg == "relay1On"){
digitalWrite(relay1, HIGH);}
if (msg == "relay1Off"){
digitalWrite(relay1, LOW);}
If I can guarantee that the only codes sent would be some form of "relay01On", "relay20Off" etc, how can I seperate it into two strings? if I am able to do this, I could cut 24 copies of that code down to a simple void:
void relayActivate(String string) {
//some code here to seperate string into string1 and string 2
if(string2 == "On")
digitalWrite(string1, HIGH);
if(string2 == "Off")
digitalWrite(string1, LOW);
}
Would this work?
EDIT: No, digitalWrite() doens't accept Strings, must be uint8_t. For now, I'm just gonna do it the hard way I think.
Well you could send a byte that says here is a control, here is a analog etc.
example:
byte one = 123 (control), byte two = 224 turn OFF relay 24
byte one = 123 (control), byte two = 124 turn ON relay 24
byte one = 111 (analog), byte two (MSB) = 0xF3, byte three (LSB) = 0xFF
F = analog 15 = 0x3FF
after some research, I will change the incoming string to include a Separator (in this case, a comma) and then can use Serial.readStringUntil(',') to get the first string, then again to get the second string.
So if I send my strings as this "relay1,HIGH," and "relay1, LOW," I can then use this:
String receivedMsg;
// all String memory used in relayActivate is completely recovered on method return.
// no memory fragmentation here
bool relayActivate(String& string) {
String msg = string; // note this makes a copy so original string can be used in error msg
msg.toUpperCase(); // make all upper case
if (msg.startsWith("RELAY")) {
msg.replace("RELAY", "");
int turnOn = LOW;
if (msg.endsWith("ON")) {
turnOn = HIGH;
msg.replace("ON", "");
} else if (msg.endsWith("OFF")) {
turnOn = LOW;
msg.replace("OFF", "");
} else {
Serial.print(string); Serial.println(" Error relay not On or Off.");
return false;
}
// here have turnOn set and only number left
int pinNo = msg.toInt();
if (pinNo == 0) {
Serial.print(string); Serial.println(" Error invalid pin.");
} else {
Serial.println(string);
digitalWrite(pinNo, turnOn);
return true;
}
} // else {
Serial.print(string); Serial.println(" is an Invalid relay msg.");
return false;
}
void setup() {
Serial.begin(9600);
for (int i = 10; i > 0; i--) {
Serial.print(' '); Serial.print(i);
delay(500);
}
Serial.println();
receivedMsg.reserve(80); // reserve space to prevent any memory fragmentation
receivedMsg = "relay01on";
relayActivate(receivedMsg);
receivedMsg = "relay21off";
relayActivate(receivedMsg);
receivedMsg = "rela21off";
relayActivate(receivedMsg);
receivedMsg = "relayoff";
relayActivate(receivedMsg);
receivedMsg = "relay1out";
relayActivate(receivedMsg);
}
void loop() {
}
Gives this output
relay01on
relay21off
rela21off is an Invalid relay msg.
relayoff Error invalid pin.
relayoff is an Invalid relay msg.
relay1out Error relay not On or Off.
Not necessary to avoid Strings, they are very safe on small memory AVR boards and using reserve( ) and String& avoids memory fragmentation.
See my tutorial on Taming Arduino Strings
But if you want to avoid Strings and still want to use the String type text functions like replace, substring, indexOf, endsWith etc then check out my SafeString library that uses fixed size char[ ..] underneath and protects against buffer overflows, null pointer, off by one indexing and missing '\0' terminators
i use the following for debug/controling in almost all my code
a numeric value followed by a single letter command. there can be multiple "commands" on a single line. new "commands" can easily be added. human readable
// process single character commands from the PC
#define MAX_CHAR 10
char s [MAX_CHAR] = {};
int analogPin = 0;
void
pcRead (void)
{
static int val = 0;
if (Serial.available()) {
int c = Serial.read ();
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
val = c - '0' + (10 * val);
break;
case 'A':
analogPin = val;
Serial.print ("analogPin = ");
Serial.println (val);
val = 0;
break;
case 'D':
debug ^= 1;
break;
case 'I':
pinMode (val, INPUT);
Serial.print ("pinMode ");
Serial.print (val);
Serial.println (" INPUT");
val = 0;
break;
case 'O':
pinMode (val, OUTPUT);
Serial.print ("pinMode ");
Serial.print (val);
Serial.println (" OUTPUT");
val = 0;
break;
case 'P':
pinMode (val, INPUT_PULLUP);
Serial.print ("pinMode ");
Serial.print (val);
Serial.println (" INPUT_PULLUP");
val = 0;
break;
case 'a':
Serial.print ("analogRead: ");
Serial.println (analogRead (val));
val = 0;
break;
case 'c':
digitalWrite (val, LOW);
Serial.print ("digitalWrite: LOW ");
Serial.println (val);
val = 0;
break;
case 'p':
#if !defined(ARDUINO_ARCH_ESP32)
analogWrite (analogPin, val);
Serial.print ("analogWrite: pin ");
Serial.print (analogPin);
Serial.print (", ");
Serial.println (val);
val = 0;
#endif
break;
case 'r':
Serial.print ("digitalRead: pin ");
Serial.print (val);
Serial.print (", ");
Serial.println (digitalRead (val));
val = 0;
break;
case 's':
digitalWrite (val, HIGH);
Serial.print ("digitalWrite: HIGH ");
Serial.println (val);
val = 0;
break;
case 't':
Serial.print ("pinToggle ");
Serial.println (val);
digitalWrite (val, ! digitalRead (val));
val = 0;
break;
case 'v':
Serial.print ("\nversion: ");
Serial.println (version);
break;
case '\n': // ignore
break;
case '"':
while ('\n' != Serial.read ()) // discard linefeed
;
readString (s, MAX_CHAR-1);
Serial.println (s);
break;
case '?':
Serial.println ("\npcRead:\n");
Serial.println (" [0-9] append to #");
Serial.println (" A # - set analog pin #");
Serial.println (" D # - set debug to #");
Serial.println (" I # - set pin # to INPUT");
Serial.println (" O # - set pin # to OUTPUT");
Serial.println (" P # - set pin # to INPUT_PULLUP");
Serial.println (" a # - analogRead (pin #)");
Serial.println (" c # - digitalWrite (pin #, LOW)");
Serial.println (" p # -- analogWrite (analogPin, #)");
Serial.println (" r # - digitalRead (pin #)");
Serial.println (" s - digitalWrite (pin #, HIGH)");
Serial.println (" t -- toggle pin # output");
Serial.println (" v - print version");
Serial.println (" \" - read string");
Serial.println (" ? - list of commands");
break;
default:
Serial.print ("unknown char ");
Serial.println (c,HEX);
break;
}
}
}