I have a project that I've been working to remotely control an Amateur Radio amplifier located in the basement. Over 90% of it is working but I have a bug that I can't figure out.
I have an M5Stack Core2 that is in the shack and sends 8v Power and Serial Comms to an Arduino NANO, located at the amplifier. The comms works GREAT, most of the time.
Both the M5Stack and NANO are running a 200ms Cycle Time (I don't see any over-runs). Loop Execution time is typically 20ms for both...
In trying to simulate loss & re-connection of comms, I cycle power to the NANO, but the comms but after that does NOT work as it should!
M5Stack code to start comms with the NANO:
NanoPort.end(true);
M5.delay(200);
NanoPort.begin(38400, SERIAL_8N1, NanoRxPin, NanoTxPin); //Serial.begin() will clear the buffer
//Check the communications with the NANO, once it boots up.
// We use the Volts to know when the NANO has sent Power to the Amp, and the voltage has been set
byte Count = 0;
do {
//After 2 seconds, change the Display to indicate we are Powering up the Nano.
String SecondLine = String(Mode);
SecondLine = SecondLine + " Count:" + String(Count) + "/100";
LcdLines("Wait for NANO Com", SecondLine); //LcdLines prints to M5Stack display.
Count++;
//Need to send Comms to the NANO to wake it up.
**Send5CheckSum(ModePowerTurnedOn, 0, 0);** //We sent Mode, Band and Bypass...
M5.delay(310); //Can't be real short, should be about equal or greater than NANO cycle time. NOTE that I've tried several values, but it doesn't seem to make a difference!!
Mode = ReceiveMode();
Serial.print(F("Startup Comms ReceiveMode = ")); Serial.println(ModeToString(Mode));
} while ((Mode == 0) && (Count < 100));
M5Stack Comms routine:
// Sent To NANO
bool Send5CheckSum(byte Mode, int Band, bool Bypass) {
// We send the Mode, Band and Bypass variables to the Nano.
// Return true = Failed.
unsigned long Tmr = millis();
String StringToSend = "";
//MODE, 2 digits ONLY. (Length=2)
// To get the "+" String concatonate to work, you need to start out with the []= StringToSend + Mode;]
//NANO NOTE: NANO does not support Modes > ModeOverTemp (12). NANO just forces itself to ModeReceive when greater than 12.
if (Mode < 10) StringToSend = StringToSend + "0" + Mode;
else StringToSend = StringToSend + Mode;
//Serial.print(F("Sending Mode = ")); Serial.println(ModeToString(Mode));
//Band, 2 digits only (Length=4)
if (Band < 10) StringToSend = StringToSend + "0" + Band;
else StringToSend = StringToSend + Band;
//Bypass, 1 Digit Only, 0 or 1, 1 Digit. (Length=5)
StringToSend = StringToSend + Bypass;
//Sum the Mode + Band + Byp
int Sum = Mode + Band + int(Bypass);
// 2 digits:
if (Sum < 10) StringToSend = StringToSend + "0" + Sum;
else StringToSend = StringToSend + Sum;
//Add a termination Carriage Return. (Adds 1 more char.)
StringToSend = StringToSend + "\n";
if (StringToSend.length() != 8) { //I'm NOT Seeing this error!!!
Serial.print("StringLength does NOT equal 8 (with CR & CheckSum): "); Serial.print(StringToSend);
Serial.print(" String.Length: "); Serial.print(StringToSend.length());
Serial.print(" Mode(2): "); Serial.print(Mode);
Serial.print(" Band(2): "); Serial.print(Band);
Serial.print(" Bypass(1): "); Serial.print(Bypass);
Serial.print(" Sum(2): "); Serial.println(Sum);
return true; //Programming Error!
}
***//NOTE: If I execute the following LINES, it works!!!!!***
// unsigned long Tmr = millis();
// //Serial.print(F("WHY DOES IT WORK WHEN I PRINT THIS???"));
// Serial.print(F("String: '")); Serial.print(StringToSend);
// Serial.print("' Mode: "); Serial.print(ModeToString(Mode));
// Serial.print(" Band: "); Serial.print(Band);
// Serial.print(" Bypass: "); Serial.print(Bypass);
// Serial.print(" Sum: "); Serial.print(Sum);
// Serial.println();
// Serial.print(F(" Time = ")); Serial.println(millis() - Tmr);
//Send the string through the Comm Port.
for (unsigned int i = 0; i < StringToSend.length(); i++) {
NanoPort.write(StringToSend[i]); // Push each char 1 by 1 on each loop pass
Serial.print(StringToSend[i]);
}
return 0;
}
The NANO Receive code is:
bool Receive5CheckSum(byte &Mode, int &Band, bool &Act1_Byp0) {
//returns true for failed comms, false for successful.
Serial.println("ST....");
String RcvString = "";
char inChar;
int Sum = 0;
while (M5Port.available()) {
inChar = (char)M5Port.read(); // get the new byte:
//delay(1);
if (inChar == '\n') { // ignore carriage return, we don't add it to the string
Serial.println(F("CR"));
break; //Break out of the while loop
}
RcvString += inChar; // add it to the inputString:
Serial.print(RcvString);
}
if (RcvString.length() != 7) {
if (RcvString.length() > 0) {
Serial.print(F("From M5, RcvString Length NOT 7: ")); Serial.print(RcvString); Serial.print(F(" RcvString Length: ")); Serial.println(RcvString.length());
}
Serial.print(F(" Rcved Short: Time = ")); Serial.println(millis() - Tmrr);
return true;
}
Serial.print(RcvString); Serial.print(F(" RcvString Length: ")); Serial.println(RcvString.length());
//Mode, 2 Digits
String tmp = RcvString.substring(0, 2);
Mode = tmp.toInt();
//Band, 2 Digits
tmp = RcvString.substring(2, 4);
Band = tmp.toInt();
//Act1_Byp0, 1 Digit
tmp = RcvString.substring(4, 5);
Act1_Byp0 = tmp.toInt();
//CheckSum 2 Digits
tmp = RcvString.substring(5, 7);
Sum = tmp.toInt();
//Make sure the Sum is correct
if ((Mode + Band + Act1_Byp0) == Sum) {
//Serial.print(F("Sum OK Mode=")); Serial.print(Mode); Serial.print(F(" Band=")); Serial.print(Band); Serial.print(F(" Act1_Byp0=")); Serial.print(Act1_Byp0); Serial.print(F(" Sum=")); Serial.print(Sum); Serial.print(F(" RcvString = ")); Serial.println(RcvString);
Serial.print(F(" FAILED: Time = ")); Serial.println(millis() - Tmrr);
return false;
} else {
Serial.print(F("Sum Error Mode="));
Serial.print(Mode);
Serial.print(F(" Band="));
Serial.print(Band);
Serial.print(F(" Act1_Byp0="));
Serial.print(Act1_Byp0);
Serial.print(F(" Sum="));
Serial.println(Sum);
return true;
}
}
The Receive String Length should be 7!!!
What I'm getting is the first read shows 4 Characters and the next read shows 3 characters!.
My Debug Output shows: (2 cycles shown)
ST....
19:40:59.078 -> 0000000001CR
19:40:59.078 -> From M5, RcvString Length NOT 7: 0001 RcvString Length: 4
19:40:59.117 -> Rcved Short: Time = 7
19:40:59.117 -> ST....
19:40:59.117 -> 001010From M5, RcvString Length NOT 7: 010 RcvString Length: 3 //NO CR to break out of the loop!!!
19:40:59.117 -> Rcved Short: Time = 9
19:40:59.117 -> Return2 was true, Nothing read...
19:40:59.117 -> ExecuteTime is: 20
19:40:59.278 -> ST....
19:40:59.278 -> 0000000001CR
19:40:59.278 -> From M5, RcvString Length NOT 7: 0001 RcvString Length: 4
19:40:59.313 -> Rcved Short: Time = 7
19:40:59.313 -> ST....
19:40:59.313 -> 001010From M5, RcvString Length NOT 7: 010 RcvString Length: 3
Like I mentioned, these routines work correctly. I use them when I start and run the system (M5Stack turns on a RELAY which sends Power to the NANO, and uses these exact same routines to establish Comms. It's ONLY when I disconnect the cable to get the Error, and re-connect (Power is cycled to the NANO) and it fails as you see above.
I'm stumped!
Suggestions?
Sir Michael