我正在实现一个通过USB设备与电机控制器通信的类。我有一切工作,除了指示通过comm链接获取的参数是否“新鲜”的方式。到目前为止我所拥有的:
class MyCommClass
{
public:
bool getSpeed( double *speed );
private:
void rxThread();
struct MsgBase
{ /* .. */ };
struct Msg1 : public MsgBase
{ /* .. */ };
struct Msg2 : public MsgBase
{ /* .. */ };
/* .. */
struct MsgN : public MsgBase
{ /* .. */ };
Msg1 msg1;
Msg2 msg2;
/* .. */
MsgN msgn;
std::map< unsigned long id, MsgBase *msg > messages;
};
rxThead()
是一个无限循环,在一个单独的线程中运行,检查USB设备是否有可用消息。每封邮件都有一个唯一标识符rxThread()
用于将其粘贴到正确的msgx
对象中。我需要的是当用户调用getSpeed()
函数时,它需要能够判断当前速度值是“新鲜”还是“陈旧”,即包含速度值的msgx
对象是否为在指定的超时期限内更新。因此,每个消息对象都需要实现自己的超时(因为它们因每条消息而异)。
所有消息都由电机控制器定期发送,但也有一些消息在内容发生变化时立即发送(但如果内容不变,它们也会定期发送)。这意味着接收超过标称速率的消息是可以的,但它应该在最大超时时间内至少出现一次。
USB设备提供时间戳和消息,因此我可以访问该信息。时间戳不反映当前时间,它是具有微秒分辨率的unsigned long
数字,设备每次收到消息时都会更新。我怀疑设备刚从我调用其初始化函数时开始从0
开始递增。我能想到实现这一点的几种不同方式是:
每个消息对象都会启动一个在超时期间无限运行(WaitForSingleObject)的线程。超时后,它会检查计数器变量(在等待之前缓存)是否已递增。如果没有,它会设置一个标记消息为过时的标志。每次rxThread()
更新该消息对象时,计数器都会递增。
rxThread()
除填充消息外,还会遍历消息列表并检查每个消息的上次更新时间戳。如果时间戳超过超时,则将消息标记为失效。此方法可能存在所需处理量的问题。它可能不会成为大多数机器的问题,但这个代码需要在速度慢的“工业计算机”上运行。
我非常感谢您对如何实施这一点的想法和建议。我对除了我提到的两个以外的想法持开放态度。我正在使用Visual Studio 2005,因为USB设备驱动程序仅限Windows,因此跨平台可移植性不是一个大问题。目前我正在监控大约8条消息,但如果解决方案足够轻,我可以添加几个(可能是另外8个),而不会遇到处理功能限制,这将是很好的。
提前致谢, 与Ashish。
答案 0 :(得分:1)
如何在邮件中存储时间戳,并getSpeed()
检查时间戳?
答案 1 :(得分:1)
如果您在消息变得陈旧时不需要“立即”做某事,我认为如果您将计算机的时间和设备的时间戳存储在每条消息中,您可以跳过使用计时器:
#include <ctime>
#include <climits>
class TimeStamps {
public:
std::time_t sys_time() const; // in seconds
unsigned long dev_time() const; // in ms
/* .. */
};
class MyCommClass {
/* .. */
private:
struct MsgBase {
TimeStamps time;
/* .. */
};
TimeStamps most_recent_time;
bool msg_stale(MsgBase const& msg, unsigned long ms_timeout) const {
if (most_recent_time.sys_time() - msg.time.sys_time() > ULONG_MAX/1000)
return true; // device timestamps have wrapped around
// Note the subtraction may "wrap".
return most_recent_time.dev_time() - msg.time.dev_time() >= ms_timeout;
}
/* .. */
};
当然,如果您愿意,TimeStamps可以是MyCommClass中的另一个嵌套类。
最后,每次收到消息时,rxThread()都应该设置相应的消息的TimeStamps对象和most_recent_time成员。如果在收到任何其他类型的最后一条消息后它变得陈旧,所有这些都不会检测到过时的消息,但是你在问题中的第二个可能的解决方案会有同样的问题,所以也许这无关紧要。如果它确实重要,如果msg_stale()也比较当前时间,这样的事情仍然有效。