시리얼 통신 패킷용 COBS 디코더도 만들어 보자

COBS가 두근두근하고 싶다 그 2

할 일



마지막 기사 "시리얼 통신 패킷용 COBS 인코더를 만들어 보자"의 계속입니다.
디코더를 만듭니다.

마지막 기사:

참고



전회와 같이, 이쪽의 기사를 참고로 했습니다. 고마워요.

사용하는 것


  • Arduino
  • Arduino IDE 등

  • 구현



    COBS 디코더를 만듭니다.
    아래 스크립트에서
    · 원래 데이터 표시
    · 인코딩된 데이터 표시
    · 그것을 디코딩하기 위해 자른 데이터를 표시합니다.
    ・위에 0x00을 넣어 원래의 데이터를 복원한 디코드 결과를 표시
    라는 순서로 작업하고 있습니다.

    Arduino
    //1バイト型で作っているため、データ配列の最大長は254
    
    //↓送信したいデータの配列。データを書き換えてテストできます。(uint8_t型の値のみ)
    uint8_t source_data[] = {00, 00, 185, 00, 33, 00, 44, 00, 00, 55, 00, 00, 200, 222, 130, 566, 60, 00}; //適当な数字
    
    uint8_t cobs[sizeof(source_data) + 2]; // COBSに変換した送信データの配列(上記に2バイト追加)
    uint8_t received_data[sizeof(source_data)]; //受信後にデコードしたデータを入れる配列。
    
    void setup() {
      Serial.begin(115200);//シリアルモニター表示
      delay(500);
    }
    
    void loop() {
    
      // **** 元のデータの表示 ****
      Serial.print("Source Data   :   ");
      for (int i = 0 ; i < sizeof(source_data) ; i++)
      {
        Serial.print(source_data[i]);
        Serial.print(",");
      }
      Serial.println();
    
      // **** 配列をCOBSの方式で処理する エンコーダー ****
    
      uint8_t count = 0; //次にsource_data[i]に0x00が出るまでの配列番号をカウント
      int mark = 0; //最後に0x00が出たsource_data[i]の配列番号をキープ
    
      for (int i = 0 ; i < sizeof(source_data) + 1; i++) {
    
        //現在チェックしているsource_data[i]の中身が0x00ではない場合
        if (source_data[i] != 0x00) {
          cobs[i + 1] = source_data[i]; //チェックした値をそのままcobs配列に書き込む
          count ++;//前回0x00が出たsource_data[i]の配列内のカウント値を+1
        }
    
        //現在チェックしているsource_data[i]の中身が0x00だった場合
        else {
          count ++;//前回0x00が出た配列のカウントを+1
          cobs[mark] = count;//前回0x00が出たcobs配列にカウント値を書き込み確定
          mark = i + 1; // 現在のcobs配列を0x00が出た配列としてキープ
          count = 0 ;//0x00が出た配列のカウントをリセット
          cobs[mark] = count; //今回0x00が出たcobs配列にカウント値を書き込む
        }
      }
    
      //COBSの末端処理
      cobs[mark] = count; //前回0x00が出た配列にカウント値を改めて書き込む
      cobs[sizeof(source_data) + 1] = 0; //終端に0x00を代入する
    
      //エンコーダーで変換した結果を表示
      Serial.print("Encorded Data : ");
      for (int i = 0 ; i < sizeof(source_data) + 2; i++){
        Serial.print(cobs[i]); Serial.print(",");
      }
      Serial.println();
    
      // ** COBSから元のデータを復元するデコーダー **
    
      //先頭と末尾をトリムしたデータを作成する(0x00はまだ代入していない)
      for (int i = 0; i < sizeof(received_data); i++) { //全パケットをデコード結果用の配列に取り込む(先頭と末尾を除く)
        received_data[i] = cobs[i + 1];
      }
    
      //先頭と末尾をトリムしたデータの表示
      Serial.print("Trimmed Data  :   ");
      for (int i = 0 ; i < sizeof(received_data); i++) {
        Serial.print(received_data[i]); Serial.print(",");
      }
      Serial.println();
    
      //該当する場所に0x00を代入する処理
      int i = 0;
      while ( i <= sizeof(received_data)) {
        i = i + cobs[i];
        received_data[i - 1] = 0;
      }
    
      //0x00を代入したデコード結果の表示
      Serial.print("Decorded Data :   ");
      for (int i = 0; i < sizeof(received_data); i++) {
        Serial.print(received_data[i]); Serial.print(",");
      }
      Serial.println(); Serial.println();
      delay(1000);
    }
    

    동작 확인



    기본적으로 시리얼 모니터에 다음과 같은 결과를 출력합니다.



    Source Data : 첫 번째 데이터
    Encorded Data: COBS로 인코딩된 데이터
    Trimmed Data : 디코딩을 위해 COBS의 시작과 끝을 자른 데이터
    Decorded Data: 0x00을 대입하여 원래 데이터를 재현한 것

    source_data[]의 배열 데이터를 다시 쓰거나 요소 수를 늘려 동작을 확인할 수 있습니다.

    틀리면



    죄송합니다!

    다음 일



    공용체를 사용하여 2바이트 데이터를 저장하고 전송할 수 있습니다.

    마지막 기사:

    좋은 웹페이지 즐겨찾기