5

我需要从 Python 向 Arduino 发送浮点数据并返回相同的值。我想先从 Arduino 发送一些浮点数据。数据以 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上面代码所示的模块可以打印浮点值。

50% 的时间,数据打印正确。但是,如果我弄乱time.sleep()或停止传输并重新启动它,则会打印出不正确的值。我认为在这种情况下解包了错误的 4 个字节集。知道我们可以在这里做什么吗?

除了使用 struct 模块向 Arduino 发送和接收浮点数据外,还有其他想法吗?

4

3 回答 3

0

因为这个问题在搜索引擎上排名很高,所以我制定了一个可行的解决方案。

警告:除非您需要全浮点精度,否则转换为字符串并发送(使用 sprintf 或 dtostrf,或使用Serial.print(value,NumberOfDecimalPlaces) (文档))。这是因为以下解决方案 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 中接收这个,我使用了你的解决方案,并添加了一个函数来比较两个输出以进行验证。

# 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() 部分可能是某些硬件缓冲区溢出并且您丢失了导致对齐偏移的字节。一旦你开始从一个浮点数中获取几个字节,从另一个浮点数中获取几个字节,你就会开始得到错误的答案。

我注意到的一件事是您没有任何对齐机制。这通常很难用 UART 来完成,因为您只能发送字节。一种方法是来回发送握手。计算机说重新启动,硬件重新启动连接(停止发送内容,清除它拥有的 w/e 缓冲区等)并发送一些魔法,如 0xDEADBEEF。然后计算机可以找到这个 0xDEADBEEF 并知道下一条消息将从哪里开始。您仍然需要了解硬件/操作系统中存在的任何缓冲区,并采取预防措施以免它们溢出。从 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 回答