//digital pins connected to Leds//
const int NUM_LEDS = 2;
const int LED_pins[] = { 13, 4 };
const char LED_ids[] = { 'A', 'B' };
void setup() {
for (int i = 0; i < NUM_LEDS; i++) {
pinMode(LED_pins[i], OUTPUT);
}
Serial.setTimeout(10); //window time to receive data from Serial
Serial.begin(115200); // start serial communication at 115200 baud (bits per second)
}
void loop() {
LEDsControl();
}
void LEDsControl() {
if (Serial.available() > 0) {
char id = Serial.read();
int state = Serial.parseInt();
for (int i = 0; i < NUM_LEDS; i++) {
if (id == LED_ids[i]) {
digitalWrite(LED_pins[i], state);
Serial.print(id);
Serial.print(" ");
Serial.println(state);
}
}
}
}
In the max side I'm translating the message A 0 or A 1 from symbol to integer using the [atoi] object - so what is really sends is 65 32 48 or 65 32 49.
In the Arduino code I'm receiving the data and stores it into char variable for the ID (A or B) and the number 0 or 1 I'm storing into integer (state). I don't understand what is the type of value arriving inside Arduino? is is integers that get translating automatically to symbols and integers? so when Arduino see 65 (A) he knows to store it as char? and when he sees 48 or 49 he automatically translate it into number? how this happens?
It is not an Arduino who knows how to store each piece of data, it is programmer.
In your code you clearly direct the controller to store a first byte as char and than interpret the next as integer:
char id = Serial.read();
int state = Serial.parseInt();
Take the attention to the data types on the left of each line.
There are more than one way to do it. You can, for example, read the chars in a loop and store them in char array.
But be warned that moving from a single char to a string is much more complicate than just reading a next char in serie. I would recommend you to read a "Serial basic tutorial" to see more.
Some thoughts. While such goals are nice, in the microcontroller world learning to be brief saves time and effort, and often reduces the bug count. Unless you have more than 26 commands in mind, I'd keep my commands to one character, then as others have suggested, an index number, and last, a data value. Something like:
L30 (ell three zero) would suffice for LED three off, as long as there are 10 or fewer LEDs, P51 for the 5th pump on, R81 for relay 8 on, etc.
You could get fancier, with N and F for on and off instead of 1 or 0; this abstracts from the physical. Why? because often, you'll have a device that is turned on with a 0 and off with a 1, and you want your stream of commands to be human-comprehensible, even though you've kept it brief. It costs little/nothing in terms of code to interpret N or F instead of 1 or 0, as they're all ASCII chars.
Yes, but the difference is more subtle when viewing a record of what's been transmitted, for example. In some circumstances, I tend to use upper and lower as an implicit 1 or 0, meaning if I send 'A', I want the first output set high, whereas if I send 'a', I want it set low. However, that's generally more when I'm using Serial Monitor to 'direct drive' a sketch.
It's all sort of YMMV, really. Whatever gets the job done.
presumably the benefit of a single character command is to simplify lexical analysis of the command, for example, immediately processing the command as soon as the command letter is received.
To do this requires knowing any arguments before the command letter is received, otherwise it requires buffering multiple chars, recognizing that a complete command is received and then processing the command, similar to what i posted above.
processing a command char-by-char is relatively simple by reversing the order of a command, instead of the syntax being cmd (letter) followed by arguments (e.g. A123), the arguments precede the command (e.g. 123A) or recognizing one or more arguments delimited by a comma, for example (e.g. 123,45B) and pushing arguments into an array.
numeric arguments can be handled one char at a time and acumulating a multi-digit value, val = 10*val + c-'0'
recognizing that a command is complete when the letter is received also make it possible to string commands together, for example 123A56BC (of course spaces can be ignored)
but with the string processing capabilites of C, just receiving a \n terminated string and using sscanf() to extact multiple string and numeric fields is east and convenient even with a simple processor like Arduino without an OS.
You protected the first part but that's risky business
if the command that has been sent is longer than 9 bytes.
may be consider
void cmdProcessor()
{
if (Serial.available()) {
char buf[90];
size_t n = Serial.readBytesUntil('\n', buf, sizeof(buf) - 1);
buf[n] = '\0';
char cmd[10];
int id, arg;
if (sscanf(buf, "%9s %d %d", cmd, &id, &arg) == 3) {
if (strcmp(cmd, "led") == 0) {
if (id >= 0 && id < NUM_LEDS) digitalWrite(LED_pins[id], arg);
}
// else if (...) // other cmds
}
}
}
also this is blocking and timeout might come bite you, so an async handing of the serial line as described in Serial Input Basics to handle this would seem more appropriate.
when using the serial monitor, the entire line is sent at once, not char-by-char without being able to edit. this is also most likely if it's machine-to-machine
Knowing if there is a risk for data to accumulate whilst a command is being handled (ie more commands coming in) would help decide if asynchronous handling is needed.
I don't think anyone has answered that; it's not anything, it's 8 bits sitting in a hardware register waiting for some code to do something with it. What type it ends up as depends on your code and how you handle it. If you want it to be a char then it's a char. If you want it to be a 16 bit int then it's either the lower 8 bits or the upper 8 bits, but it's for your code to pair it up with another 8 bits to make the 16 needed and put them into an int as required. The hardware (in this case serial port) doesn't know anything about data types. I strongly suggest you read the serial tutorial @J-M-L lined to in post #13.