Arduino Nano Every Serial is cutting incoming messages

Hello,
I want first to thank all the contributors to this forum. The discutions are informative and helpful. :slightly_smiling_face:

I have a problem with two Arduino Nano Every modules that are communicating using Serial1. The transmitted line is 8000@8000@8000@.
The problem: The receiver is splitting the string. Mostly the split is into 2 parts: the first 4 characters of the line (8000), then all the rest of the transmission (@8000@8000@). This structure was achieved after some experiments focusing on the the filter
if(Serial1.available() < commandSegmentLen) return false;
Neither interrupts nor delay() statement are being used, and delays utilize the millis() statement. The CPU clock speed is the default value, so are the TX1 and RX1 pins. Serial1 is used from the IDE built-in library.
The hardware was reduced into hookupping the TX1 and RX1 pins of the two Nano Everys.
The following very simple class is being used by both communicating stations. I tried to add delays in the reading loop (as can be seen, and in another places) to allow recovery time for the HW UART. Nothing helped.
During the experiments I started to suspect the Serial1.available() statement – may it be unstabe? The MPU datasheet does not suggest the availability of a byte counter for the receiver; hence I assume this method is a software-based. I couldn't the source of thios method.

#ifndef Serial1CommClass
#define Serial1CommClass

class serial1Communication {
public:
  bool begin();
  bool txData(String txStr);
  bool rxData(String &rxStr, uint8_t rxSizeLim);
private:
  #define delimiter '.'
//  #define hc12Mode
  #ifndef hc12Mode
    #define RS485mode
  #endif
  #define SerialBaudRatePort1 9600
} Comm;
//**************************************
bool serial1Communication::begin() {
  Serial1.begin(SerialBaudRatePort1);
  pinMode(txRxPin, OUTPUT);
  digitalWrite(txRxPin, false); // If RS485-transciever to RX mode; if HC12 - transparent
  while (!Serial1)
    ;
  return true;
}
//**************************************
bool serial1Communication::txData(String txStr) {
#ifdef RS485mode
  digitalWrite(txRxPin, true);  // If RS485 - set transciever to TX mode
#endif
  Serial1.print(txStr);
  Serial1.flush();
#ifdef RS485mode
  digitalWrite(txRxPin, false);  // If RS485 - set transciever to RX mode
#endif
  return true;
}
//**************************************
bool serial1Communication::rxData(String &rxStr, uint8_t rxSizeLim) {
  rxStr = "";
  if(Serial1.available() < commandSegmentLen)
    return false;
  while (Serial1.available() && ((uint8_t)rxStr.length() < rxSizeLim)){
    char c = (char)Serial1.read();
    if (c == delimiter)    // Terminate the reception when the delimiter arrives
      break;
    rxStr += c;
    for (int i = 0; i < 1000; i++) ;    // Delay between characters for UART recovery
  }
  return (rxStr.length() > 0);
}
#endif

The relevant sketch:

#include <Arduino.h>

#define txRxPin 15  // Both configs: RS485 direction - D15

#define SerialBaudRatePort0 9600
#define txInterval 1000
#define commandLineLength 21
#define commandSegmentLen 4

uint32_t timing, commError, previousPacketCounter, packetCounter;
uint32_t nullError = 0, correct = 0;

#include "SimplifiedGenericSupportClasses.h"
#include "CommClass.h"
/******************************************************
**************   Main programs   **********************
******************************************************/
void setup() {
  Serial.begin(SerialBaudRatePort0);
  Serial.println("Init started\n");
  while (!Serial)
    ;
  Comm.begin();  // Sets txRxPin as output; must be done after reading the stationType setting
  Serial.println("\nInit passed successfully.\n");  //  testing closure
}
/***********************************/
void loop() {
  String machineRxBuffer = "";
  if (!Comm.rxData(machineRxBuffer, commandLineLength))
    return;
  
//  Serial.println("MAC data received= <" + machineRxBuffer + "> (" + String(machineRxBuffer.length()) + ")");
  if(gpio.checkMachineReceivedString(machineRxBuffer))
    Comm.txData("Success " + String(++correct) + " (F=" + String(nullError) + ")");
  else
    Comm.txData("Failed" + String(++nullError));
}

We would like to see minimal compilable examples for both sender and receiver.

It's in the file UART.cpp in the megaAvr core.

Dear Sterretje,
Thank you for your response. The contents of MAC.INO were added to the issue body.

Regards
Yona

I had to remove anything related to SimplifiedGenericSupportClasses as you did not supply that class / file.

Can you please show the exact sender code.

Some comments

  1. After a flush it's advisable to wait one character time (at 9600 baud that is approx 1 ms) before you can issue the digitalWrite(txRxPin, false);. Reason is that you can disable the RS485 output before the complete last byte has been transmitted.
  2. Although true/false and HIGH/LOW represent the same value, you should use HIGH/LOW; the Nano Every does not use uint8_t (aka byte) like an 328P or 2560 but an enum called PinStatus.
  3. Serial is slow; that's probably the reason why you get what you observe. Your code is a lot faster so somewhere along the line a byte might not yet have been received completely and your Serial1.available() will return false. I suggest that you study Robin's update Serial Input Basics tutorial to get ideas.

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