一种常见的情况是有一台PC通过RS232将命令发送到微控制器。我的PC程序正在将命令(每个命令由多个字节组成)以最快的速度发送给小型机器人。机器人上的微控制器是一个视差螺旋桨。螺旋桨可用的端口驱动程序。 (缓冲区通常为16到256个字节)。我可以任意增加这些缓冲区或创建自己的更大的循环缓冲区,但是我想采用一种更有条理的方法来确定适当的大小要求和/或在从串行端口驱动程序缓冲区中取出字节之前可以等待的最短时间。

乍一看:


115200 ==每毫秒115.2位==〜每毫秒12.8字节(假设1个停止位)

1)这是一种计算串行传输时序的有效方法吗?

还可以根据我的特定设置进行操作:蓝牙串行配置文件驱动程序<->蓝牙收发器<-*-> BlueSMIRF无线调制解调器<->视差推进器程序

2)在给定的时间内,我可以发送的最大数据量是多少?

也许我一直在使事情复杂化,但是似乎上面的传输链中可能涉及多个缓冲区。其他人通常如何处理?他们会限制PC发送到已知的安全速率吗?实施流量控制?如果要实施流控制,这将如何影响带宽和响应时间?

(如果重要的话,我的实验是在PC上使用操纵杆来控制多个伺服器,并对操纵杆的运动做出即时反应。因此,操纵杆的每一次微小运动都会导致向微控制器发送多个命令。这些命令不仅简单位置命令尽管如此,它们也会随着时间的推移而涉及伺服的加速/减速,这就是微控制器在处理新字节之前花费大量时钟周期的原因。)

#1 楼

我认为您的问题形式是错误的。问题不在于您没有正确地计算出微控制器每秒可以抛出多少数据。这是因为您无法让微控制器表明其准备接收下一条命令。

换句话说,如果尝试通过精确计算发送数据的速度来解决此问题,则不可避免地要执行以下操作之一:


发送的数据少于微控制器的处理能力
发送的数据超出微控制器的处理能力(在最坏的情况下,发送的数据只会稍微多一点,因此缓冲区需要一个小时才能超载并导致调试一些完全不相关的东西)

该解决方案是为您的微控制器提供反馈-流量控制。在最基本的示例中,仅发送一个代表命令完成的字符(@Rocketmagnet的SpaceWire建议将是最可靠的,但也很费劲)。在缓冲区中。因此,您应该进行的计算是将缓冲区大小除以要发送的最大命令的大小,然后再减去1(或更多)以确保安全。这将告诉您已发送的命令与已收到的确认之间最大的允许差异,并使您可以通过保持缓冲区已满来以最大的速度工作。最长的命令是7个字节(“ fw 4.32”)或类似的内容,并且您具有64字节的缓冲区。这意味着您可以在缓冲区中放入9个命令($ 7 \ times 9 = 63 <64 $),但是为了安全起见,您将减去一个,并且只允许8个命令。这是一些python psudeocode:取决于您的PC代码的工作方式。

评论


$ \ begingroup $
谢谢,这是一个很好的答案。但是,等待“ ack”类型消息的延迟是相当大的。我希望避免这种情况,但是对于100%的可靠性来说,这是不可避免的。我同意Rocketmagnet建议的Spacewire协议看起来非常健壮,但是对于我所需要的来说可能太多了。
$ \ endgroup $
– kaliatech
2012年11月12日在22:37



$ \ begingroup $
好吧,请记住,您无需等待每个命令被确认。您可以发送具有缓冲区空间的任意数量的命令,然后根据收到的每个确认开始发送一条消息。这样可以消除任何延迟(通过保持微控制器命令队列已满),但可以防止您溢出缓冲区(这是原始问题)。
$ \ endgroup $
–伊恩
2012年11月13日14:23



#2 楼

我建议两种可能的方法。


使用“心跳”以适合您“速度预算”的固定频率传输众所周知的状态包。在这种情况下,您永远不会直接从PC或MCU发送临时消息,您所能做的就是更新将在计划的时间发送的状态数据包。执行它。例如。您只能每100毫秒发送一个数据包,如果在100毫秒到期之前提交了第二个数据包,则其传输将延迟到100毫秒超时(例如,量子)到期为止。这要求您将消息添加到队列,然后以固定的速率从队列发送。与#1中的心跳类似,但是效率更高,因为在未更改的情况下不会发送数据。这种设计的缺点是,如果您超负荷使用,则会在通信中建立越来越高的延迟,并且如果您的通信突发性可变,则通信延迟可能会有很大差异。由于算法简单且体积小,因此可以从MCU发送数据。

