Hello,
I want first to thank all the contributors to this forum. The discutions are informative and helpful.
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));
}