Serial2 Arduino Mega does not work without Serial Monitor open

Hi all,

I have an Arduino mega which communicates through Serial2 to a device to collect data. However, it only works when I open the serial monitor with USB connected. However, it does not work without opening the serial monitor. I've read that Serial blocks the code waiting for data. I though the serial monitor is linked to the definition of Serial.begin (no Serial1, Serial2, Serial3). How can I make it work?

Thanks,

Raúl

On a Mega, Serial does not care if something is connected or not.

You can use Serial.availableForWrite() to check if there is space in the software buffer used by the hardware serial. Don't try to send if there is no space

You mean Serial2.availableForWrite() in my case? Should I use it at the end of the code or after each Serial.read call?

=== It does not make sense that you need to have serial monitor open. Unless your code expects data on Serial and waits for that. Or you don't use a Mega but an Arduino with native USB support.

=== Which one? No idea.

All 4 serial ports on the Mega have a buffer implemented in software with a size of 64 bytes. A print/write will place bytes in that buffer and the respective interrupts will take them out and transmit those bytes to what is connected.

If you put data faster in the buffer than the interrupt can take them out, the buffer will fill up and at the end be full and your code will wait (block) till it can put data in again.

If your baudrate is 9600, it takes roughly 1 ms to transfer one byte over the serial line. Your arduino could have put 10 or 20 bytes in that same time in the buffer.

=== The suggestion to use availableForWrite is to prevent the blocking when the buffer is full. It must be on the port that you're 'overfilling'.

=== I suggest that you give a good description of the functionality of what your Mega is doing. I also suggest tat you post your code so we can look at it. Spec of your device connected to Serial2 can also be useful.

=== Below is basically a recipe for disaster. It however depends on how often data is read from Serial2 and how much data you receive in 'one go'. If your device on Serial2 pumps out data continously at 115200 (just an example; 10 times as fast as you pump it out on Serial)) without breaks in the transmission, your code will slow down.

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

