5

Python から Arduino に float データを送信し、同じ値を取得する必要があります。最初にArduinoからfloatデータを送信することを考えました。データは連続する 4 バイトとして送信されます。これらの連続するバイトを収集し、Python 側 (システム側) で適切な形式に変換する方法を見つけようとしています。

Arduino コード:

void USART_transmitdouble(double* d)
{
    union Sharedblock
    {
        char part[4];
        double data;

    } my_block;
    my_block.data = *d;
    for(int i=0;i<4;++i)
    {
        USART_send(my_block.part[i]);
    }


}

int main()
{
    USART_init();
    double dble=5.5;
    while(1)
    {
       USART_transmitdouble(&dble);
    }
    return 0;
}

Python コード (システム エンド):

my_ser = serial.Serial('/dev/tty.usbmodemfa131',19200)

while 1:
    #a = raw_input('enter a value:')
    #my_ser.write(a)
    data = my_ser.read(4)
    f_data, = struct.unpack('<f',data)
    print f_data
    #time.sleep(0.5)

struct上記のコードに示すようにモジュールを使用すると、float 値を出力できます。

50% の確率で、データは正しく印刷されます。ただし、送信をいじっtime.sleep()たり、送信を停止して再起動したりすると、誤った値が出力されます。この場合、間違った 4 バイトのセットがアンパックされていると思います。ここで何ができるかについて何か考えはありますか?

Arduino との間で float データを送受信するために struct モジュールを使用する以外のアイデアはありますか?

4

3 に答える 3

0

この質問は検索エンジンで上位にランクされるため、実用的な解決策をまとめました。

警告: 完全な浮動小数点精度が必要な場合を除き、文字列に変換して送信します (sprintf または dtostrf を使用するか、Serial.print(value,NumberOfDecimalPlaces) (documentation)を使用します)。これは、次の解決策が a) 異なるエンディアンのマシンでは機能せず、b) 一部のバイトが制御文字として誤って解釈される可能性があるためです。

解決策: 浮動小数点数のポインターを取得し、それをバイト配列として Serial.write() に渡します。

例えば

/*
Code to test send_float function
Generates random numbers and sends them over serial

*/

void send_float (float arg)
{
  // get access to the float as a byte-array:
  byte * data = (byte *) &arg; 

  // write the data to the serial
  Serial.write (data, sizeof (arg));
  Serial.println();
}


void setup(){
  randomSeed(analogRead(0));  //Generate random number seed from unconnected pin
  Serial.begin(9600); //Begin Serial
}

void loop()
{
  int v1 = random(300); //Generate two random ints
  int v2 = random(300);
  float test = ((float) v1)/((float) v2);  // Then generate a random float

  Serial.print("m");  // Print test variable as string
  Serial.print(test,11);
  Serial.println();

  //print test variable as float
  Serial.print("d"); send_float(test);
  Serial.flush();
  //delay(1000);

}

次に、これを Python で受け取るために、ソリューションを使用し、検証のために 2 つの出力を比較する関数を追加しました。

# Module to compare the two numbers and identify and error between sending via float and ASCII
import serial
import struct
ser = serial.Serial('/dev/ttyUSB0', 9600) // Change this line to your port (this is for linux ('COM7' or similar for windows))
while True:
    if(ser.inWaiting() > 2):    
        command = ser.read(1) #read the first byte
        if (command == 'm'):
            vS = ser.readline()
            #
            ser.read(1)
            data = ser.read(4)
            ser.readline()
            vF, = struct.unpack('<f',data)
            vSf = float(vS)
            diff = vF-vSf
            if (diff < 0):
                diff = 0-diff
            if (diff < 1e-11):
                diff = 0

            print "Str:", vSf, " Fl: ", vF, " Dif:", diff 

参考文献: Python から arduino への浮動小数点数の送信、シリアル経由で浮動小数点数を送信する方法

于 2015-02-25T12:55:40.157 に答える
0

簡単に言えば、ソフトウェアとハ​​ードウェアの間で何らかの相互作用が行われているということです。送信を停止する方法がわかりません。あなたがしていることは、実際にはバイトの途中で送信されているバイトを停止していると思われるため、バックアップを開始するときに新しいバイトを挿入します。time.sleep() の部分は、一部のハードウェア バッファがオーバーフローし、アライメント オフセットの原因となるバイトを失っている可能性があります。あるフロートから数バイトを取得し、別のフロートから数バイトを取得し始めると、間違った答えが得られるようになります。

私が気づいたことの 1 つは、調整メカニズムがないことです。送信できるのはバイトだけなので、これは UART では難しいことがよくあります。1 つの方法は、ハンドシェイクを前後に送信することです。コンピュータは再起動を言い、ハードウェアは接続を再起動し(送信を停止し、バッファをクリアするなど)、0xDEADBEEFのような魔法を送信します。次に、コンピューターはこの 0xDEADBEEF を見つけて、次のメッセージがどこから始まるかを知ることができます。ハードウェア/OS に存在するバッファを認識​​し、オーバーフローしないように予防措置を講じる必要があります。XON/XOFF から実際のハードウェア フロー制御まで、さまざまなフロー制御方法があります。

于 2012-09-30T20:47:40.250 に答える
-1

私はPythonを知りませんが、Arduinoが次のような番号を送信するのは何が問題なのですか:

value= 1.234;
Serial.println(value);

Arduino がフロートを受け取るには:

#include <stdio.h>
#include <stdlib.h>

void loop() {
    char data[10], *end;
    char indata;
    int i=0;
    float value;

    while ((indata!=13) & (i<10)) {
        if (Serial.available() > 0) {
            indata = Serial.read();
            data[i] = indata;
            i++;
        }
    }
    i-=1;
    data[i] = 0; // replace carriage return with 0
    value = strtof(data,&end);           
}

このコードは、私が過去に使用したコードと非常によく似ていますが、テストされていないことに注意してください。

于 2012-10-01T00:52:40.723 に答える