1

I currently have a setup where I take serial output from Arduino 1 and push it through a transmitter to the receiver of Arduino 2 where it is fed back into the serial input and further processed. I want to ensure that there is as little error as possible and recover the data wherever possible.

I have come across the syndrome decoding technique which seems to be the ideal one for me, but I am confused as to how I would go about implementing it.

I know that the Arduino Serial transfers data byte by byte, each being 8 bits, but do not know how this data is sent over the serial connection (i.e. how the start & stop bits & parity is implemented).

I would assume that a solution to this could either involve modifying the data in the buffer or reading it from the buffer and then operating upon it. I could also use adjacent bytes of data for error correction, but this seems wasteful.

How should I proceed with this?

1
  • Which "syndrome decoding technique" are you considering? It will probably affect the approach. – slash-dev Dec 9 '15 at 1:10
2

Welcome to the wide world of Communications. You are asking about "Error Detection and Correction". This is different from "framing", which allows you to determine when a message starts and ends.

With "error detection", you know there was an error, but you can't necessarily recover from it. With "correction", you know there was an error and you can determine what was originally sent.

This always requires extra bytes. There are many schemes, but the Fletcher checksum for Error Detection is easy to implement, fast, and only requires 2 extra bytes in the message (4 if hex digits).

The generic approach is to use a finite-state machine. In complicated message protocols, there would be nested state machines: the inner-most would probably determine framing, the next one out might looks at addressing, etc. Any or all of those layers could use Error Detection and/or Correction.

For your simple "protocol", a single state machine is probably sufficient. The states might be IDLE, RX_PAYLOAD and RX_CS. As characters are received, they are processed according to the current state and occasionally change the state variable.

while (Serial.available()) {
  uint8_t c = Serial.read();
  switch (state) {
    case IDLE:
      if (c == MSG_START)
        state = RX_PAYLOAD;
      break;
    case RX_PAYLOAD:
      if (c == MSG_END) {
        state = RX_CS;
        cs = 0;
        csCount = 0;
      } else if (length < MAX_LENGTH-1) {
        msg[ length++ ] = c;
      }
      break;
    case RX_CS:
      //  Add in the next hex CS digit
      cs = cs * 16 + fromHex(c);
      if (++csCount == 2) {
        // both digits received, see if the CS matches
        if (cs == csOfMsg( msg, length )) {
          // Handle the message
          msg[ length ] = '\0';
          Serial.println( msg );
        } else {
          Serial.println( F("Bad message!") );
        }
        state = IDLE;
      }
      break;
  } // end switch
} // end while

There are entire books written on protocols and their design. This is just a made-up example to give you an idea of how it should be structured: a finite state machine, driven by received character "events".

Sometimes you can compute the checksum as the characters are received, like Fletcher. Here, it waits until the entire message plus 2 CS bytes are received.

0

In my case i used a buffer and a delimiter. Specificaly: The reading is placed on the byte array untill the delimiter is reached.

For example

From the arduino IDE serial monitor im sending this: CAT;

Each letter will be placed inside the byte array and this will stop when the ; sign is entered. This migh be usefull because you can send the bytes whenever you can and they will remain in the array.

void loop(){
if(Serial.available() > 0) {
 
 char rec = Serial.read();

 if(rec == '.'){
    Serial.print("Here: ");
    for(int i = 0; i < sizeof(attitude); i++){
       Serial.print(attitude[i]); //print
       attitude[i] = (char)0;
    }
    attitudePointer = 0;
    Serial.println();
    
 }else{
   if(attitudePointer <= sizeof(attitude)){
      attitude[attitudePointer] = rec;
      attitudePointer++;
    }
  }

 }
}
1
  • That code doesn't match your description! That code waits for a period (full stop), not a semicolon. And it's a little misleading to use attitudePointer, when it is actually an index, not a pointer. – slash-dev Dec 9 '15 at 1:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.