Serial send receive.

Hi
This a test sketch to test Serial send receive.
The first part works OK. <1> <2> or <3> will go to voids A, B, C.
The code in void A() is still getting the <1> entered to get there.
Should I be clearing the “receivedChars” before sending to “recvWithStartEndMarkers();”
To get the 2nd number?
Running this from the Serial Monitor to test, will use Python when working.

Thanks for any help, David.

int datain = 0;
int stops = 0;
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

void setup()
{
  Serial.begin(9600);
  Serial.print("Hello from Arduino, you are connected.");
  Serial.print("Enter 1 2 or 3 start with < end with >");
}
void loop()
{
  recvWithStartEndMarkers();
  showNewData();
}
void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  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) {
    datain = atoi(receivedChars);
    if (datain == 1)
    {
      A();
    }
    if (datain == 2)
    {
      B();
    }
    if (datain == 3)
    {
      C();
    }
    newData = false;
  }
}

void A()
{
  Serial.write("You are in A ");
  Serial.write("Enter any number NOT 1 with <> ");
  recvWithStartEndMarkers();
  if (newData == true) {
    stops = atoi();
    Serial.write("You sent ");
    Serial.write(receivedChars);
    Serial.write(stops);
    newData = false;
    hangon();
  }
}
void hangon()
{
  delay(500);
  hangon();
}
void B()
{
  Serial.println("You are in B");
  hangon();
}
void C()
{
  Serial.println("You are in C");
  hangon();
}
 stops = atoi();

atoi what?

They're called "functions" not "voids"

david17:
will go to voids A, B, C.

Those “voids” are called functions. Functions with a terrible name btw. A variable or function name should tell exactly what it holds or does. Void only tells the compiler it doesn’t return a value.

And about your problem, no, but you should set newData to false the moment you read that data and it’s not new anymore. When A() is entered the newData flag is still true so the whole receiving is skipped and the “old data” is used.

Also, why are there things in recvWithStartEndMarkers static? Would understand that if the code was non blocking but it just blocks it. Especially the ndx (which is a terrible variable name) being static gives you a problem of not being able to receive something new. And don’t abbreviate just one word. Just cal it receiveWithMarkers().

Ow, and it would make more sens to make the startMarker and endMarker const globals. Easy to edit on the top and because of const don’t take up memory.

Also spot an error. Because you receive small strings it’s fine now but you have to

  1. add a null character to the end of the received chars
  2. check if you don’t receive more then 31 (32 - 1 for the null char) because otherwise you will write beyond the receivedChars array

(2) explains itself
(1) gives you problems if you receive something that’s shorter then the last received string. Now (after removing the static part) if you send “” and then “” the receivedChars array will contain “foolo world\0” instead of “foo\0”

@septillion Does not look like it's blocking. Looks like robin2's serial input basics but can't compare at the moment.

Damn I missed that! :o Now I also see the overshoot check an termination. Man, time for dinner!

Then all needed is to make newData false the moment it’s not new anymore :wink: And remove the empty atoi() or put something useful in it :stuck_out_tongue: And make some names a bit more useful :stuck_out_tongue:

david17: Thanks for any help, David.

You should only call recvWithStartEndMarkers() in loop() - nowhere else.

It only works if it can be called lots of times by the repeating loop() function. Ensure that the rest of your code does not prevent loop() from repeating hundreds or thousands of times per second.

There is a simple user input example in Planning and Implementing a Program. Note how the request to the user and the reply from the user are handled separately.

...R

Should have been.. stops = atoi(receivedChars);

Looks like robin2's serial input basics.. Yes it is.

And make some names a bit more useful :.. I will this is just bit of test code.

Then all needed is to make newData false the moment it's not new anymore.. Thanks I will do that.

david17: I will this is just bit of test code.

Doesn't really matter. Because you make thinks only harder if you don't call them what they do ;) Even in a test situation.

david17: Then all needed is to make newData false the moment it's not new anymore.. Thanks I will do that.

M, not only. That wil indeed fix the problem of A() reading 1 again but will break the code now I know (doohhhhh) the code is not blocking. Because the change of newData being true after one call of recvWithStartEndMarkers() in A() is pretty damn small. So instead of calling it in A() you still call it in the loop(). But now you remember you already called A() so the next input you receive is for the second part of A. We already use weird names so let's call that AA(). In which you do the "You sent x"-part.

Btw, what the heck is that hangon() supposed to do?