远程读取和写入结构

时间:2013-04-07 23:25:53

标签: c++ struct embedded arm protocol-buffers

我正在建造一个附有传感器的机器人。机器人上的控制单元是ARM Cortex-M3,所有传感器都连接到它上面,它通过以太网连接到“地面站”。

现在我想通过地面站在机器人上读写设置。因此,我考虑在机器人上实施一个可由地面站操纵的“虚拟寄存器”。

它可以由结构组成,看起来像这样:

// accelerometer register
struct accel_reg {
  // accelerations
  int32_t accelX;
  int32_t accelY;
  int32_t accelZ;
};

// infrared distance sensor register 
struct ir_reg {
  uint16_t  dist; // distance
};

// robot's register table
struct {
  uint8_t     status;         // current state
  uint32_t    faultFlags;     // some fault flags
  accel_reg   accelerometer;  // accelerometer register
  ir_reg      ir_sensors[4];  // 4 IR sensors connected
} robot;

// usage example:

robot.accelerometer.accelX = -981;
robot.ir_sensors[1].dist = 1024;

在机器人上,寄存器将不断填充新值,配置设置由地面站设置并由机器人应用。

地面站和机器人将用C ++编写,因此它们都可以使用相同的struct数据类型。

问题我现在的问题是如何在不写大量元数据的情况下将读/写操作封装在协议中?

假设我想阅读注册robot.ir_sensors[2].dist。我如何在我的协议中解决这个寄存器?

我已经考虑过以字节为单位传输相对偏移量(即结构内存中的相对位置),但我认为内存对齐和填充可能会导致问题,特别是因为地面站在x86_64架构上运行而机器人运行在一个32位ARM处理器。

感谢任何提示! :)

2 个答案:

答案 0 :(得分:1)

我认为Google protocol buffers是一个很好的会话/表示层工具。实际上,Google协议缓冲区不支持我想到的语法。因此,我将更改我的答案的这一部分,以通过Code Synthesis推荐XSD。虽然它主要与XML一起使用,但它支持不同的表示层,例如XDR,并且可能比具有大量可选数据的协议缓冲区更有效。生成代码也非常适合使用。 XSD 可以免费使用OpenSource软件,甚至可以使用有限的消息结构进行商业用途。

我不相信你想随机读/写寄存器组。您可以使用enum为消息添加前缀,该消息表示消息,例如IR updatedistanceaccel等。这些是注册组。然后机器人用寄存器组响应。到目前为止,您提供的所有寄存器都是传感器。 write必须是电机控制?

您想要考虑您想要执行的控制以及您希望接收的遥测类型。然后提出一个消息结构并将信息捆绑在一起。您可以使用sequence diagrams和远程过程API,例如SOA/SOAPRPCREST等。我不直接表示这些RPC框架,但是诸如request/response之类的概念以及可能只是在没有特定请求的情况下定期发送的消息(遥测)。因此,来自地面站的遥测请求会有某种间隔,然后机器人会定期响应未经请求的数据。你总是需要一个消息ID(enum以上),除非你的协议是有状态的,我会因为健壮的原因而不鼓励。

您还没有描述控制系统如何工作或者您是否希望远程执行此操作。描述可能会导致更多关于协议的想法。我相信我们正在讨论OSI的第5,6,7层。玩得开心。

答案 1 :(得分:1)

我也会建议使用Google Protocol Buffers。

在最简单的情况下,您可以像这样实现一条消息RobotState

message RobotState {
   optional int32_t status = 1;
   optional int32_t distance = 2;
   optional int32_t accelX = 3;
   ...
}

然后,当机器人收到消息时,它将从存在的任何可选字段中获取新值。然后它将回复一条包含所有字段当前值的消息。

这样,使用大多数protobuf实现的“合并消息”功能实现字段更新非常容易。此外,您可以在开始时保持简单,因为您只有一种消息类型,但如果您稍后需要扩展,则可以添加子消息。

protobuf确实不支持int8_tint16_t。只需使用int32_t代替。