4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シリアル通信パケット用のCOBSエンコーダーを作ってみる

Last updated at Posted at 2021-07-10

SS 192.png COBSがふにおちたい

やること

シリアル通信でそれなりの量のデータを短時間に送ろうとしたとき、テキストではなくバイナリで流した方が軽量快速です。
しかしArduinoの Serial.write() はバイナリデータをダーっと流すだけなので、受信側でデータの区切りを判断させるところに一工夫が必要です。
(パケットサイズが大きくてもよい場合には、改行記号で簡単に区切り判別をさせることもできます。1/1000秒単位で少し長めのデータをやりとりしたいときなどにはやはりバイナリ送信が助かります。)

COBS(Consistent Overhead Byte Stuffing)は1パケットのデータの中に0x00が1度しか出現しないようにするデータ変換方法です。
これを手元で(自分でもわかるように)実装してみます。
今回はエンコーダーを作ります。

参考

こちらの記事を参考にさせていただきました。とても勉強になりました。ありがとうございました。

使うもの

  • Arduino
  • Arduino IDE など

COBSの原理

まずデータを1バイトずつ配列に格納していきます。
その際、配列の冒頭に1バイトを追加し、次に0x00が現れるまでのデータの個数をカウントして代入します。次に0x00が現れた配列番号のデータには、その次の0x00が現れるまでのカウントを代入します。これを繰り返していくことで、データに現れる0x00を全て1以上の数値に置き換えることができます。データの最後だけを0x00とし、スタートビット/ストップビットとして利用していくという仕組みです。
たとえばデータ中に一度も0x00が現れないパケットの場合、冒頭のカウンタはデータの最後尾の配列番号を示すことになります。
元のデータの前後に1バイトずつ、合計2バイトしか増えないすぐれた方式です。

実装

流し込みたいシリアルデータを準備します。
ここでは、wikipediaのデータ事例が成立するかどうかを見ていきます。

なるべく規模が小さくなるように作っています。1パケットあたりのシリアルデータの長さは254バイトが上限となります。

Arduino
//1バイト型で作っているため、データ配列の最大長は254(カウントできる最大値)
uint8_t source_data[] = {11, 22, 00, 33}; //送信したいデータの配列。書き換えて動作テスト。
uint8_t cobs[sizeof(source_data) + 2]; // COBSに変換した送信データの配列(上記に2バイト追加)

void setup() {
  Serial.begin(115200);//シリアルモニター表示
  delay(500);
}

void loop() {
  //配列を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[mark] = count; //前回00が出た配列にカウント値を改めて書き込む
  cobs[sizeof(source_data) + 1] = 0; //終端に00を代入する

  //変換した結果を表示
  for (int i = 0 ; i < sizeof(source_data) + 2; i++)
  {
    Serial.print(cobs[i]); Serial.print(",");
  }
  Serial.println();
  delay(1000);
}

動作確認

source_data[]の中の配列データを、Wikipediaの事例のように変更してみてください。
意図通りの結果が出力されると思います。

まちがっていたら

すみません!

つぎやること

COBSのデコーダーをつくります。

次回記事:

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?