91211
私は大学の研究のためにここ５日ほど，ラズパイのPythonの数値（小数点）をArduinoにどうにか伝えようと(SPI or
I2C)色んなサイトを奔走しています．(そのため私の過去質問は似たような内容で埋め尽くされています．

あるいは以下のサイトでも  
<https://forum.arduino.cc/t/what-numbers-are-they-ieee-754-arduino-
float/1033366/5>

しかしながら結果は芳しくありません．（以下に試してきたことを書いておきます）  
もちろん，あらゆるサイトを見てきましたが，まともな例が一つもありませんでした．（海外サイトを含めて）  
そこで抽象的な質問になってしまい，申し訳ないのですが，「皆さんはラズパイが計算した値をarduinoに伝えたい，という場面に遭遇した時にどうしていますか？」  
もし普段使っているコードがあればそのまま教えていただきたいですし，あるいはそれを実現しているサイトをご存知のようであれば教えていただきたいです．

これは何も，すべてを皆様に全投しているわけではなく，五日間という日を投資して足掻いた結果が芳しくなく，そもそもの考えの枠組みから見直すために質問させていただいているということです．

### 試したこと

数を1byte単位で送り，Arduinoの中でIEEE754に変換する方法はうまくいきましたが，基点となる信号を送れないため（Arduinoにとっては全てが等しく数字のため），Arduino側でbyteをカウントする必要があるために，一度読み間違えたらドミノ倒しになります．(SPI,
I2C)  
これはstrに変換して送る方法でも言えます．(I2C)  
結局スレーブにする時点で，「byteが来るたびに格納」する必要があり，そのbyteの受け取りミスを防ぐ方法が全てにおいて必要なのです．が，そのようなサイトを見つけることができませんでした．

過去質問はこちら  
[ラズパイ to Arduino:
SPI送受信のタイミングが合わずに乱れる](https://ja.stackoverflow.com/q/91206/41334)

usbシリアルはサイトを見かけましたが，肝心のマシン（arduinoに渡った数値はモーター指令速度になります）が動かず，デバグしようにもusbポートを物理的に塞いでいるので，この案は棄却されました
CC BY-SA 4.0
2022-09-21T05:53:55.113
91207
2022-09-22T01:02:35.793
2022-09-21T06:22:45.633
3060
41334
question
python c++ c raspberry-pi arduino
ラズパイのPythonの数値（小数点）をArduinoにどうにか伝えたい(SPI or I2C)
区切りを電文内でつけなければならない場合、

  * 文字列で送る

非常に単純です。`123.4`という数値を送りたいなら`"123.4"`という文字列を送ります。  
メッセージの区切りは制御文字を使います。大抵改行です。  
複数の種類の値を扱う場合はコマンド文字列を先頭に付け加えたりします。  
マイコン側で文字列をパースする必要があるのが難点ですが、  
Arduinoなら特に問題にはならないでしょう。  
特に理由がなければ文字列で送ります。

  * バイナリで送る

文字列で送ると通信速度の問題がある場合は仕方なくこちらを選びます。  
メッセージの区切りを認識するために送るデータのチェックサムなどを含めたヘッダーを作り、  
マイコン側で区切れを探索します。

* * *

上は電文の中で電文の区切りを持たせる場合ですが、今回の場合そもそもSPIですので  
CS信号を区切りに使うことができます。

Raspi側はCSを下げたままにしてデータ、例えば"123.4"を送信し(xfer2でまとめて送るとそうなる、または明示的にCSを操作する)  
Arduino側ではCSを監視してL->Hになった時点でデータ転送が終了したと判断します。
CC BY-SA 4.0
2022-09-21T06:26:55.730
91210
2022-09-21T23:54:39.197
2022-09-21T23:54:39.197
13127
13127
91207
answer
そういうのは「電文」の設計ということになります。電文とは何らかの方法で最初と最後とチェックデジットがわかるもの、ということになりそうです。よくある
RS232 で計測器→ PC に測定値を知らせるような場合

`[STX]` ASCII 文字だけ使った電文 `[ETX]` チェックデジット

のようにしておくと開始を知るには `[STX]=0x02` が見つかるまで読み捨てればよくて、そののち `[ETX]=0x03`
があるまで受け取ればいいわけです。更にチェック方法に従ってチェックデジットを自分で計算し、自分の計算結果と受け取った値が異なっていれば破棄するなどを行います（ノイズが混入しうる距離の伝送が前提なので）

この手続きだと本文に `STX`/`ETX` と同じ値を含むことができないので情報密度が上げられません。それが許容される場合にしか使われません。

SPI の場合 `#CS=H→L` で電文開始 `#CS=L` が継続している間が電文本文 `#CS=L→H`
で電文終了、外来ノイズから隔離されている同一基板内の通信しか想定していないのでチェックデジットは無し、ということで十分です。

I2C でも `[スタートコンディション]` 電文 `[ストップコンディション]` となり、同様チェックデジットはなし、が基本です。

なので SPI や I2C
ではどこで電文が開始終了するかはほぼ自明であり、わざわざ解説記事に詳細を記載するまでもないのです（当たり前すぎて解説不要だから記事を見つけられていないだけ）

今回 SPI で伝送することを選ぶなら SPI バス上 32bit Transaction が可能なのに対して、今 Payload として 8bit
しか載せていないようなので 24bit 分無駄な転送をしている可能性があります。 SPI の空き部分に `コマンド` あるいは `データ種別` として
`データX の bit0-15` のように区別できる何かを載せるといいでしょう。

* * *

RaspberryPI の `spi.xfer2` はバイトの列を１つのトランザクションで送る仕様なので、１回の `spi.xfer` の呼び出しによって

  * `#CS=H→L` にする
  * 指定したバイト列をその順に送信する
  * `#CS=L→H` にする

という挙動をします。伝送したいデータが１種類しかないならバイト列として本文だけ用意すれば十分で、複数種類あればそれを判別する別バイトを用意すればよいわけです。

  * 前者なら `spi.xfer2([0x40,0x49,0x0F,0xD8])` (32bit Transaction)
  * 後者なら `spi.xfer2([種類,0x40,0x49,0x0F,0xD8])` (40bit Transaction)

種類の値は送る側と受ける側で合意した任意の値

Arduino の受信側は全然知らないので SPI の受信ロジックが `#CS` を受け付けるのか否か、何ビットの伝送ができるのかを確かめてください。
`#CS` を受け付けるのであれば電文の開始終了は `#CS` で判断できるので小細工は不要。 40bit Transaction ができないのなら
32bit 以下 Transaction にしなきゃならないので、データを分割する必要が生じます。 16bit
値と電文の種類（何のどこ）も受け渡す、なんてことになります。

see also; [RaspberryPi CM4
にて、Pythonを使用し、SPI通信で外部のEEPROMにアクセスしますが、値の読み書きができません。](https://ja.stackoverflow.com/questions/90231/)
CC BY-SA 4.0
2022-09-21T06:37:10.457
91211
2022-09-22T01:02:35.793
2022-09-22T01:02:35.793
8589
8589
91207
answer
> そのどちらにせよ，Arduinoはバイトに分かれたものを順番正しく保持し，揃ったら結合，  
>  をしなければなりません。  
>  これの方法がどこにも載っておらず困っています．どのサイトもArduinoがます他，  
>  あるいはスレーブだけど１byte受け取るだけ，で参考になりません。

これはRS232C等でも同様ですが、一般的にデータの頭にSTX、データの最後にETX等をつけ、  
さらにデータの整合性をチェックするために、STXの後に送るデータ数をつけ、ETXの前にCRCコードをつけることにより、受信して結合したデータに欠落がないかチェックします。  
データが1つ欠落していた場合、STXの後のデータ数と実際のデータ数が異なりますし、CRCの値も違ってきます。  
当然ですが、データ自身はは文字に変換して送ります。

別の方法としては、1バイトデータのうち、下の4ビットのみをデータ用とし、  
上位の4ビットはなんバイト目、これで終わり等意味で使用する方法があると思います。
CC BY-SA 4.0
2022-09-22T00:44:57.200
91223
2022-09-22T00:51:04.750
2022-09-22T00:51:04.750
24490
24490
91207
answer