【问题标题】:Sending float type data from Arduino to Python将浮点类型数据从 Arduino 发送到 Python
【发布时间】:2012-09-21 19:17:00
【问题描述】:

我需要从 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 发送和接收浮点数据之外还有其他想法吗?

【问题讨论】:

  • 看起来您正在将数据从 arduino 发送到 python ...而不是从 python 到 arduino,正如标题所暗示的那样...
  • 我认为他的意思是标题中的往返。 tez,如果是这种情况,请更改。
  • 你为什么要读 5 个字节,看来你只发送了 4 个。
  • 是的,上面的所有代码都是用于将数据从 arduino 发送到 python。我首先尝试“arduino 到 python”部分。但是关于“将浮点数据从 python 发送到 arduino 和正如我在问题中提到的那样,欢迎在 python 端接收相同的数据。
  • @CrazyCasta 是的,对不起。那是一个错误。我正在尝试不同的东西(添加新行字符等)。我会编辑它

标签: python c arduino atmega


【解决方案1】:

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

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

# 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 

参考资料: Sending a floating point number from python to arduinoHow to send float over serial

【讨论】:

    【解决方案2】:

    我不知道 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);           
    }
    

    请注意,此代码未经测试,尽管与我过去使用的代码非常相似。

    【讨论】:

    • 这个页面在搜索引擎上的排名很高,所以值得指出的是,这实际上并没有发送浮点数,而是将浮点数四舍五入到小数点后2位并将其转换为字符然后发送。根据您的应用程序,这可能是也可能不是问题。与您的返回码相同。还有 - 将字符转换为浮点数的好代码。
    【解决方案3】:

    嗯,简短的回答是软件和硬件之间正在进行一些交互。我不确定你是如何停止传输的。我怀疑你所做的实际上是停止发送中间字节的字节,因此在你开始备份时注入一个新字节。 time.sleep() 部分可能是某些硬件缓冲区溢出并且您丢失了导致对齐偏移的字节。一旦你开始从一个浮点数中抓取几个字节,从另一个浮点数中抓取几个字节,你就会开始得到错误的答案。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-27
      • 1970-01-01
      • 2015-10-07
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 2020-04-16
      • 2020-08-16
      相关资源
      最近更新 更多