How to send numbers from one Arduino to another using Serial

Of course, if data can be lost other things can go wrong as well. "-42" might become "42" if the minus sign is lost. Or "1234" could become "124".

So really, for secure communications, you need some sort of CRC check.

OK, you 're right not to complicate the tutorial code by error handling, that is left as an exercise for the reader

I'd just be sure to point out that the exercise IS left for the reader to do. Without any sort of warning, the user will assume that the code is robust, and not add any error checking.

OK, I've added extra warnings. Like the ones on packets of peanuts: "Warning: contains nuts.".

"Warning: contains nuts."

I think I've been subtly insulted. But, I laughed anyway.

No, Paul I think his apparent cynicism is unfortunately right on target.

Bob

PaulS:
I think I've been subtly insulted.

Not intentionally. There was one on a tractor: "Warning: avoid death".

Sorry to bump up this thread: I have used this and works pretty well.

I only send 1 piece of data from one Arduino to another. First Arduino gathers data and sends it to a second Arduino that received this piece of data. What I'd like to do is to set the received data to a variable. Then re-use it in my "Loop".

Code I am using in my receiving part is this, but doesn't work as expected:-

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

long _r = 0;

void setup ()
  { 
  Serial.begin (115200);
  Serial2.begin (115200);
  Serial3.begin (115200);
  
   pinMode(8, INPUT);  
  } // end of setup
  
void processNumber (const long n)
  {
      _r = n;

  }  // end of processNumber
  
void processInput ()
  {
  static long receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial2.read ();
  
  switch (c)
    {
      
    case endOfNumberDelimiter:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } // end of switch  
  }  // end of processInput
  
void loop ()
  {
       
        if (Serial2.available ())
        {
          processInput ();
        } 
                       
        Serial.println(_r);
 
  }

Any help is appreciated.

but doesn't work as expected:

How does it work? How do you expect it to work? How are those different?

When it's done the original way when I stream lets say the number 8000 it gets there as 8000. However when I use my code it's sometimes 800, sometimes 80 or even 8.

When it's done the original way when I stream lets say the number 8000 it gets there as 8000.

What is "the original way"?

Your code is expecting "<8000>", not "8000". Are you sending it correctly? What does your debug output tell you? Oh wait, you don't have any!

processInput() collects the serial data that is in the buffer. It does NOT block until the end of the packet has arrived. You are printing the value as though the whole packet had arrived, on each pass through loop, even though there is a better then even chance that it has not.

When I do it this way:

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

long _rpm = 0;


void setup ()
  { 
  Serial.begin (115200);
  Serial2.begin (115200);
  Serial3.begin (115200);
  
   pinMode(8, INPUT);  
  } // end of setup
  
void processNumber (const long n)
  {
      Serial.println(n);
  }  // end of processNumber
  
void processInput ()
  {
  static long receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial2.read ();
    
  switch (c)
    {
      
    case endOfNumberDelimiter:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';

      break;
      
    case '-':
      negative = true;
      break;        
      
    } // end of switch  
  }  // end of processInput
  
void loop ()
  {
       

        if (Serial2.available ())
        {
          processInput ();
        } 
 
  }

the output I get from the second Arduino on the Serial Monitor is correct. So when I send <8000> from the 1st Arduino I get 8000 on the Serial Monitor of the 2nd Arduino.

When I do send <8000> this way from the 1st Arduino however,

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

long _rpm = 0;


void setup ()
  { 
  Serial.begin (115200);
  Serial2.begin (115200);
  Serial3.begin (115200);
  
   pinMode(8, INPUT);  
  } // end of setup
  
void processNumber (const long n)
  {
     _rpm = n;
  }  // end of processNumber
  
void processInput ()
  {
  static long receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial2.read ();
    
  switch (c)
    {
      
    case endOfNumberDelimiter:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';

      break;
      
    case '-':
      negative = true;
      break;        
      
    } // end of switch  
  }  // end of processInput
  
void loop ()
  {
       

        if (Serial2.available ())
        {
          processInput ();
        } 
                       
       Serial.println(_rpm);

  }

then I don't get the correct values, sometimes I get 800, sometimes 80 sometimes 8 etc.

Hope this is more clear.

void loop ()
  {
        if (Serial2.available ())
        {
          processInput ();
        } 
                       
       Serial.println(_rpm);
  }

As PaulS said, you are printing _rpm before it arrives. That's why I made a function processNumber. You are supposed to print it from there, when it has totally arrived. Why are you changing a method that works, to one that doesn't?

As PaulS said, you are printing _rpm before it arrives. That's why I made a function processNumber. You are supposed to print it from there, when it has totally arrived. Why are you changing a method that works, to one that doesn't?

That's what I thought initially. But, in processNumber, he's copying the value to _rpm, rather than printing it. Since processNumber doesn't get called until the > arrives, copying the value in processNumber should be OK.

PaulS:

As PaulS said, you are printing _rpm before it arrives. That's why I made a function processNumber. You are supposed to print it from there, when it has totally arrived. Why are you changing a method that works, to one that doesn't?

That's what I thought initially. But, in processNumber, he's copying the value to _rpm, rather than printing it. Since processNumber doesn't get called until the > arrives, copying the value in processNumber should be OK.

Exactly, I print it after it has arrived and setting _rpm within processNumber.

matinzk:
Exactly, I print it after it has arrived and setting _rpm within processNumber.

You are printing _rpm every time through loop. The time taken to do that (which uses interrupts) is likely to make you miss incoming data.

BTW I wouldn't be using leading underscores in variables names if I were you.

Maybe:

long _rpm = -1;

...

    if (_rpm != -1)
      {
      Serial.println(_rpm);
      _rpm = -1;
      }

This works beautifully thanks.

However if I have a set of extra data to also send via another serial port (Serial 3) to a device using a Bluetooth module, then I get missing data again.

So I receive the _rpm from first Arduino to my second Arduino Mega, then I send _rpm with 3 more data to Serial3 and receive these on my phone, the _rpm data is sometimes missing as before

Why are you doing it that way? Why not do the serial print in the processNumber function, which is the way that works anyway?

However if I have a set of extra data to also send via another serial port (Serial 3) to a device using a Bluetooth module, then I get missing data again.

Post this new code please.

Managed to get it working, thanks.