Multiple Serial Devices on Arduino Uno

Recently, I was given a project where I had to read multiple sensors with a UART interface. Many in the Arduino user community stated that this couldn't be done on a UNO board. I was able to make it work for four sensors. I have attached the code here. Hopefully, this is valuable to other users.

#include <SoftwareSerial.h>
SoftwareSerial mySerial_1(8, 9);
SoftwareSerial mySerial_2(10, 11);
SoftwareSerial mySerial_3(12, 13);
SoftwareSerial mySerial_4(A0,A1);

#include <LiquidCrystal.h>
LiquidCrystal lcd (2, 3, 4, 5, 6, 7);

unsigned char hexdata[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};

int SensorSelect = 1;   // Start reading from the 1st CO2 sensor
int TD = 1000;          // time delay

void setup() {
  Serial.begin(9600); //Serial communication with computer
  lcd.begin (16, 2);  //Set the size of the LCD display

  while (!Serial)
  {
  }

  lcd.setCursor(0, 0); // Thanking NASA for the opportunity
  lcd.print(" THANK YOU NASA ");
  lcd.setCursor(0, 1);
  lcd.print("SPACE CO2 DETECT");

  delay(1000);

}

void loop()
{

  switch (SensorSelect)
  {
    
  case 1:

  Serial.println("Attempting to read sensor 1...");

  mySerial_1.begin(9600);
  delay(TD);

  mySerial_1.write(hexdata, 9);
  delay(TD);

  for (int i1 = 0; i1 < 9; i1++) //CO2 sensor 1
  {

    if (mySerial_1.available() > 0)
    {

      Serial.println("Reading sensor 1...");

      long hi_1, lo_1, CO2_1;
      int ch_1 = mySerial_1.read();

      if (i1 == 2)
      {
        hi_1 = ch_1; //high concentration of CO2
      }

      if (i1 == 3)
      {
        lo_1 = ch_1; //low concentration of CO2
      }

      if (i1 == 8)
      {

        CO2_1 = hi_1 * 256 + lo_1; //CO2 concentration equation

        Serial.println("Sensor 1 Reading");
        Serial.print("CO2 concentration: ");
        Serial.print(CO2_1);// display concentration on computer
        Serial.println(" ppm");

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Sensor 1 Reading");
        lcd.setCursor(0, 1);
        lcd.print("CO2: "); //display concentraition on LCD
        lcd.print(CO2_1);
        lcd.print(" ppm");

      }

    }

  }

  SensorSelect = 2;  // Read the next sensor

  break;

  case 2:

  mySerial_2.begin(9600);
  delay(TD);

  Serial.println("Attempting to read sensor 2...");

  mySerial_2.write(hexdata, 9);
  delay(TD);

  for (int i2 = 0; i2 < 9; i2++) //CO2 sensor 2
  {

    if (mySerial_2.available() > 0)
    {

      Serial.println("Reading sensor 2...");

      long hi_2, lo_2, CO2_2;
      int ch_2 = mySerial_2.read();

      if (i2 == 2)
      {
        hi_2 = ch_2; //high concentration of CO2
      }

      if (i2 == 3)
      {
        lo_2 = ch_2; //low concentration of CO2
      }

      if (i2 == 8)
      {

        CO2_2 = hi_2 * 256 + lo_2; //CO2 concentration equation

        Serial.println("Sensor 2 Reading");
        Serial.print("CO2 concentration: ");
        Serial.print(CO2_2);// display concentration on computer
        Serial.println(" ppm");

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Sensor 2 Reading");
        lcd.setCursor(0, 1);
        lcd.print("CO2: ");
        lcd.print(CO2_2);
        lcd.print(" ppm");

      }

    }

  }

  SensorSelect = 3;  // Read the next sensor

  break;

  case 3:

  mySerial_3.begin(9600);
  delay(TD);

  Serial.println("Attempting to read sensor 3...");

  mySerial_3.write(hexdata, 9);
  delay(TD);

  for (int i3 = 0; i3 < 9; i3++) //CO2 sensor 3
  {

    if (mySerial_3.available() > 0)
    {

      Serial.println("Reading sensor 3...");

      long hi_3, lo_3, CO2_3;
      int ch_3 = mySerial_3.read();

      if (i3 == 2)
      {
        hi_3 = ch_3; //high concentration of CO2
      }

      if (i3 == 3)
      {
        lo_3 = ch_3; //low concentration of CO2
      }

      if (i3 == 8)
      {

        CO2_3 = hi_3 * 256 + lo_3; //CO2 concentration equation

        Serial.println("Sensor 3 Reading");
        Serial.print( "CO2 concentration: ");
        Serial.print(CO2_3);// display concentration on computer
        Serial.println(" ppm");

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Sensor 3 Reading");
        lcd.setCursor(0, 1);
        lcd.print("CO2: ");
        lcd.print(CO2_3);
        lcd.print(" ppm");

      }

    }

  }

  SensorSelect = 4;  // Read the next sensor

  break;

  case 4:

  mySerial_4.begin(9600);
  delay(TD);

  Serial.println("Attempting to read sensor 4...");

  mySerial_4.write(hexdata, 9);
  delay(TD);

  for (int i4 = 0; i4 < 9; i4++) //CO2 sensor 4
  {

    if (mySerial_4.available() > 0)
    {

      Serial.println("Reading sensor 4...");

      long hi_4, lo_4, CO2_4;
      int ch_4 = mySerial_4.read();

      if (i4 == 2)
      {
        hi_4 = ch_4; //high concentration of CO2
      }

      if (i4 == 3)
      {
        lo_4 = ch_4; //low concentration of CO2
      }

      if (i4 == 8)
      {

        CO2_4 = hi_4 * 256 + lo_4; //CO2 concentration equation

        Serial.println("Sensor 4 Reading");
        Serial.print( "CO2 concentration: ");
        Serial.print(CO2_4);// display concentration on computer
        Serial.println(" ppm");

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Sensor 4 Reading");
        lcd.setCursor(0, 1);
        lcd.print("CO2: ");
        lcd.print(CO2_4);
        lcd.print(" ppm");

      }

    }

  }

  SensorSelect = 1;  // Read the next sensor

  break;

  }


delay(500);

}
1 Like