#3 楼

没有正确的答案,我敢肯定,您已经知道(或可以猜测)解决此问题所需的一切。但是

首先要说的是,下游设备必须能够处理长期和短期的数据流。在短期内,设备使用缓冲来应对流量。从长远来看,需要对数据采取行动的处理能力。

您遇到的一个问题是,您无法控制链中的所有步骤,因此如果其中一个步骤造成了延迟,除了更换它以外,您可能无能为力。但是,我曾想过,蓝牙串行驱动程序会有一个不错的大缓冲区,并且可以与收发器和BlueSMIRF一起很好地使用,因此忽略它们可能是安全的。我想真正的问题出在Propeller与PC之间。对此应用一些适当的理论。

有趣的是,已经针对与餐厅排队有关的这个问题进行了研究,例如EG服务时间和服务价值未知的队列中餐厅排队模型和均衡的案例研究。但是,在线上有更容易理解的资源,例如“排队论”,“傻瓜排队论”。但是,您真正想要的可能是如何确定消息队列的大小。

您有几个选择:有序率。确切确定您真正需要的速率,不要超过此速率。
在MCU上使用实时操作系统,以确保及时处理字节。
实施流控制。


但这是我的首选解决方案。太空线!或至少使用它的流量控制系统。

本质上,下游设备向上游设备发送字节,说明其FIFO中的空位数。这样,数据生成者仅发送用户可以应付的内容。

如果您有兴趣,可以阅读完整的Spacewire标准:IEEE 1355。

#4 楼


乍一看:

115200 == 115.2位/毫秒==〜〜12.8字节/毫秒
(假设有1个停止位)

是那是
串行传输计时的一种有效方法吗?蓝牙链接上的任何协议开销


另外,根据我的特定设置,

PC程序<->蓝牙串行配置文件驱动程序<->蓝牙<收发器<-*-> BlueSMIRF无线调制解调器<->视差螺旋桨
程序


我认为假设PC到调制解调器是合理的能够处理115200 bps的流量,因此您可以从等式中消除这些流量。

但是,具有这样的多跳确实可以防止使用流控制信号,而不会引入响应消息...会减慢响应时间。

现在,以最坏的情况,不协议开销115200 bps,这意味着您的视差将每69us接收一个字节-添加开始,停止或奇偶校验位将使该速率降低一点点,但是假设最坏的情况会给您一些余地。这意味着您的控制器必须处理每69us接收一个字节,以及执行其正常工作(计算等)。

但是实际上,您将发送(n)个字节的消息字符串,需要进行缓冲并作为字符串进行处理-同时仍在进行常规操作。计算缓冲区本身就是一门艺术,但是我通常会使用(最少)两倍于最长字符串(如果您有RAM空间)的大小。如果在开始接收下一个消息之前未对其进行处理,那么任何丢失消息的可能性都有可能丢失。

如果仅限于最长消息的长度,则需要100%确保可以在接收到最后一个字节和接收到下一条消息的第一个字节之间处理该消息。 (对于较小的消息,显然问题较少)。

#5 楼

除了计算速度要求(随时间变化/随时间的变化而变化,以及每次更改代码的时间),您还可以执行其他一些操作:通过将中断发送到主设备来请求输入(在这种情况下,它是PC-您可能不需要使用中断,只需保留端口即可)。您可以让主设备缓冲输出(更容易使用pc进行缓冲-有效地进行无限缓冲),也可以除非必要就丢弃它们。 。通过中断引脚接受对μC的输入。在μC上具有一些基本上表示“需要输入”的标志变量。如果设置了此标志,则μC将接受输入。否则,它将被丢弃。这样,所有输入都会被快速消耗(保持缓冲区空闲),但不会使用所有输入。为了提高效率,请将时序调整为整个设置的近似波特率。您可能希望对自己的缓冲区类型的东西进行编码,而不是丢弃它-拥有一个小的数组,其中存储了一些输入。现在,您已经摆脱了所有上游缓冲区,并在μC上只有一个“人工”缓冲区,您可以对其进行完全控制。 μC作为简单的从控制器-给它简单的运动/位置命令,这些命令可以直接通过管道传递给电机。如果您有足够的中断引脚/中断MUX,则可能希望通过中断发送这些命令,以加快响应速度。