在这篇文章中有多个问题交织在一起。请仔细阅读,并回答你可以进行投票的部分。
用例
创建一个时间序列csv文件的压力读取。这些读物必须是最大频率,但我只需要它持续不到10秒左右。
材料
问题
识别并修复阻止最大读取/秒频率的瓶颈。
密码
阿杜伊诺
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)带宽
一些计算来找出瓶颈在哪里。
1数据包= 10位
串行线路速度: 450000/10 = 45000包/秒
Arduino样品.成串/二流率:
100 s* 1s/(10^-6 s)=1x10^4样本/秒
arduino硅适配器:廉价的克隆芯片。假设表现不佳,因为它不是一种arduino许可的产品,但这被认为是可以接受的损失,将在后面解释。假设有无限的带宽,尽管这显然将提高一个数量级的性能。
USB2.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秒。
结论:瓶颈是串行波特率。
调整波特率证实了这一点。我发现el uno只支持最大450000波特率,当arduino实际上支持了270万美元从我可以收集到的网上。话虽如此,还是有些不对劲。
关键问题
回想一下,以这个波特率,我们应该看到压力读取产生的理论45000包/秒。
波德率.数据长度-无奇偶校验-1端位存在: 450000-8-n-1
让sensorValue = 1023。数据显示在println:1023\n中
当我在arduino中运行serial.println(sensorValue)时,有多少数据包通过线路发送到PC?如何将其序列化为数据包?有多少包将通过电报发送?下列哪一项是正确的:
16位int要求传输2个分组。\n还会强制执行2条。共计=4
B. sensorValue被转换成字符串,并通过单独的数据包通过线路发送:1用于1,1用于0,1用于2,1用于3,1用于\,1用于n。共计=6
C.其他(帮助我优化??)
测试
我看到的结果不像我预期的那样。
让baud = 450000。
更改arduino代码中的value serial.println(value)会在txt文件中产生不同的读取/秒数:
value = readPin\n >> 5417压力读数/秒
value = 1 >> 10201读取/s
value = 1023 >> 4279读取/s
这告诉了我几件事。读取类比the的值时存在开销。我还可以得出结论,arduino也只在需要(1 >8位数据,1023 > 16位数据)时才发送多个数据包。等等,什么?这没什么意义。这是怎么回事?
调整波特率会导致读取数发生变化,直到arduino maxes结束为止。但是让我们找到我应该期待的吞吐量。
450000 b/s * (1包/ 10b) *1读/ (4或6包)= 11250读或7500个理论读/s
实际= 5417读/秒
2,000读消失在哪里?
发布于 2016-09-05 06:51:09
您是对的,瓶颈是串行端口(从低效率传输数据的意义上说)。然而,大多数其他假设都是错误的。
波特率代表
波特率是指每秒不同的符号变化数。在这里,它相当于每秒的位数。波特率将包括传输的所有比特,而不仅仅是数据(开始、停止、奇偶)。
如何传输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换行和回车。
如何使它更快
println(val, HEX) --对于大于255的数字,您将需要最多5个字节。Serial.write() -这个函数将原始二进制数据放入串行,所以如果您想发送一个值10的值,它只会发送一个字节的值10。然而,当您想发送10位变量时,事情变得复杂起来--为此您需要2字节,而PC需要知道哪一部分是第一部分,第二部分是第二部分。您需要想出某种形式的简单传输协议来处理这个问题,因此可能需要一些开始/停止字符。如果您仍然使用10位,我建议使用3字节的帧:1开始字节,2字节数据。这样,理论上可以达到每秒18000帧,超过最大analogRead()频率。
发布于 2016-10-05 15:49:53
一种选择是,在发送回PC之前,先对x次进行采样,然后对其进行平均值。或者接受压缩328 p的挑战!如果你的压力读数基本一致的话,你可能对一些RLE没什么意见。
不要用10位。ADC可能有10位分辨率,但精度是+/- 2 LSB,并且非常依赖于稳定的vref。因此,放下2 LSB,使用前8位的快速阿杜诺到个人电脑读数或多样本和平均噪音。
这是一个高噪音,共享,低分辨率的ADC。因此,不要让其他模拟引脚漂浮,因为这会导致噪音(只是接地)。还运行Arduino在一个接地的外壳,如果可能的话,因为ADC有一个MUX,使它有更长的跟踪。转换模数转换器模式或引脚也会产生一些噪音(不是你在这里做的)。电池功率是伟大的,如果你可以保持一个稳定的输入电压,否则AC/DC噪音可能会导致意想不到的vref波动。
Arduino上的主循环运行328 p和8u之间的串行IO,以及模拟读取。因此,时间瓶颈要复杂一些。
UNO串行到USB转换是由ATMEGA8u2 (板上的另一个芯片)处理的,它可以在115.2kbaud (而不是450000)进行通信。
8u和328 p上有缓冲区,这只是为了增加复杂性。两片芯片在不同的时钟上运行。ATMEGA8u2由晶体运行,ATMEGA328p (主处理器)从谐振器(均为16 The )运行。
根据您的需要,提斯有一个稍微准确的模数转换器(外部的一个将提供更好的读取)和一个更快的CPU,更多的内存等,它可以最大限度的USB端口速度。此外,保罗有很好的信息,一些低水平的技术,以使事情非常快。
https://stackoverflow.com/questions/39324332
复制相似问题