在过去的几周里,我一直在破坏我的头脑,在网上找不到有关我应该如何做的有用信息。
目标:
pi
到另一个pi
驱动多个伺服/ RC电机无线。 RC
构建pi
遥控器,接收器端有第二个pi
。到目前为止我做了什么:
pi/arduino
上的串行库来完成,但它会导致主连续程序循环的采样率降至200Hz以下,这是一个问题。 下一步和问题:
pi
(据我所知)在发送准确的PWM信号时是垃圾,更糟糕的是正确地拾取它们。 我该怎么做?
也许使用两个Arduinos进行传输和接收?
我可以购买“盾牌”吗?
是否有可以为我这样做的图书馆? (Pi
或adruino
?)
已编辑: Roland感谢您的回复
我添加了当前的串行传输代码。我不认为这是最有效的方式。如果在另一个PWM信号之间暂停发送PWM信号,则可以发送更多数据而不是仅发送比特。我不完全确定,但我认为这就是遥控遥控飞机控制器发送信号的方式。
请注意,我插入的代码是一个来自更大程序的简单摘录,包含几个模块和几百行代码。我认为以下几行是串行发射器的核心。
import serial
bProgramLoop = True
while (bProgramLoop == True):
#...lots of code...
iThrustPort = int(fThrustPort)
iThrustStrb = int(fThrustStrb)
iThrustTail = int(fThrustTail)
iPortMotorAngle = int(fPortMotorAngle) + 50
iStrbMotorAngle = int(fStrbMotorAngle) + 50
sPortMotorSignal = '{:02d}'.format(iThrustPort)
sStrbMotorSignal = '{:02d}'.format(iThrustStrb)
sTailMotorSignal = '{:02d}'.format(iThrustTail)
sPortAngleSignal = '{:02d}'.format(iPortMotorAngle)
sStrbAngleSignal = '{:02d}'.format(iStrbMotorAngle)
sSignal = sPortMotorSignal + sStrbMotorSignal + sTailMotorSignal + sPortAngleSignal + sStrbAngleSignal
oSer.write(sSignal) #where sSignal = 1234567890 for example or any combination of numbers from 0 to 9
答案 0 :(得分:0)
在您的评论中,您提到波特率为4800.对于串行端口,非常为低。串行端口使用两级(二进制)信令,因此以每秒位数为单位的数据速率等于波特率的符号速率。
但是我看到的一个收发器数据表列出了5 kbits / s作为典型传输速度,以及9.6 kbit / s作为最大速率。也许你可以尝试改善天线以提高传输速率?
但是4800波特串行意味着你不会获得超过4800/8 = 600字节/秒的带宽(这是无视停止位和奇偶校验位的事情)。使用10字节消息,您应该获得最多60Hz。一个5字节的消息可以将其提高到120 Hz。所以似乎发射机是限制因素。
这意味着你必须每一点都节俭!
您的代码将数据作为连续的十进制字符串传输。对于5个数字,这需要10个字节。可以减少一半:
让我们在0-100范围内生成5个2位数字。
In [1]: import random
In [2]: data = [random.randint(0, 101) for _ in range(5)]
In [3]: data
Out[3]: [18, 80, 55, 96, 44]
两位十进制数只需要一个字节来存储它们。即使是两位十六进制数也适合一个字节。因此,让我们将数字组合成一个字节字符串。
In [4]: import struct
In [5]: struct.pack('5B', *data)
Out[5]: b'\x12P7`,'
In [6]: len(struct.pack('5B', *data))
Out[6]: 5
您可以在单个串行write
调用中发送此5字节字符串,并在接收端解压缩它们。
让我们以速度比较两个结论。我已将原始代码和struct
解决方案包含在函数中,因此我可以轻松使用IPython的%timeit
魔术命令来测量它们。
In [7]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:def astext():
: data = [random.randint(0, 101) for _ in range(5)]
: sPortMotorSignal = '{:02d}'.format(data[0])
: sStrbMotorSignal = '{:02d}'.format(data[1])
: sTailMotorSignal = '{:02d}'.format(data[2])
: sPortAngleSignal = '{:02d}'.format(data[3])
: sStrbAngleSignal = '{:02d}'.format(data[4])
: sSignal = (sPortMotorSignal + sStrbMotorSignal + sTailMotorSignal +
: sPortAngleSignal + sStrbAngleSignal)
: return sSignal
:
:
:def asbinary():
: data = [random.randint(0, 101) for _ in range(5)]
: return struct.pack('5B', *data)
:--
In [8]: %timeit astext()
10000 loops, best of 3: 31.6 µs per loop
In [9]: %timeit asbinary()
10000 loops, best of 3: 23.5 µs per loop
In [10]: (31.6-23.5)/31.6
Out[10]: 0.2563
(这是在intel core2处理器上。Pi
中的ARM芯片可能会慢一些。)生成二进制字符串所需的时间比生成文本字符串少大约25%。
但是从这些时候你可以看到这些可能不是性能关键。它们可以以> 30 kHz的频率组装数据。 Pi
的速度要慢150倍才能达到时间要求。
重要的是二进制字符串是文本字符串的一半,所以我希望它的传输速度大约是文本字符串的两倍。
您应该仔细考虑的是每个信号实际需要多少不同的信号电平?四位给出2⁴= 16级,而8位给你2⁸= 256级。如果您的应用程序可以使用16个信号级别,则可以将消息打包为5 * 4 = 20位。
答案 1 :(得分:0)
(代表OP发布)。
我已经解决了上面解释的串行数据传输问题。有关详细信息,请访问我的另一篇文章:使用Raspberry Pi进行串行数据传输输入输出延迟
我希望这可以帮助任何人。这样,您就可以通过串行连接传输数据,无论是通过RF链路模块还是通过直接布线,都没有时间延迟。
请注意,许多RF链路模块的最大传输速率为4800波特,以实现稳定良好的连接。