2+ Serials read at the same time

Hi
I have a requirement to listen on 3 serial ports connected through max232 to the device

I have defined the SoftwareSerial as

SoftwareSerial Serial2(D8, D7, false, 256);
and in setup i have:

Serial.begin(115200);
Serial2.begin(9600);

in my loop i try to read the values as follows

void loop() {
delay(5); //wait for data to arrive

if (Serial.available() > 128)
{
while (Serial.available() > 0)
{
processIncomingByte(Serial.read());
}

}

if (Serial2.available() > 128) {
while (Serial2.available() > 0)
{
processIncomingByte(Serial2.read());
}
}
}

Hardware serial works just fine and always receive the data.
SoftwareSerial on the other hand seems to be working completly randomly. in fact more not receiving anything than receiving.

The string im receiving is always 128-145 characters long.

Can someone point me in the right direction or show what im doing wrong ?
Best Regards

delay(5); //wait for data to arrive

Don't! That's what the next line does :wink:

Also

if (Serial.available() > 128)

Don't :wink: The buffer isn't that big om most devices. So if you want to store more bytes, make your own buffer and read serial waayyyyyyyyyyy more often!

septillion:

delay(5); //wait for data to arrive

Don’t! That’s what the next line does :wink:

Also

if (Serial.available() > 128)

Don’t :wink: The buffer isn’t that big om most devices. So if you want to store more bytes, make your own buffer and read serial waayyyyyyyyyyy more often!

thanks,

i removed the delay
regarding the buffer here is how i fill my own buffer:

void processIncomingByte(const byte inByte)
{
	static unsigned int input_pos = 0;
	static char input_line[MAX_INPUT];
	switch (inByte)
	{

	case '\n':   // end of text
		input_line[input_pos] = 0;  // terminating null byte

		// terminator reached! process input_line here ...
		process_data(input_line);

		// reset buffer for next time
		input_pos = 0;
		break;

	case '\r':   // discard carriage return
		break;

	default:
		// keep adding if not full ... allow for terminating null byte
		if (input_pos < (MAX_INPUT - 1))
			input_line[input_pos++] = inByte;
		break;

	}  // end of switch

}

Still the same behaviour.

pluciorx:
here is how i fill my own buffer:

But first you wait till there are 128 bytes in the buffer of Serial...

septillion:
But first you wait till there are 128 bytes in the buffer of Serial...

yes correct because i dont want to process partial data.

But I suggest you do :wink:

Which arduino are you using? The title mentions three serial ports, running more than a single software serial port can be unreliable.

Personally, I would keep the default buffer size on the serial ports, and create buffers in the code. Call serial receive functions every time through loop, if there is input available append it to the buffer, then process the data when the end of line has been received. Pretty standard process using the examples from Serial Input Basics.

david_2018:
Which arduino are you using? The title mentions three serial ports, running more than a single software serial port can be unreliable.

Personally, I would keep the default buffer size on the serial ports, and create buffers in the code. Call serial receive functions every time through loop, if there is input available append it to the buffer, then process the data when the end of line has been received. Pretty standard process using the examples from Serial Input Basics.

I've created a buffer char buffer[com_cnt][max_input]

There is nearly no difference in behaviour now.

One of the problems with the code

if (Serial.available() > 128)

is that when you have a line with slightly more than 129 characters, the first 129 characters will get read in when you reach the 129th character, but the rest of the line will sit in the receive buffer until you receive enough additional characters to add up to 129 again. If there is a long delay between lines received, you will have a very noticeable delay in your code.

david_2018:
One of the problems with the code

if (Serial.available() > 128)

is that when you have a line with slightly more than 129 characters, the first 129 characters will get read in when you reach the 129th character, but the rest of the line will sit in the receive buffer until you receive enough additional characters to add up to 129 again. If there is a long delay between lines received, you will have a very noticeable delay in your code.

Yes correct so now i changed the reading to:
while (Serial.available() > 0)
{
src_com = 0;
processIncomingByte(Serial.read(), src_com);
}

while (Serial1.available() > 0)
{
src_com = 1;
processIncomingByte(Serial1.read(), src_com);
}

and declared buffer as
static char input_line[SERIAL_PORT_CNT][MAX_INPUT];

and filling the buffer:
if (input_pos < (MAX_INPUT - 1))
input_line[serialPort][input_pos++] = inByte;
break;

the HW serial reads just fine, but SoftwareSerial will not read inputs at any baud… ( but RS led blinks during transmission)

Can you provide a MCVE to show (and prove) this behavior?

Personally, I wouldn’t try to do the receive with a common function, having separate receive functions for each serial port is easier to implement and understand. If I were to use a common function, I would just pass the port number to the function, then do the test for Serial.available() inside the function. It also is rarely the case where the function to process the incoming data is the same for each serial port, incorporating that into a common function would be a bit cumbersome.

A generic sketch to read two serial ports and then print the incoming text to the serial monitor:

