sending multiple sensors values between two arduinos via serial

Hello everyone.
Iam fairly new to arduino and this is my first post, so thank you for your patience.
I am successfully sending int between two arduinos with this code:
sender:

const int analogPin = A0;

void setup()
{
Serial.begin(9600);

}

void loop()
{   

  int sensor = analogRead(analogPin) - '0';
Serial.println(moisture);
delay(100);
  }

Receiver:

int sensor=0;

int inByte = -1;
char inString[6];
int stringPos = 0; 



void setup()  { 

  Serial.begin(9600); 


} 

void loop() { 

   inByte = Serial.read();
  //if there is any numerical serial available, store that
  if((inByte >= '0') && (inByte <= '9')){
    inString[stringPos] = inByte;
    stringPos ++;
  }

  //if there is a line end character, this string is done, take value and write to LED pin
  //clear the string when done
  if(inByte == '\r'){
    sensor = atoi(inString); //convert string to int
Serial.println(sensor);
    //clear the values from inString
    for (int c = 0; c < stringPos; c++){
      inString[c] = 0;
    }
    stringPos = 0;
  }

}

I am now trying to send 2 different sensors values, still unsuccessfully.
I tried modifying the sender, adding the line :
Serial.println(‘a’); , before Serial.println(sensor);.
and adding to the receiver arduino:

