91146


現在私はPython
(ラズパイ）で計算した数値をC言語(Arduino)にfloatとして送信することを目標としています．なぜそうしたいかというとある深層学習中のモデルからの指令値をArduinoに渡してモーター速度を制御したいためです．リアルタイムでの学習ですのでRaspiにはそのことに集中してもらいたいです．  
I2CのRaspi ->
Arduino(float)についてネットで，英語/日本語どちらもの検索をしましたが，解決策を統一的に載せている方がいなかったので，改めましてステップバイステップでみなさんの意見を伺いたく質問させていただきます．

私が考えるに，以下のようなステップがあり，そしてそのステップの実現方法がわからないため，教えてくださいませ．

  1. Pythonで送信したい数字(speedと名づけます）を，Cが読める型に変更します．
  2. おそらくそれは4byteなので，Pythonはそれを区切って送信します
  3. Cは受け取った4byteを繋げてfloatとしてspeedを復元します

各ステップについて，やり方あるいはライブラリを知っていれば是非教えて下さい．よろしくお願いします


CC BY-SA 4.0
2022-09-17T00:07:08.243
91138
2022-09-19T02:06:54.967
2022-09-17T11:38:36.870
3060
41334
question
python c raspberry-pi arduino
Python (ラズパイ）で計算した数値をC言語(Arduino)にfloatとして送信したいです


以下の理由で、質問に提示した方法そのままでの通信はやめておいた方が良いでしょう。

I2Cを含むシリアル通信は1バイト単位で行われるもので、通信に関わるAPI・デバイスドライバ・ハードウェア等のすべてがその時点で送受信対象の各バイトがどのような属性のデータ(構造の一部)であるかの情報を持っていません。

つまり浮動小数点数のようにそれぞれのバイトが0x00から0xFFまでのどんな値でも取り得る、複数のバイトで構成されるデータがあった時に、その先頭・最後・途中の順番を表すものは何もないわけです。

浮動小数点数のデータだけを通信している場合、そのほとんどは問題無く通信出来るとは思われますが、何かの事象があって順番がズレた場合に、そのズレを検出したり修正する方法はほぼありません。  
強いて言えば各バイト間の時間間隔を計測して指定以上の時間が経過したらそこで区切ると言ったものですが、かえって重い処理になったりタイミングや処理性能にシビアになったりします。

参考：  
[Raspberry PiでI2C通信をする](https://www.raspberrypirulo.net/entry/raspberrypi-i2c)  
[Arduino初心者編：I2C通信によるArduino間のデータ送受信](https://stemship.com/arduino-
beginner-i2c/)  
[ラズパイ（Raspberry Pi）とArduinoをI2Cで接続【基本編】
ラズパイからPythonのSMBusモジュールを使ってArduinoにデータを送信しよう](https://deviceplus.jp/raspberrypi/raspberry-
pi-and-arduino-connect-with-i2c-01/)

* * *

ではどのようにすれば良いかと言うと、以下のように考えましょう。

  * 1件のデータの開始を示すデータを定義する  
例えばモーター制御用に`M`あるいは速度なら`S`とするなど

  * 浮動小数点データは文字列に変換する

    * 単純に`str()`関数で処理すれば、可変長にはなりますが特別な処理は不要だし、何かプログラム上(別の処理でも)の不具合があった時に確認するのが簡単になります。
    * 浮動小数点データを4バイトの配列に見立てて16進数文字列に変換する方法もあります。8文字の固定長なのでバッファに関する扱いは簡単になるでしょう。
  * 1件のデータの終了を示すデータを定義する  
単純に改行コードの0x0D(`'\r'`)だけでも良いし、更に1件分のデータのチェックサム等を付けても良いでしょう。

[浮動小数点数内部表現シミュレーター](https://tools.m-bsys.com/calculators/ieee754.php)

* * *

送信側(Raspberry Pi, Python)では上記を連結して1件のデータとし、1バイトづつ送信していけば良いでしょう。

浮動小数点データを16進数文字列に変換する方法には、以下のような記事が使えるでしょう。  
[Pythonで浮動小数点数floatと16進数表現の文字列を相互に変換](https://note.nkmk.me/python-float-hex/)  
[How to convert a float into
hex](https://stackoverflow.com/q/23624212/9014308)  
[Python program to represent floating number as hexadecimal by IEEE 754
standard](https://www.geeksforgeeks.org/python-program-to-represent-floating-
number-as-hexadecimal-by-ieee-754-standard/)

* * *

受信側(Arduino, C)では受信したデータを判定しつつバッファに格納し、1件分のデータが揃ったら浮動小数点数に変換すれば良いでしょう。

可変長の文字列であれば[String.toFloat()](https://garretlab.web.fc2.com/arduino_reference/language/variables/data_types/String/functions/toFloat.html)とかの標準的な関数が使えるでしょう。  
16進数文字列なら、バイトの配列に変換してからそのアドレスを使って(float *)とかで浮動小数点扱いに出来るのでは？  
[Convert IEEE 754 32 to float](https://forum.arduino.cc/t/convert-
ieee-754-32-to-float/323109)


CC BY-SA 4.0
2022-09-17T13:26:11.033
91146
2022-09-17T13:26:11.033
26370
91138
answer


floatで送信する、ってのは筋が悪いです。

ラズパイ側からは生データのバイナリデータを送信し、それをarduino側でfloatに変換するようにしましょう。  
そもそもシリアル通信する時間に比べれば、float変換する時間は誤差程度しかないですよ


CC BY-SA 4.0
2022-09-17T22:38:40.467
91148
2022-09-17T22:38:40.467
27481
91138
answer


ラズパイとArduinoの通信はシリアル通信での通信でしょうか？  
私の場合、シリアル通信で2つのボード間の通信を行う場合、テキストに変換して  
通信しています。  
テキストに変換した場合、ターミナルソフト等で別々にテスト、動作確認を  
行うことが容易になります。


CC BY-SA 4.0
2022-09-19T02:06:54.967
91166
2022-09-19T02:06:54.967
24490
91138
answer