void loop()
{
  if(Serial2.available()
  {
    Serial.write(Serial2.read());
  }
}

The best solution is to increase the baudrate of Serial or decrease the baudrate of Serial2. The alternative is to change loop() to below. You will loose data at the receiving end of Serial2.

void loop()
{
  if(Serial2.available()
  {
    // if there is space in the buffer of Serial
    if(Serial.availableForWrite() > 1)
    {
      // read from Serial2 and transfer on Serial
      Serial.write(Serial2.read());
    }
  }
}

This is my code:

const int PR21_NO = 43; const int PR21_NC = 42;
.....
int x, flag = 0, y, delay_ = 700, pin = 0, count=0, once=0, idx, ar[8] = {13, 20, 27, 33, 40, 47, 53, 60};
const byte MY_ADDRESS = 42, MASTER_ADDRESS = 25 ;
uint8_t Buffer[15];
byte BufferMT[11], dat=0;
char ini;
char Model;
uint8_t Channel, MayorRelease, MayorReleaseDec, Release,Address1,Address2,Address3,rssi,AFC,Band;

#define ArrayElementCount(x) (sizeof(x) / sizeof(x[0]))
#include <Wire.h>

void setup() {
  Wire.begin (MY_ADDRESS); 
  Serial2.begin (9600); 
  Wire.onReceive(receiveEvent);
  .....
  pinMode(A_TEST, OUTPUT); digitalWrite(A_TEST, HIGH); 
  
}

void loop() {
  if (flag == 1)
  {
    if (y == 36) {
      
      pin = 0; check(pin);
    } 
    else if (y == 37) {
      
      pin = 1; check(pin);
    }
    else if (y == 35) {
      
      pin = 2; check(pin);
    }
    else if (y == 34) {
      
      pin = 3; check(pin);
    } 
    else if (y == 33) {
     
      pin = 4; check(pin);
    }
    else if (y == 38) {
      
      pin = 5; check(pin);
    } 
    else if (y == 26) {
      
      pin = 6; check(pin);
    } 
    else if (y == 24) {
      
      pin = 7; check(pin);
    } 
    else if (y == 22) {
      
      pin = 8; check(pin);
    } 
    else if (y == 41) {
      
      pin = 9; check(pin);
    } 
    else if (y == 40) {
      
      pin = 10; check(pin);
    } 
    else if (y == 39) {
      
      pin = 11; check(pin);
    } 
    else if (y == 31) {
      
      pin = 12; check(pin);
    }
    else if (y == 30) {
      
      pin = 13; check(pin);
    } 
    else if (y == 28) {
      
      pin = 14; check(pin);
    }
    else if (y == 100) {
      pin = 100;       
      initial(pin);      
    }
    else if (y == 200) {
      pin = 200; start(pin);
    } 
    else if (y == 210) {
      pin = 210; start(pin);
    }
    else if (y == 220) {
      pin = 220; start(pin);
    }
    else if (y == 230)
    {      
      digitalWrite(A_TEST, LOW);      
      delay (500);
      pin = 230; monitor_test();
    }
  }
}

void receiveEvent(int howMany) {
  y = Wire.read();
  flag = 1;  
}

void check (int pin)
{
  ...
}

void initial (int pin)
{
  static const uint8_t arraypin_NO[] = {PR5_NO, PR6_NO, PR9_NO, PR10_NO, PR11_NO, PR14_NO, PR15_NO, PR16_NO, PR17_NO, PR21_NO, PR22_NO, PR23_NO, PR25_NO, PR26_NO, PR27_NO};
  static const uint8_t arraypin_NC[] = {PR5_NC, PR6_NC, PR9_NC, PR10_NC, PR11_NC, PR14_NC, PR15_NC, PR16_NC, PR17_NC, PR21_NC, PR22_NC, PR23_NC, PR25_NC, PR26_NC, PR27_NC};
  int z = 15;

  if (pin == 100)
  {
    
    
      ini = 'O';
      Wire.beginTransmission (25);
      Wire.write (ini);
      Wire.endTransmission ();
      flag = 0;
    }
    else
    {
      ini = 'K';
      Wire.beginTransmission (25);
      Wire.write (ini);
      Wire.endTransmission ();
      flag = 0;
    }    
  }
}

void start (int pin)
{
  if (pin == 200)// Check START, CLAX, STOP and LAMP when MARCIA -> LOW
  {
    if (digitalRead(LAMP) == 0 && digitalRead(START) == 0 && digitalRead(CLAX) == 0 && digitalRead(STOP) == 0)
    {
      
      ini = 'O';
      Wire.beginTransmission (25);
      Wire.write (ini);
      Wire.endTransmission ();
      flag = 0;
    }
    else
    {
      ini = 'K';
      Wire.beginTransmission (25);
      Wire.write (ini);
      Wire.endTransmission ();
      flag = 0;
    }
  }
  else if (pin == 210)// Check START, CLAX, STOP and LAMP when MARCIA -> HIGH
  {
    ....
    Wire.beginTransmission (25);
    Wire.write (ini);
    Wire.endTransmission ();
    ini = 'Z';
    flag = 0;
  }
  else if (pin == 220)
  {
   
    if (digitalRead(LAMP) == 1 && digitalRead(START) == 1 && digitalRead(CLAX) == 1 && digitalRead(STOP) == 1)
    {
      
      ini = 'O'; // FAIL ALL
    }
    else
    {
      ini = 'K';
    }
    Wire.beginTransmission (25);
    Wire.write (ini);
    Wire.endTransmission ();
  }
}

void monitor_test()
{  
  if (once == 0)
  {    
   
    Serial2.write(0x03);
    Serial2.write(0x02);
    Serial2.write(0x01);
    Serial2.write(0x05);
    Serial2.write(0xF8);
    Serial2.write(0x03);
    Serial2.write(0x03);
   
    once = 1;
  }
  if (once == 1)
  {
    if (Serial2.available() > 0)
    {
      dat = Serial2.read();
      if (dat == 5)
      {
        
        count = 10;
      }
      if (dat == 255)
      {
        count = 30;
      }
      if (count == 11)
      {
        Model = dat;
        BufferMT[0] = Model;

      }
      if (count == 12)
      {
        MayorRelease = dat;
        BufferMT[1] = MayorRelease;
      }
      if (count == 13)
      {
        Release = dat;
       
      }
      if (count == 14)
      {
        MayorReleaseDec = dat;
        BufferMT[2] = MayorReleaseDec;
        Serial.println(MayorReleaseDec);
      }
      if (count == 15)
      {
        Address1 = dat;
        BufferMT[3] = Address1;
        
      }
      if (count == 16)
      {
        Address2 = dat;
        BufferMT[4] = Address2;
        
      }
      if (count == 17)
      {
        Address3 = dat;
        BufferMT[5] = Address3;
        
      }
      if (count == 31)
      {
        Band = dat;
        BufferMT[6] = Band;
        
      }
      if (count == 32)
      {
        Channel = dat + 1;
        BufferMT[7] = Channel;
       
        //once = 2;
      }
      if (count == 35)
      {
        once = 2;
      }
    }
    count = count + 1;
  }
  if (once == 2)
  {
    Serial2.write(5);
    Serial2.write(2);
    Serial2.write(1);
    Serial2.write(1);
    Serial2.write(252);
    Serial2.write(3);
    Serial2.write(3);
    once = 3;
    count = 0;
  }
  if (once == 3)
  {
    if (Serial2.available() > 0)
    {
      
      dat = Serial2.read();      
      if (dat == 1)
      {
        count = 10;
      }
      if (count == 11)
      {
        rssi = dat;
        BufferMT[8] = rssi;        
        idx = nearest(rssi, ar, ArrayElementCount(ar));
        BufferMT[9] = idx;
      }
      if (count == 12)
      {
        AFC = dat;
        BufferMT[10] = AFC;        
        Wire.beginTransmission (25);
        Wire.write((byte*)&BufferMT, sizeof(BufferMT));
        Wire.endTransmission ();        
        once = 4;
      }
      count = count + 1;      
    }
  }

    if (once == 4)
    {
      digitalWrite(A_TEST, HIGH);
      delay (500);           
    }  
}

int nearest(int x, int myArray[], int elements)
{
  int idx = 0; // by default near first element

  int distance = abs(myArray[idx] - x);
  for (int i = 1; i < elements; i++)
  {
    int d = abs(myArray[i] - x);
    if (d < distance)
    {
      idx = i;
      distance = d;
    }
  }
  return idx;
}

The default Serial function is not needed in my case since the acquire from the slave by the connected device (Serial2) is transmitted to the Master (i2C) and that last, process it.

So, if Serial is not used, Serial2 shouldn’t be “blocking” the system?

As far as I can see, the (visible !!) Serial will not cause problems. If the only place where you use Serial or Serial2 is in monitor_test, Serial, Serial2 and Serial Monitor is not the cause of your problem.