Detecting Corrupted Serial Communication

I have an esp board serially connected to a modem and I notice that it can return nonsense characters. When this happens the modem will only return nonsense characters until I reboot the modem. It is rebooted by pulling an esp GPIO to ground which is connected to the modem's powerkey. So my question is there a way to verify that a serial connection is good quality? I observe this problem most frequently when the microcontroller are in an electrically noisy environment..

Only if your communications is individual packages/distinct messages. If so, you can add check characters to the end of the message. Then you have to implement error correction to the communication protocol.
Easiest may be to protect the controller from the interference.

1 Like

Change port settings from 8N1 to 7 bit Parity 2 stop. Adding parity for pure ASCII helps.

1 Like

Better shielding for wiring and board is strongly advised for that case, and may actually solve the problem.

1 Like

I am thinking a grounded metal box would work better, so this is a good idea. Right now I am just using a 3d printed box.

I think I have found a way to run a check on a test package if I send AT to the modem I should receive the command echoed and then OK unless the connection is bad quality.

So with the following code I am receiving this on the serial monitor: "AT\r\r\nOK\r\n"

   Serial2.print("AT\r\n");
   char feedback0;
   char corruptioncheck[20];
   int arrayIndexer = 0;
   elapsedMillis basicti0;
    while ((feedback0 != '\n') && (basicti0 <= 300)){
    while(Serial2.available() && feedback0 != '\n'){
        feedback0 = Serial2.read();
        if (feedback0 == '\r'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'r';
        }      
        else if (feedback0 == '\n'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'n';
        }
        else if (feedback0 != '\n'){
          corruptioncheck[arrayIndexer++] = feedback0;
        }
    }
   }
   feedback0 = '\\'; //placeholder
    while ((feedback0 != '\n') && (basicti0 <= 300)){
    while(Serial2.available() && feedback0 != '\n'){
        feedback0 = Serial2.read();
        if (feedback0 == '\r'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'r';
        }      
        else if (feedback0 == '\n'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'n';
        }
        else if (feedback0 != '\n'){
          corruptioncheck[arrayIndexer++] = feedback0;
        }
    }
   }
   corruptioncheck[arrayIndexer++] = '\0';
   Serial.println(corruptioncheck);

Because I know what I should Ideally receive: AT\r\r\nOK\r\n I wanted to try

if (corruptioncheck == "AT\r\r\nOK\r\n"){
//execute reboot sequence
}

But I cannot compile this... How can I rewrite this last portion to check for the expected value of
AT\r\r\nOK\r\n

Most people use a checksum or CRC calculation to test for message corruption.

They are simple to implement and the more bits in the checksum or CRC result, the less likelihood of a false positive.

One of many resources: Cyclic redundancy check - Wikipedia

I may implement a more forward thinking approach down the road such as this. But to solve my simple problem I am using the code below which seems to work. Although people will laugh at my use of strings haha

   //verifying serial communication isn't corrupted*****************************
   Serial2.print("AT\r\n");
   char feedback0;
   char corruptioncheck[20];
   int arrayIndexer = 0;
   elapsedMillis basicti0;
    while ((feedback0 != '\n') && (basicti0 <= 300)){
    while(Serial2.available() && feedback0 != '\n'){
        feedback0 = Serial2.read();
        if (feedback0 == '\r'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'r';
        }      
        else if (feedback0 == '\n'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'n';
        }
        else if (feedback0 != '\n'){
          corruptioncheck[arrayIndexer++] = feedback0;
        }
    }
   }
   feedback0 = '\\'; //placeholder
    while ((feedback0 != '\n') && (basicti0 <= 300)){
    while(Serial2.available() && feedback0 != '\n'){
        feedback0 = Serial2.read();
        if (feedback0 == '\r'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'r';
        }      
        else if (feedback0 == '\n'){
          corruptioncheck[arrayIndexer++] = '\\';
          corruptioncheck[arrayIndexer++] = 'n';
        }
        else if (feedback0 != '\n'){
          corruptioncheck[arrayIndexer++] = feedback0;
        }
    }
   }
   corruptioncheck[arrayIndexer++] = '\0';
   String corruptionchecks = String(corruptioncheck);
   if (corruptionchecks == "AT\\r\\r\\nOK\\r\\n"){
    //do nothing
   }
   else{
    modemreboot(); //reboot due to corruption
    corruptmodemreboots++;
   }
   //end of corruption verification**********************************************

If that fixes the problem, great!

if you are sending data over doubtful communication system create a frame with a sequence number data and CRC, e.g. simple example
seq(byte) length(byte) data[length] (bytes) CRC(byte or short)
the CRC checks for errors in the frame and seq checks for lost or duplicate frames
if a frame is lost you can request a resent
this is frame I have used over BLE transparent UART (with DLEs being byte stuffed)
SYN DLE STX byte stuffed data CRC DLE ETX

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