Imaginary Code

from kougaku-navi.net

Arduinoのシリアル通信でコンマ区切りのデータを受信・分解する

シリアルで送られてきた「100, 200, 300, 400, 500」みたいなコンマ区切りの数値列をint型の配列データに分解するコード例です。Processingでいうところのsplit()関数があると便利なんですが、ないみたいなので、みんな各々作ってるみたいですね。

void setup() {
  Serial.begin(9600);
}

void loop() {
  if ( Serial.available() ) {
    String str = Serial.readStringUntil('\n');
    Serial.println(str);

    int data[5];
    stringToIntValues( str, data, ',' );

    Serial.println("---------");
    for (int i = 0; i < 5; i++) {
      Serial.print("data[");
      Serial.print(i);
      Serial.print("]=");
      Serial.println(data[i]);
    }
  }
}

// String型のカンマ区切り文字列をint型配列に分解する関数
void stringToIntValues(String str, int value[], char delim) {
  int k = 0;
  int j = 0;
  char text[8];

  for (int i = 0; i <= str.length(); i++) {
    char c = str.charAt(i);
    if ( c == delim || i == str.length() ) {
      text[k] = '\0';
      value[j] = atoi(text);
      j++;
      k = 0;
    } else {
      text[k] = c;
      k++;
    }
  }
}

上記のコードでは受信データを入れる配列が int data[5] と5個のデータしかこない想定になっていますが、送り手がミスって5個以上のデータを送ってしまったり、受信バッファがバグって5個以上の数値が連なったデータを読んでしまう事故は起こりえます。そうなると配列の境界外のインデックスを参照してしまい、エラーでプログラムが停止します。最も単純な対策はdataのサイズを少し大きめにしておくことですが、ちゃんとやりたければ stringToIntValues() の中に配列の要素数を越えて読まない処理を組むのがいいかも。