I have Arduino code that reads commands from the serial and changes colors of LED light based on a command. however, I want to have it change from staying one color to start blinking, and later via sending a different command to the Serial it should change color and stop blinking.
I believe to make it blink I need to throw it into a loop, but then I have difficulty how to take it out of the loop it should check if new command came in.
Below is my code which does not have a blink option.
Please take a look and help me out.
Thanks.
define Red 10
#define Green 11
#define Blue 9
String cmnd;
char rcvdChar;
void setup() {
// put your setup code here, to run once:
pinMode(Red, OUTPUT);
pinMode(Green, OUTPUT);
pinMode(Blue, OUTPUT);
Serial.begin(115200);
}
void readFromSerial(){
while (Serial.available() > 0){
rcvdChar = Serial.read();
cmnd.concat(rcvdChar);
delay(10); //Check if need
}
}
void setColor(){
if (cmnd.equals("red")== true){
digitalWrite(Red, HIGH);
digitalWrite(Green, LOW);
digitalWrite(Blue, LOW);
}
if (cmnd.equals("green")== true){
digitalWrite(Red, LOW);
digitalWrite(Green, HIGH);
digitalWrite(Blue, LOW);
}
if (cmnd.equals("off")== true){
digitalWrite(Red, LOW);
digitalWrite(Green, LOW);
digitalWrite(Blue, LOW);
}
}
void loop() {
// put your main code here, to run repeatedly:
readFromSerial();
setColor();
cmnd = "";
}
if you reset cmnd (cmnd = "";) immediately after setColor(), i doubt it will ever contain a complete string. but it does need to be reset but only if a valid word, and what about errors.
suggest Serial.readBytesUntil() and reading a complete line terminated with a linefeed.
You want the microcontroller do what most microcontroller-applications do.
Running multiple tasks so fast sequentially that the user-experience is the tasks are done in parallel.
This requires quit some learning that goes beyond a simple blink or receive some bytes.
Doing multiple things in sequential requieres on big loop where each task takes over "control" for a very short time does a single step and then hands over "control" to the next task.
Well it is not really taking "control" it is a jump in / jump out in each task.
This is done by calling each function inside the main-loop which is
one task is checking if a new command is in the receive-buffer
with a very important difference:
the looping is done by void-loop and not inside your "receive-code"
one task does the blink etc.
non-blocking timing is done based on function millis()
So one part is learing what is a function
One part is learn to "loop" with repeated calling of functions
One part is learning to use non-blocking timing based on function millis()
It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.
having loop() sequentially invoke multiple sub-functions would be more accurate. in this case, one sub-function monitors the serial interface while a 2nd sub-function flashes an LED
the term "task" is misleading because there is no operating systems doing context switching between tasks that independent of one another such as on an esp32. operating systems also include mechanisms for tasks to communicate with one another
of course, windows and linux are multi-tasking operating systems
<In an everyday meaning "task" could be used too.
But
is a good description which distinguishes from the informatic term "task" but the everyday analogon "something is functioning" is somehow a bit misleading too.
Maybe something like a sub-unit of code which does one thing and is build from two to n basic commands
This sub-unit should ideally do just one thing like:
checking the serial receivebuffer if a byte is there take it out of the buffer and add it to a variable
You need a better solution to handle Serial input... you should be checking for the end of input (such as a CR character), and you can't assume that the input can keep up with the Arduino. So you might get the the end of the serial buffer and not have read everything yet. You need to handle this, and allow the program to continue... and check the Serial buffer again for the rest of the message on the next loop.
You need to hold the previous command received while you are waiting for the next one to arrive.
To enable blinking use something like millis(s) to count the time to switch on/off... rather than blocking with something like delay(1000). If you have a variable that holds this information you can use when you decide which lights to turn on/off.