#include <SoftwareSerial.h>
SoftwareSerial Serial2(8, 7);

const byte bufferSizeSerial = 150; //define size of receive buffer
char receivedCharsSerial[bufferSizeSerial]; // an array to store the received data
bool newDataSerial = false;

const byte bufferSizeSerial2 = 150; //define size of receive buffer
char receivedCharsSerial2[bufferSizeSerial2];   // an array to store the received data
bool newDataSerial2 = false;

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600);
}

void loop() {
  recvWithEndMarkerSerial(); //check Serial for incoming data
  recvWithEndMarkerSerial2(); //check Serial2 for incoming data
  showNewDataSerial(); //process data from Serial
  showNewDataSerial2(); //process data from Serial2
}

// Example 2 - Receive with an end-marker
// copied from the "Serial Input Basics" tutorial
void recvWithEndMarkerSerial() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  while (Serial.available() > 0 && newDataSerial == false) {
    rc = Serial.read();

    if (rc != endMarker) {
      receivedCharsSerial[ndx] = rc;
      ndx++;
      if (ndx >= bufferSizeSerial) {
        ndx = bufferSizeSerial - 1;
      }
    } else {
      receivedCharsSerial[ndx] = '\0'; // terminate the string
      ndx = 0;
      newDataSerial = true;
    }
  }
}

void recvWithEndMarkerSerial2() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  while (Serial2.available() > 0 && newDataSerial2 == false) {
    rc = Serial2.read();

    if (rc != endMarker) {
      receivedCharsSerial2[ndx] = rc;
      ndx++;
      if (ndx >= bufferSizeSerial2) {
        ndx = bufferSizeSerial2 - 1;
      }
    } else {
      receivedCharsSerial2[ndx] = '\0'; // terminate the string
      ndx = 0;
      newDataSerial2 = true;
    }
  }
}

void showNewDataSerial() {
  if (newDataSerial == true) {
    Serial.print("Serial: ");
    Serial.println(receivedCharsSerial);
    newDataSerial = false;
  }
}

void showNewDataSerial2() {
  if (newDataSerial2 == true) {
    Serial.print("Serial2: ");
    Serial.println(receivedCharsSerial2);
    newDataSerial2 = false;
  }
}

I have made a simple sketch showing what’s the issue:

#include <SoftwareSerial.h>

SoftwareSerial Serial3(D4, D3); //RX,TX

#define SERIAL_PORT_CNT 2
//Iputs
const unsigned int MAX_INPUT = 145;

enum E_STATE {
	READ_KB,
	SERIAL_READING,
	UPLOAD
};
E_STATE _state;

void setup()
{
	// Open serial communications and wait for port to open:
	Serial.begin(115200);
	Serial3.begin(9600);
	Serial.println("Goodnight moon!");

	// set the data rate for the SoftwareSerial port
	_state = SERIAL_READING;
}

void loop() // run over and over
{
	switch (_state)
	{
	case READ_KB: {
		//some code to read kb is here
	}break;
	case SERIAL_READING: {
		//delay(5);
		int src_com;

		/*char key = myKeypad.getKey();
		if (key != NULL) {
			if (key == '*')
			{

				_state = READ_KB;
				break;
			}
		}*/

		if (Serial3.available() > 0)
		{
			src_com = 1;
			processIncomingByte(Serial3.read(), src_com);
		}

		if (Serial.available() > 0)
		{
			src_com = 0;
			processIncomingByte(Serial.read(), src_com);
		}

		
	}break;
	}
}
	void processIncomingByte(const byte inByte, int serialPort)
	{
		static unsigned int input_pos = 0;

		static char input_line[SERIAL_PORT_CNT][MAX_INPUT];
		switch (inByte)
		{

		case '\n':   // end of text
			input_line[serialPort][input_pos] = 0;  // terminating null byte

			// terminator reached! process input_line here ...

			process_data(input_line[serialPort]);

			// reset buffer for next time
			input_pos = 0;
			break;

		case '\r':   // discard carriage return
			break;

		default:
			// keep adding if not full ... allow for terminating null byte
			if (input_pos < (MAX_INPUT - 1))
				input_line[serialPort][input_pos++] = inByte;
			break;

		}  // end of switch

	}
	void process_data(String data)
	{

		Serial.println(data);
		Serial.print("length:");
		Serial.println(data.length());

		if (data.length() < 135)
		{
			Serial.print("Data incomplete:");
			Serial.print(data.length());
			return;
		}

		Serial.println("Data OK");
	}

so here suprisingly it works slightly better apart from the fact that firs send to sw serial have 0 bytes.

I have tested this today on NodeMCU V1 board and the issue exists.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

If this was my project I would make two versions of the appropriate function and call them from loop() like this (expanded from the second example in the Tutorial

void loop() {
    recvWithEndMarker();
    recvSoftWithEndMarker();
    showNewData();
    showNewSoftData();
}

...R