Using serialEvent for Communication between two arduinos.

Hi everyone,

I am very new here,

I am working on project that involves a master arduino sending data to a slave arduinoMega. Each of them has sensors that detect stuff.
The code on the master senses an event and sends data via serial to the slave. The slave runs its own code (reading the sensors), but I need it to able read the incoming data from the master and do something with. I tried using serialEvent, but it does not work.
The slave code runs the normal routine of the reading the sensors, but does not run the case where it needs to do something with the serial data from the master.
Attached below are the codes.

Thank you very much for the help.

Master.ino (3.7 KB)

Slave.ino (4.44 KB)

Which serial port of the slave is used to receive data from the master ?

Unless it is the main Serial port then serialEvent() will not be run. For other serial ports on the mega there are corresponding serialEvent() functions named serial1Event() etc

However, I have never seen the point of the serialEvent functions. Why not just check whether data is available yourself and act on it ?

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

The technique in the 3rd example will be the most reliable.

You can send data in a compatible format with code like this

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

This is what I use for communication between my Arduinos.

...R

// The Event Report
  if(millis() - start <= 30000){

That if statement will be true for the first 30 seconds after reset and false forever after that. Is that what you intend? The start variable is never updated. See the blink without delay example to see how to use millis() for timing.

The serial input basics thread has information that will help you to send the data and reliably receive them on the other end without using the String class.

Serial.flush is almost never required.

@UKHeliBob

I am using the main serial on the mega, not the other ports...

"However, I have never seen the point of the serialEvent functions. Why not just check whether data is available yourself and act on it ?"

I tried it first, and it did not work...

@groundFungus
Thanks will check it out...
I intend that data be sent through serial for 30 seconds and stop, until when another event occurs...

@ Robin2
I am checking the examples you sent...thanks

I tried it first, and it did not work...

Show us what you tried.

If you put

if (Serial.available())
{
  //code to run if serial data is available
}

as the last lines of loop() then you can process incoming data in any way that you need

I am using the main serial on the mega, not the other ports...

I recommend that you use one of the extra serial ports on the Mega if you can. Having the main Serial to print debug messages to serial monitor is very valuable.

Many people think that serial event is an interrupt type of function. It is not. Putting serial.available in loop() so that it checks the serial buffer every time through loop() does exactly the same thing.

UKHeliBob:
Show us what you tried.

If you put

if (Serial.available())

{
  //code to run if serial data is available
}



as the last lines of loop() then you can process incoming data in any way that you need

I had it at the beginning of the loop though, I will change it and run again. Thanks.

UKHeliBob:
Show us what you tried.

If you put

if (Serial.available())

{
  //code to run if serial data is available
}



as the last lines of loop() then you can process incoming data in any way that you need

This is what I tried...

/* *** This is the Robot Sensor Node Code. ***********************************
 * *** The Robot receives the coord of the zone reporting an event ***********
 * *** and navigates there for assessment. ***********************************
 */
// Include necessary Libraries
#include "DHT.h"

//Initializing the Inputs
int Flame = 2; //Flame Sensor
int Gas_1 = 3;
int Gas_2 = 4;
int LEDPin = 6;
int Temp_nml_mx = 30; int Temp_hg = 40;
int RH_nml_mx = 40; int RH_lw = 30;

// Setup the DHT Sensor
#define DHTPIN 5          // DHT11 data pin is connected to Arduino pin 8
#define DHTTYPE DHT11     // DHT11 sensor is used
DHT dht(DHTPIN, DHTTYPE); // Initialize DHT library

// Communication Data
String data_1, data_2, data_3;
String X_coord = "2.0";
String Y_coord = "7.0";
String Even_Alert_CR = "1.0"; // 1.0 is Event Alert Critical
String Even_Alert_HG = "0.0"; // 0.0 is Event Alert High

void setup() {
  pinMode(Flame, INPUT);
  pinMode(Gas_1, INPUT);
  pinMode(Gas_2, INPUT);
  pinMode(LEDPin, OUTPUT);
  dht.begin();
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(115200);
}

void loop() {
  // Continuously run Event detection by the MSN and Route to BSN
  Event_detection();
  if(Serial.available()){
       String data_1 = Serial.readString();
       String data_2 = Serial.readString();
       String data_3 = Serial.readString();
       // In case of an Serial event from SSN, run code to send location into LabVIEW
       if(data_1 == X_coord && data_2 == Y_coord && data_3 == Even_Alert_CR)
        {
          Serial.print("X_coord: ");Serial.println(X_coord);
          Serial.print("Y_coord: ");Serial.println(Y_coord);
          Serial.println("Critical Event Detected at");
          Serial.println("(" + X_coord + "," + Y_coord + ")");
          Serial.println("Wait till Event is Suppressed");
          // Send to Serial1 of Arduino Mega, Routing to Base Station
          Serial1.print("Node");Serial1.println("SSN1");
          Serial1.print("X_coord: ");Serial1.println(X_coord);
          Serial1.print("Y_coord: ");Serial1.println(Y_coord);
          Serial1.println("Critical Event Detected at");
          Serial1.println("(" + X_coord + "," + Y_coord + ")");
          // Send to Serial2 of Arduino Mega, Sending location into LabVIEW
          Serial2.println(X_coord);
          Serial2.println(Y_coord);
          Serial2.println(Even_Alert_CR);
         }
       else if(data_1 == X_coord && data_2 == Y_coord && data_3 == Even_Alert_HG)
        {
          Serial.print("X_coord: ");Serial.println(X_coord);
          Serial.print("Y_coord: ");Serial.println(Y_coord);
          Serial.println("High Alert Event Detected at");
          Serial.println("(" + X_coord + "," + Y_coord + ")");
          Serial.println("Navigate to Event Location");
          // Send to Serial2 of Arduino Mega, Sending location into LabVIEW
          Serial2.println(X_coord);
          Serial2.println(Y_coord);
          Serial2.println(Even_Alert_HG);
         }
     }   
}
 
// Event Detection Function
void Event_detection(){
  // Read DHT Sensor
  int RH = dht.readHumidity(); int Temp = dht.readTemperature();
  // Indicate that data reported is from mobile node
  Serial1.print("Node: ");Serial1.println("MSN");
  // Case Critical Event
  if((digitalRead(Flame) == HIGH) && (digitalRead(Gas_1) == HIGH) && (digitalRead(Gas_2) == HIGH) 
     && (Temp > Temp_hg) && (RH < RH_lw))
     {
      digitalWrite(LEDPin,HIGH);
      Serial1.println("Zone 1");
      Serial1.print("Event: ");Serial1.println("Critical");
      Serial1.print("Temperature: ");Serial1.println(Temp);
      Serial1.print("Relative Humidity(RH): ");Serial1.println(RH);
      delay(200);
     }
  // Case High_Alert Event
  else if((digitalRead(Flame) == HIGH) || (digitalRead(Gas_1) == HIGH) || (digitalRead(Gas_2) == HIGH)
          || (Temp > Temp_nml_mx && Temp < Temp_hg) || (RH > RH_lw && RH < RH_nml_mx)) 
     {
      digitalWrite(LEDPin,HIGH);
      Serial1.println("Zone 1");
      Serial1.print("Event: ");Serial1.println("High_Alert");
      Serial1.print("Temperature: ");Serial1.println(Temp);
      Serial1.print("Relative Humidity(RH): ");Serial1.println(RH);
      delay(200);
     }
  // Case Normal Event   
  else if((digitalRead(Flame) == LOW) && (digitalRead(Gas_1) == LOW) && (digitalRead(Gas_2) == LOW)
          && (Temp <= Temp_nml_mx) && (RH >= RH_nml_mx))
     {
      digitalWrite(LEDPin,LOW);
      Serial1.println("Zone 1");
      Serial1.print("Event: ");Serial1.println("Normal");
      Serial1.print("Temperature: ");Serial1.println(Temp);
      Serial1.print("Relative Humidity(RH): ");Serial1.println(RH);
      delay(200);
     }
}

I had it at the beginning of the loop though, I will change it and run again. Thanks.

Beginning or end of loop() should make no difference. In fact it can be anywhere in loop() or a function called from loop() as long as free running of the code is not prevented.

I see in your code that you have delay()s so free running of the code is being prevented and you also use Serial.readString() which I believe is a blocking function

May I suggest that you write a small sketch that only sends some hard coded data from one Arduino to the other. That removes all of the non-essential code and makes debugging easier. Once that you have the serial comms working, add in the code for sending real data a piece at a time. It is much easier to troubleshoot when adding code incrementally. Then you know when it goes south and have a better idea of what caused the problem.

Please look at the serial input basics tutorial. Using the start/end marker method will make communication more reliable. And not using the String class will make the program smaller and more reliable in the long term.

groundFungus:
May I suggest that you write a small sketch that only sends some hard coded data from one Arduino to the other. That removes all of the non-essential code and makes debugging easier. Once that you have the serial comms working, add in the code for sending real data a piece at a time. It is much easier to troubleshoot when adding code incrementally. Then you know when it goes south and have a better idea of what caused the problem.

Please look at the serial input basics tutorial. Using the start/end marker method will make communication more reliable. And not using the String class will make the program smaller and more reliable in the long term.

Thanks for the recommendation...
The issue is the slave Mega further sends the data into LabVIEW, thats why I am using strings, for it is easier that way in LabVIEW.

Robin2:
Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

The technique in the 3rd example will be the most reliable.

You can send data in a compatible format with code like this

Serial.print('<'); // start marker

Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker





This is what I use for communication between my Arduinos.

...R

What class of data can I use as value1...value2..., strings, chars, or int...

What class of data can I use as value1...value2..., strings, chars, or int...

Yes.

Chidore:
What class of data can I use as value1...value2..., strings, chars, or int...

Any of them.

But it would help to know what you want to do when you receive the data. Post an example of the sort of message you want to send and explain how it will be used.

...R

Robin2:
Any of them.

But it would help to know what you want to do when you receive the data. Post an example of the sort of message you want to send and explain how it will be used.

...R

Thanks @ Robin2,
I want to send a location (x,y) and a flag (1 or 0). Something like this

String x_loc = "1.0";
String y_loc = "2.0";
String flag = "1";
string flag_2 = "0";

if(something is true)
Send x_loc
Send y_loc
Send flag
else
Send x_loc
Send y_loc
Send flag_2

Sorry I used pseudocode...:slight_smile:
On the other side, I want to receive these data piece by piece, in sequential order, x_loc, y_loc and the flags.
I having been using strings because, when I receive the data in the second arduino, and further send them into LabVIEW where strings are the most preferred way to receive data.

Thank you very much.

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. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

It will be very much simpler if you send all the data in a single message. The example I posted in Reply #2 was this

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

If you want to change it to send three pieces of information just change it to this

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.print(','); // comma separator
Serial.print(value3);
Serial.println('>'); // end marker

As far as receiving is concerned have you carefully studied the parse example in Serial Input Basics ?

...R