ラズパイからArduinoに2byteシリアル通信する

[link-01]:https://www.amazon.co.jp/gp/product/B07BBPX8B8/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

#はじめに
[前回の記事](https://qiita.com/teraken_/items/c8ac4c0ff60d8856a15c)のデータを通信するために、[USB-シリアル変換ボード][link-01]を買ったので、ラズパイからArduinoに2byteシリアル通信する実験をしたメモ。

記述言語はpython。

ラズパイ側はUSBに[USB-シリアル変換ボード][link-01]を差し、Arduino nanoのTX、RXに接続する。**GNDをつながないと通信が安定しなかった**。

ラズパイ側からの値は16bit以下であることが、暗黙的な仕様になっている。

#jsonファイル

辞書形式で読み込んだ時に、データの順番がファイル通りになるようにjsonファイルを読み込んで、valuesに格納されたxy座標をシリアル通信でArduinoに送信する。

```json
{
    "0": [
        91,
        78
    ],
    "1": [
        119,
        169
    ],
    "2": [
        223,
        140
    ],
    "3": [
        174,
        115
    ],
    "4": [
        224,
        82
    ],
    "5": [
        283,
        160
    ],
    "6": [
        163,
        194
    ],
    "7": [
        53,
        168
    ]
}
```

#pythonプラグラム

##参考文献

以下の情報を参考にして、プログラムを作成した。

+ [Raspberry Pi3とArduino Unoのシリアル通信](https://qiita.com/yumatsud/items/03281b32d49dfe9e59fd)
+ [python--serial通信--arduino, 1byte, 2bytes, 複数データ](https://qiita.com/keitasumiya/items/25a707c37a73bfd95bac)
+ [cloverrose's blog](http://cloverrose.hateblo.jp/entry/2015/02/01/004810)


##ライブラリ

pyserial、jsonを使用する。

##プログラム

### ラズパイ

数字を文字列ではなく実データとして送信する必要がある。従って2byteデータを上位8bit、下位8bitに分割してbig endianで送信し、Arduino側で合成する。

|0|1|2|3|4|5|6|7|...|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|x[0]_upp|x[0]_low|y[0]_upp|y[0]_low|x[1]_upp|x[1]_low|y[1]_upp|y[1]_low|...|

```py:
import json
import serial
import collections

#通信設定
sdev = '/dev/ttyUSB0'
baud = 115200

def send2Byte(pt):
	j = 0
	with serial.Serial(sdev, baud, timeout=1) as ser:
		for i in pt.values():
			#print(i[0]) # x
			#print(i[1]) # y
			ix_upp = (i[0] & 0xff00) >> 8
			ix_low = (i[0] & 0x00ff)
			iy_upp = (i[1] & 0xff00) >> 8
			iy_low = (i[1] & 0x00ff)
			#print("x : ", ix_upp * 256 + ix_low,"=",  i[0])
			#print("y : ", iy_upp * 256 + iy_low,"=",  i[1])
			print("x[", j, "] : ", ix_upp * 256 + ix_low)
			print("y[", j, "] : ", iy_upp * 256 + iy_low)
			ser.write(ix_upp.to_bytes(1, 'big'))
			ser.write(ix_low.to_bytes(1, 'big'))
			ser.write(iy_upp.to_bytes(1, 'big'))
			ser.write(iy_low.to_bytes(1, 'big'))
			j += 1
		ser.close()

if __name__ == "__main__":

	decoder = json.JSONDecoder(object_pairs_hook=collections.OrderedDict)
	with open('test.json', 'r') as f:
		pt = decoder.decode(f.read())
	"""
	for i in pt.values():
		print(i)
	"""
	send2Byte(pt)
```

### Arduino

通信データの上限は100として、1byteづつ送られてくるデータを4byte周期で合成し、x、y配列に格納していく。

```c:
#define DNUM 100
int n = 0;
int m = 0;
int x[DNUM], y[DNUM];
int nmod = 0;

void setup(){
  pinMode(13,OUTPUT); //13番ピンを出力に設定。特に使っていない。
  Serial.begin(115200);//シリアル通信のレート
  int i;
  for(i = 0; i < DNUM; i++){
    x[i] = 0;
    y[i] = 0;
  }
}

void loop(){

  int inchar;      //入力状態の読み取りに使う
  inchar = Serial.read();  //シリアル通信で送信された値を読み取る

  if(inchar!=-1){
    nmod = n % 4;

    if(nmod == 0){
      Serial.println("== received ==");
    }
    
    switch(nmod){
      case 0:
        x[m] += (inchar << 8);
        break;
      case 1:
        x[m] += inchar;
        Serial.print("x[");
        Serial.print(m);
        Serial.print("]:");
        Serial.println(x[m]);
        break;
      case 2:
        y[m] += (inchar << 8);
        break;
      case 3:
        y[m] += inchar;
        Serial.print("y[");
        Serial.print(m);
        Serial.print("]:");
        Serial.println(y[m]);
        m++;
        break;
    }
    //Serial.print("n:");
    //Serial.println(n);
    n++;
  }
  else{
    n = 0;
    m = 0;
    int i;
    for(i = 0; i < DNUM; i++){
      x[i] = 0;
      y[i] = 0;
    }
  }
}
```
##実行結果

### ラズパイ側

```terminal:
x[ 0 ] :  91
y[ 0 ] :  78
x[ 1 ] :  119
y[ 1 ] :  169
x[ 2 ] :  223
y[ 2 ] :  140
x[ 3 ] :  174
y[ 3 ] :  115
x[ 4 ] :  224
y[ 4 ] :  82
x[ 5 ] :  283
y[ 5 ] :  160
x[ 6 ] :  163
y[ 6 ] :  194
x[ 7 ] :  53
y[ 7 ] :  168
```

### Arduino側

```terminal:
== received ==
x[0]:91
y[0]:78
== received ==
x[1]:119
y[1]:169
== received ==
x[2]:223
y[2]:140
== received ==
x[3]:174
y[3]:115
== received ==
x[4]:224
y[4]:82
== received ==
x[5]:283
y[5]:160
== received ==
x[6]:163
y[6]:194
== received ==
x[7]:53
y[7]:168
```

思ったようにできた。