射频电机/伺服控制

时间:2016-05-16 08:45:13

标签: python arduino raspberry-pi wireless pwm

在过去的几周里,我一直在破坏我的头脑,在网上找不到有关我应该如何做的有用信息。

目标:

  • 从一个pi到另一个pi驱动多个伺服/ RC电机无线
  • 本质上,我想使用RC构建pi遥控器,接收器端有第二个pi

到目前为止我做了什么:

  • 我已经能够使用串行库以及两个Pi上的Tx和Rx引脚,通过廉价的433MHz接收器/发送器成功发送串行数据。但是,我需要同时发送至少六对两位数字(即12个数字)。这可以使用pi/arduino上的串行库来完成,但它会导致主连续程序循环的采样率降至200Hz以下,这是一个问题。

下一步和问题:

  • 由于串行数据传输不能正常工作,我想到将PWM信号直接嵌入到RF信号中。 (据我所知,这就是业余爱好RC控制器的工作方式)。
  • pi(据我所知)在发送准确的PWM信号时是垃圾,更糟糕的是正确地拾取它们。
  • 只是为了澄清我必须通过网络上的通过RF模块执行此操作。

我该怎么做?

也许使用两个Arduinos进行传输和接收?

我可以购买“盾牌”吗?

是否有可以为我这样做的图书馆? (Piadruino?)

已编辑: 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

2 个答案:

答案 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波特,以实现稳定良好的连接。