【问题标题】:collecting 'double' type data from arduino从 arduino 收集“双”类型数据
【发布时间】:2012-09-23 20:44:42
【问题描述】:

我正在尝试将浮点数据从 arduino 发送到 python。数据以 8 个连续字节的数据(双精度大小)后跟换行符('\n')发送。如何收集这些连续字节和在 python 端(系统端)将其转换为正确的格式

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

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

    USART_send('\n');
}

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

python 代码。当然这不会以正确的格式打印数据,而只是想显示我尝试过的内容。

import serial,time

my_port = serial.Serial('/dev/tty.usbmodemfa131',19200)
while 1:
    print my_port.readline(),
    time.sleep(0.15)

更新

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

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

使用如上代码所示的struct 模块可以打印浮点值。但是,

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

【问题讨论】:

  • 您肯定会想要使用struct 模块,但我不确定在浮点数上使用它是否是个好主意。也许您应该使用整数或使用您自己的二进制格式。另外,请记住,您以原始二进制表示形式发送数字,因此它肯定包含换行符的 ASCII 代码。你应该使用read 而不是readline(忘记换行,你不需要它)
  • struct.unpack 是经过精心编写的,以正确解包通过网络接收的 IEEE 754 浮点数,无论它们在运行 Python 的机器上如何表示。但它仍然希望接收指定格式的浮点数,发送方应确保发送。根据您的问题,我查看了 arduino 的网站,对 learn Arduino double 实际上是单宽度精度数感到惊讶,这意味着 struct 必须使用 f 格式,而不是 d .我会更新答案。

标签: python c arduino atmega


【解决方案1】:

在 Arduino 上,doublethe same as float,即占用 4 字节内存的小端 single-precision floating-point number。这意味着您应该准确读取 5 个字节,使用 f 格式的 little-endian 变体来解压它,并忽略带有 x 的尾随换行符:

import struct
...

data = my_port.read(5)
num, = struct.unpack('<fx', data)

请注意,您不想使用readline,因为浮点数表示的任何字节都可以是'\n'

正如 Nikklas B. 所指出的,您甚至根本不需要换行,只需发送 4 个字节并从 Python 中读取尽可能多的字节。在这种情况下,格式字符串将为'&lt;f'

【讨论】:

  • 虽然我使用的是 arduino,但我不使用它的任何库。我的大学不希望我使用 arduino 库。我将它用作简单的 atmega328p 开发板。我'现在要尝试拆包并报告。
  • 我都试过了。工作得很好。我停止从 arduino 端发送换行符并使用 '
  • 尝试创建一次struct.Struct('&lt;f') 对象并在该对象上调用unpack(data)。这将消除一遍又一遍地重新编译&lt;f 格式的需要。另外,如果您要传输大量浮点数,则将它们成串处理会更有效率。例如,通过端口发送 256 个浮点数并执行单个 unpack('&lt;' + 'f' * 256)。如果您的目标机器是 little-endian,则更有效的选择是使用 numpy.frombuffer(data_received, dtype="float32"),但对于不同的问题,这将是一个很好的材料。
  • 我有问题。50% 的时间,数据打印正确。但如果我弄乱了 time.sleep() 或停止传输并重新启动它,打印出不正确的值。我猜猜在这种情况下解包了错误的 4 个字节集。知道我们可以在这里做什么吗??
  • 我猜你需要实现某种同步 - 但如果你将问题表述为一个单独的问题,你可能会得到更好的响应。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多