Issues calling functions through serial.

Hi,
I am trying to get one arduino uno (1) to send key words to another arduino uno (2). Robin2 has already pointed me to his topic “serial Input Basics” (https://forum.arduino.cc/index.php?topic=288234.0). this forum has been helpful however i have been unable to call functions.

here is some code i have written to express my issue:

char c = NULL; // input from recievedChars
String s = ""; // declare string (to convet c ) 

const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

void setup() {
    Serial.begin(9600);
    pinMode(13,OUTPUT);
    digitalWrite(13,LOW); // led starts off
}

void loop() {
a(); // get input
if (s = 'on') { //decide if days on or off and change the led state if it does. 
  digitalWrite(13,HIGH);
} else if (s == 'off') {
  digitalWrite(13, LOW);
}
}

void a() {  // get input through serial
    recvWithStartEndMarkers();
    showNewData();
c=receivedChars;
s = String(c);
   // Serial.println(s);
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
 // if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.println(receivedChars);
        newData = false;
    }
}

if it possible that i am simply using the wrong input type i.e. string or int when it is coming in as a char.
even if i try to use char in the if statements i am unable to change the led on or off.

thank you

Not saying it's your whole problem, but these things need to be fixed:

This is an assignment, not a test for equality:

if (s = 'on') { //decide if days on or off and change the led state if it does.

But, I honestly can't tell you what is being assigned because 'on' is not a string literal. Try "on".

This is a test for equality, but I don't know against what. Try "off".

} else if (s == 'off') {

This sets a char equal to a char pointer (i.e. char *). Not going to be helpful.

c = receivedChars;

Look up the 'strcpy()' function. Or better yet, use:

s = String(receivedChars);

Or even better yet, don't use the C++ class 'String' at all.

'a()' is a really bad function name.

What's more,

if (s = 'on')

on is a string, not a single character. So it doesn't belong in single quotes.

Need == as well for a comparison.

Robin2 has already pointed me to his topic "serial Input Basics"

NOWHERE in that thread will you find a String. You, obviously, did NOT read the thread.

This is all wrong (and I am being polite)

void a() {  // get input through serial
    recvWithStartEndMarkers();
    showNewData();
c=receivedChars;
s = String(c);
   // Serial.println(s);
}

For one thing, c is defined as a char and receivedChars[] is defined as an array and you CANNOT but an array into a single char.

Even if you could, what would be point of converting it to the String class since the whole purpose of my example code is to avoid using the String class. It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

And, if that were not enough, you are trying to do something with receivedChars[] when you have no idea whether it contains the complete incoming message. Look at how showNewData() deals with that and emulate it.

This part also suffers from the problem I mentioned in the previous paragraph

if (s = 'on') { //decide if days on or off and change the led state if it does.
  digitalWrite(13,HIGH);
} else if (s == 'off') {
  digitalWrite(13, LOW);
}

Finally, if all you want to do is control ON and OFF why not just send the single character 'N' for "on" and 'F' for "off"

...R

Robin2: ...if all you want to do is control ON and OFF why not just send the single character 'N' for "on" and 'F' for "off"

but that isn't in the definition of what he is trying to do...

@Stew, you want to parse the message into a string and then look to see if it matches any pre-defined commands. You can do that using strcmp().

a functioning example using On or Off. Choose NewLine in the Serial Terminal

const size_t MAX_MESSAGE_LENGTH = 16;

int var[4];

void setup() 
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  Serial.println("let's go!");
}

void loop() 
{
  if(const char* newMessage = checkForNewMessage(Serial, '\n'))
  {
    Serial.print(F("Just Recieved:\t"));
    Serial.println(newMessage);
    if(strcmp(newMessage, "On") == 0)
    {
      gotOnMessage();
    }
    else if(strcmp(newMessage, "Off") == 0)
    {
      gotOffMessage();
    }
  }
}

void gotOnMessage()
{
  Serial.println(F("Got on message."));
  digitalWrite(13, HIGH);
}

void gotOffMessage()
{
  Serial.println(F("Got off message."));
  digitalWrite(13, LOW);
}

const char* checkForNewMessage(Stream& stream, const char endMarker)
{
  static char incomingMessage[MAX_MESSAGE_LENGTH] = "";
  static byte idx = 0;
  if(stream.available())
  {
    incomingMessage[idx] = stream.read();
    if(incomingMessage[idx] == endMarker)
    {
      incomingMessage[idx] = '\0';
      idx = 0;
      return incomingMessage;
    }
    else
    {
      idx++;
      if(idx > MAX_MESSAGE_LENGTH - 1)
      {
        //stream.print(F("{\"error\":\"message too long\"}\n"));  //you can send an error to sender here
        idx = 0;
        incomingMessage[idx] = '\0';
      }
    }
  }
  return nullptr;
}

BulldogLowell: but that isn't in the definition of what he is trying to do...

That's why I started the sentence you quoted with "IF"

In any case, it is possible to send 52 different commands using single letters which completely eliminates the need for parsing.

...R

Robin2: it is possible to send 52 different commands using single letters...

...and a cipher key.

The code in that example is simply trying to help me explain my issue - there are some errors. The reason I am not using single characters is because I would like the functions I am calling to be human readable. (unlike my stupidly named functions).

@BulldogLowell you hit the nail on the head. Thank you for your suggestion. However i am unable to use newline in serial monitor as I intend to have one uno controlling the other.

The Arduino can send a newline just like the serial monitor can. Am I missing something here?

As @Delta_G points out, adding the new line char at the end of your transmitted string is trivial because

Serial.println()

automatically adds it!

In any case you can use any end marker you wish, except that it cannot be the same char as you use for a delimiter; just look at the function call.

The reason I am not using single characters is because I would like the functions I am calling to be human readable

So type in “Turn on LED 1” in the first Arduino, have it translate it to say “x”, transmit the single character, receive it on the second Arduino, decode it and have it run function turnOnLed(1); to turn on the LED

UKHeliBob: So type in "Turn on LED 1" in the first Arduino, have it translate it to say "x", transmit the single character, receive it on the second Arduino, decode it and have it run function turnOnLed(1); to turn on the LED

+1

...R