最大化Arduino串行输出

时间:2016-09-05 05:20:33

标签: python-3.x arduino serial-port arduino-uno pyserial

这篇文章中散布着多个问题。请仔细阅读并回答您可以获得的内容。

使用案例

创建压力读数的时间序列csv文件。这些读取需要具有最大频率,但我只需要它持续不到10秒左右。

材料

  1. Arduino Uno Clone(不可改变)
  2. 串口通过USB 2.0(可更改)
  3. pyserial(Python 3)
  4. SSD
  5. 问题

    识别并修复瓶颈,防止最大读数频率。

    代码

    Arduino的

    void setup() {
      //speed over the usb serial interface
      Serial.begin(450000);
    }
    
    void loop() {
        //get sensor data: read the input on analog pin 0:
        int sensorValue = analogRead(A0); //returns value 0-1023
        //send over serial
        Serial.println(sensorValue);
    }
    

    的Python

    ...
    ser.serial()
    ser.baudrate=450000
    ser.open()
    while True:
        try:
            serialData = float(ser.readline().decode().replace('\n', ''))
        except(ValueError):
            continue #I ran the code without this try/except and got 100 reads higher than when this is included in here. Caused no change in order of magnitude.
        now = datetime.datetime.now()
        serialData2 = serialData * voltageOffset #a couple of these happen
        outfile.write(now+', '+str(serialData2)+'\n')
    except(KeyboardInterrupt):
        ...
        os.sys.exit(0)
    

    带宽

    进行一些计算以找出瓶颈所处的位置。

    100 µs to read analog pin

    1包= 10位

    串行线速度:450000/10 = 45000包/秒

    Arduino sample-into-serial / second rate:

    100μs* 1s /(10 ^-6μs)= 1 x 10 ^ 4个样本/秒

    arduino硅适配器:便宜的克隆芯片。假设表现不佳,因为它不是arduino许可的产品,但这被认为是可接受的损失,这将在后面解释。假设有无限的带宽,虽然这显然会使性能提高一个数量级。

    USB 2.0

    包/ s = 480 mb / s * 10 ^ 6 b / mb * 1包/ 10 b = 48 x 10 ^ 6包/秒

    PC文件写入速度

    400 MB / s = 320 x 10 ^ 6包/ s

    PC python脚本

    未知。推定是无限的?已知datetime.now()查询需要约8μs。

    结论:瓶颈是串行波特率。

    调整波特率确认了这一点。我发现el-cheapo arduino uno只支持最大450000波特率,当arduino actually supports 2-7 million来自我可以在线收集时。话虽如此,还是有些不对劲。

    关键问题

    回想一下,在这个波特率下,我们应该看到压力读数产生理论上的45000包/秒。

    波特率 - 数据长度 - 不存在奇偶校验1结束位:450000-8-n-1

    sensorValue = 1023。数据看起来像println1023\n

    当我在arduino中运行serial.println(sensorValue)时,有多少数据包通过线路发送到PC?如何将其序列化为数据包?通过线路发送多少个数据包?以下哪一项是正确的:

    一个。 16位int需要传输2个数据包。 \n还有2个。总数= 4

    B中。 sensorValue被转换为字符串并通过网络发送,包含单独的数据包:1为1,0为1,2为1,3为1 ,\为1,n为1。总计= 6

    ℃。其他(帮我优化??

    测试

    我没有像我期望的那样看到结果。

    baud = 450000

    更改arduino代码value中的serial.println(value)会在我的txt文件中产生不同的读数/秒:

    value = readPin\n>> 5417压力读数/ s

    value = 1>> 10201读取/ s

    value = 1023>> 4279读/秒

    这告诉了我一些事情。读取analogPin的值时会有开销。我还可以得出结论,当arduino必须(1> 8位数据,1023> 16位数据)时,它也仅发送多个数据包。 等等,什么?这没有多大意义。 这是怎么发生的?

    调整波特率会导致读数变化,直到arduino最大化为止。但是让我们找到我应该期待的吞吐量。

    450000 b / s *(1包/ 10b)* [1读/(4或6包)] = 11250读数或7500理论读数/ s

    实际= 5417读/秒

    2,000个读数在哪里消失?

2 个答案:

答案 0 :(得分:2)

你是对的,瓶颈是串口(在某种意义上说,你无法有效地传输数据)。但是,您的大多数其他假设都是错误的。

波特率代表什么

波特率是每秒不同符号变化的数量。这里它等效于每秒位数。波特率将包括所有传输的比特,而不仅仅是数据(开始,停止,奇偶校验)。

如何传输10位值

由于您有8n1传输,因此无法准确发送10位数据。它必须是8的倍数,因此8位,16位,24位等10位将在两个8位部分中发送,就像它们作为int存储在Arduino存储器中一样。

println()如何运作

println()将数字转换为字符串。您可以为此转换指定基数(DEC,BIN,HEX,OCT) - 默认为DEC,因此1023将作为4字节+ \n传输,这是一个字节(ASCII 10)和\r (ASCII 13)也是一个字节。总共6个字节。 1将需要3个字节 - 1表示数据,2表示换行和回车。

如何加快速度

  1. 几乎不改变任何内容 - 使用println(val, HEX) - 对于大于255的数字,最多需要5个字节。
  2. 使用Serial.write() - 此函数将原始二进制数据放入串行,因此如果要发送值10,它将只发送一个字节值10.但是,当您要发送10位变量时事情变得复杂 - 你需要2个字节,PC需要知道哪个是第一个部分,哪个是第二个将它拼接在一起。你需要提出某种形式的简单传输协议来处理这个问题,所以可能需要一些启动/停止字符。
  3. 您需要10位分辨率吗?如果您可以继续使用8位,则可以传输纯数据,而无需任何其他字符。此外,正如评论中所建议的那样,您可以使用更快的ADC时钟。
  4. KIIV也建议 - 你可以使用ADC转换中断,它会在测量完成时立即触发。
  5. 如果仍然使用10位,我建议使用3字节帧:1个起始字节和2个字节的数据。这样理论上你可以达到每秒约18 000帧,高于最大analogRead()频率。

答案 1 :(得分:1)

一种选择是采样x次,然后在发送回PC之前对其进行平均。或者接受压缩328p的挑战!如果你的压力读数基本一致,你可能对某些RLE没问题。

不要使用10位。 ADC可能具有10位分辨率,但精度为+/- 2 LSB,并且非常依赖于稳定的vref。因此,降低2 LSB并使用前8位进行快速Arduino到PC读数或多样本并平均噪声。

这是一款嘈杂,共享,低分辨率的ADC。所以不要让其他模拟引脚悬空,因为它会产生噪声(只需将它们接地)。如果可能的话,也可以在接地外壳中运行Arduino,因为ADC有一个MUX,导致它有更长的走线。切换ADC模式或引脚也会产生一些噪声(这不是你在这里做的)。如果您可以保持稳定的输入电压,则电池电量很大,否则AC / DC噪声可能会导致意外的电压波动。

Arduino上的主循环运行328p和8u之间的串行IO以及模拟读取。所以时间瓶颈有点复杂。

UNO串口转USB由ATMEGA8u2(板上另一个芯片)处理,可以115.2kbaud(而不是450000)进行通信。

8u和328p上有缓冲区只是为了增加复杂性。两个芯片运行在不同的时钟上。 ATMEGA8u2从晶振运行,ATMEGA328p(主处理器)从谐振器运行(均为16MHz)。

根据您的需要,Teensy具有稍微更准确的ADC(外部更好的读取)和更快的CPU,更多的RAM等,并且它可以最大化USB端口速度。加上保罗在一些低级技术方面有很好的信息,可以让事情变得非常快。