Strange. As long as you know the limitations of the software serial port library, then it shouldn't be a problem under certain conditions. The 2 main considerations are:

  • It cannot transmit and receive data at the same time.
  • If using multiple software serial ports, only one can receive data at a time.

You can use the listen function to switch between listening software serial ports as shown in the library documentation here:

Well done!
The cleverness is handling one channel at the time. The UNO acts like a master, being in total control.
Using a multiplexer directed by the UNO the same strategy ought to work as well.

That statement needs to be qualified

What is true is that many in the Arduino user community stated that this couldn't be done on a UNO board with multiple asynchronous serial inputs

Well done for getting it working with your particular requirements

You can simplify the code by using an array of SoftwareSerial.

#include <SoftwareSerial.h>
SoftwareSerial mySerials[4] = { { 8, 9 }, { 10, 11 }, { 12, 13 }, { A0, A1 } };

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

unsigned char hexdata[9] = { 0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 };

const int TD = 1000;  // time delay

int CO2[4];

void setup()
{
  Serial.begin(9600);  //Serial communication with computer
  lcd.begin(16, 2);    //Set the size of the LCD display

  lcd.setCursor(0, 0);  // Thanking NASA for the opportunity
  lcd.print(" THANK YOU NASA ");
  lcd.setCursor(0, 1);
  lcd.print("SPACE CO2 DETECT");

  for (int i = 0; i < 4; i++)
  {
    mySerials[i].begin(9600);
  }
}

void loop()
{
  for (int port = 0; port < 4; port++)
  {
    Serial.print("Attempting to read sensor ");
    Serial.print(port + 1);
    Serial.println("...");

    // Start listening
    mySerials[port].listen();

    delay(TD);

    // Poll the device
    mySerials[port].write(hexdata, 9);

    // Wait for all of the characters to arrive
    delay(TD);

    // make sure all of the characters have arrived
    if (mySerials[port].available() < 9)
    {
      Serial.println("Device did not respond.");
      continue;  // skip to the next device
    }

    Serial.print("Reading sensor ");
    Serial.print(port + 1);
    Serial.println("...");

    // Read the 9 bytes, using only two
    mySerials[port].read();           // 0
    mySerials[port].read();           // 1
    int hi = mySerials[port].read();  // 2
    int lo = mySerials[port].read();  // 3
    mySerials[port].read();           // 4
    mySerials[port].read();           // 5
    mySerials[port].read();           // 6
    mySerials[port].read();           // 7
    mySerials[port].read();           // 8

    CO2[port] = hi * 256 + lo;  //CO2 concentration equation

    Serial.print("Sensor ");
    Serial.print(port + 1);
    Serial.println(" Reading");
    Serial.print("CO2 concentration: ");
    Serial.print(CO2[port]);  // display concentration on computer
    Serial.println(" ppm");

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Sensor ");
    lcd.print(port + 1);
    lcd.println(" Reading");
    lcd.setCursor(0, 1);
    lcd.print("CO2: ");  //display concentraition on LCD
    lcd.print(CO2[port]);
    lcd.print(" ppm");
  }

  delay(500);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.