char inChar = Serial1.read();
if (inChar == ‘a’){
inByte = Serial1.read();

at the beginning of the loop.
but it didn’t work (sensor value remains 0).
Any ideas what am i doing wrong?

While there are ways to do this, I believe you will be better served by using I2C

Here’s a nice library:

If you really want to go with serial this is some code I used before going to SPI.

This is for a serial lock , but I added a few pieces to the code showing how to check for multiple statements if the first one returns false. Should give you an idea on how to proceed.

#define MAXCHAR 12

const char strMem[]="STRING TO VERIFY";
const char strMem1[]="STRING TO VERIFY";
const char strMem2[]="STRING TO VERIFY";
//const char strMem(n)[]="STRING TO VERIFY";

// pins for the LEDs:
const int ledPin = 8;

char charRead;
int charCount = 0;
char strRead[MAXCHAR];

/*void welcome_msg() {
 //  Serial.println();
   Serial.println("Login");
  // Serial.println();
}
*/

void setup() {
  // initialize serial:
  Serial.begin(19200);
  // make the pins outputs:
  pinMode(ledPin, OUTPUT);
    pinMode(8, OUTPUT);
  
  /*welcome_msg();*/
}

void loop() {
 
  digitalWrite(8, HIGH);
  
  // if there's any serial available, read it:
  while (Serial.available() > 0) {
    charRead= Serial.read();
    digitalWrite(8, LOW);
    if (charRead != '\n' && charCount<MAXCHAR) {
       strRead [charCount] = charRead;
       charCount++;
       strRead [charCount] = '\0'; //end of the string
       delay(10);
    }
    else {
      // check if the password is correct
      if (strcmp(strRead, strMem) == 0) {
         //delay(1000);
         Serial.print("Accepted");
         Serial.print('\n');
         tone(6, 8000, 400);
         digitalWrite(ledPin, HIGH);
         delay(1000);
         digitalWrite(ledPin, LOW);
         charCount = 0;
	else if (strcmp(strRead, strMem1) == 0) {
	//Do action 2
      }
	else if (strcmp(strRead, strMem2) == 0) {
	//do action 3
	//else if {...}
      else {
         //Serial.println("Invalid Card");
         tone(6, 7000, 200);
         
         charCount = 0;
      }
      
     /* welcome_msg();*/
    }
  }
}

Before adding something to your code, you should think about the data that is transferred and how the sketch should work.

I also like I2C, but Serial is okay.
You can read the serial data and use atoi(), but there is a function to grab and integer from the incoming serial data: http://arduino.cc/en/Serial/parseInt

The end of the line could be ‘\n’ or ‘\r’ or ‘\r\n’ or nothing. Let’s add an ‘#’ to mark the end of the line, it might be useful someday.
The data would look like this: “a208b1019#”

Read the incoming data, one character at the time. Is it an ‘a’ or ‘b’ ? read the value with parseInt. Discard everything else. That means that all the ‘\r’ and ‘#’ are simply discarded, you are only scanning for ‘a’ or ‘b’.
Can you write your sketch to easily add new values with ‘c’ and ‘d’ and so on ?

When you read an analog pin, the analogRead() returns a vale of 0…1023. Please do not substract ‘0’. Use the value as it is.

I am successfully sending int between two arduinos with this code:

No, you are not. That sender code won't even compile.

Thank you everybody/ casemod - I will check the I2C protocol for other projects, but for this one I need to use serial because I want to use my bluetooth models which use serial.

Peter_n - I am not sure I understood how the parseInt works, will it read the id(in this example "a") and then I can continue reading the rest of the sensor value( in this example 208b1019) with my code or another parsenInt? how can stop reading and store the int when it gets to # ?

PaulS - Sorry for the mix up. replace the word moisture with sensor.

For peter suggestion there is a function that allows you to "have a look" at the first character. Cant remember which one it is, perhaps someone has better memory than me

Sou you could make something really simple based on that. Look at the first character and run a loop to know what to do. Then you need to flush the buffer to load new data.

casemod found it. it is called peek().http://arduino.cc/en/Serial/Peek. The problem is it is still in the buffer and I want to remove it.

The problem is it is still in the buffer and I want to remove it.

So, read() it and discard it.

bombom: casemod found it. it is called peek().http://arduino.cc/en/Serial/Peek. The problem is it is still in the buffer and I want to remove it.

Thats it, thank you. First thing you need to check if there is Data in the serial buffer. use this: http://arduino.cc/en/Serial/available

Once data arrives, that function will return true. Run the loop. Once the loop completes, use Serial.flush() to clear the Serial buffer.

I believe that also avoids the data changing while you are running the loop, for example, of you are sending data faster than the arduino can process. After all, you only read the first character (The rest is ignored and processed later, so you need to define how many digits your sensor data should send to avoid "catching" a bit from anything else, should any more data be received)

parseInt reads the serial data until a non-digit is found and then stops, it converts the read data into an integer. It reads the data, so the datastream also advances to the next non-digit data.

loop { something available() ? read() it, is it ‘a’ or ‘b’ ? parseInt() }
The loop can be the loop() function.

You can test it in the serial monitor, type the data (for example in the a23b444# format) and let the sketch return the integer values.

Forgot to mention:

You can also use the text.finder library.

Send all sensor values, separated by a comma. Send a stop character. For example \CR (carriage return) or \n (new line) at the end.
On the receiver, create an array large enough to receive all fields. You also need to wait for the stop character to be received. Then, everything that comes next is in order.

This method works in the assumption that the slave knows exactly the order of the values received, therefore sensor 1, sensor 2, sensor n… so you only need to send the values. Since less data is transfered and you dont need to check what is what it turns out to be a bit faster.

For example:

in your code:

Serial.print(A0);
Serial.print(A1);
Serial.print(A2);
Serial.print(A3);
Serial.print('\n');

is received on the master as:

1024, 768, 59, 658, \n

The text finder library then updates an array with the values received. Now simply print them or process them as you need.

Here’s an example for printing:

Serial.print (myarray[0]);
Serial.print (myarray[1]);

Or make a loop if you have many values

//print an array of 50 
for (int x = 0; x < 50; x = x + 1)
{ 
Serial.print (myarray[x]);
}

PaulS - I tried it, but I must be doing something wrong.
here is the modified receiver code:

int sensor=0;

int inByte = -1;
char inString[6];
int stringPos = 0; 



void setup()  { 

  Serial.begin(9600); 


} 

void loop() { 
   if(Serial.available() > 0){
   
char inChar = Serial.read();

if (inChar == 'a')
{
   inByte = Serial.read();
  //if there is any numerical serial available, store that
  if((inByte >= '0') && (inByte <= '9')){
    inString[stringPos] = inByte;
    stringPos ++;
  }

  //if there is a line end character, this string is done, take value and write to LED pin
  //clear the string when done
  if(inByte == '\r'){
    sensor = atoi(inString); //convert string to int
Serial.println(sensor);
    //clear the values from inString
    for (int c = 0; c < stringPos; c++){
      inString[c] = 0;
    }
    stringPos = 0;
  }

}
}
}

Peter_n - Thanks, I think i get it now, will try and let you know

   if(Serial.available() > 0){
   
char inChar = Serial.read();

if (inChar == 'a')
{
   inByte = Serial.read();

If there is one byte to read, do NOT try to read two bytes.

    //clear the values from inString
    for (int c = 0; c < stringPos; c++){
      inString[c] = 0;
    }

If a function ignores the first stop sign, why on earth do you expect it to stop at the second or third or 20th?

Learn to keep the array NULL terminated, by adding a NULL after every character is added. When you “reset” the string, put ONE null in the first position.

PaulS - I tried it, but I must be doing something wrong.

Well, there are no calls to peek() so, yes, you are doing something wrong.

After reading your PM, I begin to see what the problem is. On the senders, you need to send an ID as part of the packet. You need to send start and end of packet markers, too. For instance, sender one should send “<1:12>”, where the sender ID is 1, the value is 12, and < and > are the start and end of packet markers.

On the receiver, some code like this:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Where is says “Process the packet”, inData will contain “1:12”, given the example above. strtok() and atoi() can be used to get two tokens ('1" and “12”) and to convert the tokens to ints (int ID = atoi(token1); int val = atoi(token2);).

Thank you all
I got it working using Serial.parseInt()
here is my code for the next person who needs it.

sender coder:

const int analogPin1 = A0;
const int analogPin2 = A1;
void setup()
{
Serial.begin(9600);

}

void loop()
{   

  int  sensor1 = analogRead(analogPin1) ;
  int  sensor2 = analogRead(analogPin2) ;
  Serial.write('a');
Serial.println(sensor1);
delay(1000);
Serial.write('b');
Serial.println(sensor2);
delay(1000);
  }

Receiver code:

int sensor1=0;
int sensor2=0;

int inByte = -1;
char inString[6];
int stringPos = 0; 

void setup() {
Serial.begin(9600);


delay(1000);

}

void loop() {
if(Serial1.available() > 0)
{
char inChar = Serial1.read();


if (inChar == 'a')
{
sensor1 = Serial1.parseInt() ;
Serial.println(sensor1);
}

if (inChar == 'b')
{
sensor2 = Serial1.parseInt() ;
Serial.println(sensor2);
}
}
delay(100);
}

This seems to me the easiest way.
I would welcome any feedback :slight_smile:
Again thanks.

Where is the Serial1.begin ?

Sorry. Leftover from softserial experiment.

The receiver code:

int sensor1=0;
int sensor2=0;

int inByte = -1;
char inString[6];
int stringPos = 0; 

void setup() {
Serial.begin(9600);


delay(1000);

}

void loop() {
if(Serial.available() > 0)
{
char inChar = Serial.read();


if (inChar == 'a')
{
sensor1 = Serial.parseInt() ;
Serial.println(sensor1);
}

if (inChar == 'b')
{
sensor2 = Serial.parseInt() ;
Serial.println(sensor2);
}
}
delay(100);
}