ArbyBot Development Log #2 - AMP Candidate 1
974 words Estimated 5 min read
Introduction
In this post, I present the first design candidate for Arby Message Protocol (AMP), carried over Controller Area Network (CAN) using the ABC scheme introduced in my first blog post.
AMP defines the structure and meaning of message payloads carried in one or more ABC packets with protocol value 0.
Packets belonging to a message share the same sender, target and message counter.
The goal is to control the microcontroller units (MCUs) aboard ArbyBot and allow them to communicate with one another. A visualisation of the AMP communication stack is presented (Figure 1).
---
config:
flowchart:
wrappingWidth: 1000
rankSpacing: 32
padding: 10
subGraphTitleMargin:
top: 6
bottom: 16
---
flowchart TB
accTitle: AMP communication stack
accDescr: A diagram showing the four layers of the AMP communication stack.
subgraph Custom["<span style='white-space:nowrap'>Arby Message Protocol Communication Stack</span>"]
direction TB
L4["<div style='width:800px'>4. Arby Message Protocol - Heartbeats, sensor data, motor commands</div>"]
L3["<div style='width:800px'>3. ArbyBot CAN (ABC) - Addressing and message fragmentation</div>"]
L4 --> L3
end
subgraph CAN["<span style='white-space:nowrap'>Controller Area Network (CAN 2.0B)</span>"]
direction TB
L2["<div style='width:800px'>2. CAN data link - Frames, arbitration, error handling</div>"]
L1["<div style='width:800px'>1. Physical - Signalling, CAN-H/CAN-L, termination</div>"]
L2 --> L1
end
Custom --> CAN
style Custom fill:none,stroke:#93a1a1,stroke-width:1px,stroke-dasharray:2 4
style CAN fill:none,stroke:#93a1a1,stroke-width:1px,stroke-dasharray:2 4
classDef layer stroke:#93a1a1,color:#586e75
class L1,L2,L3,L4 layer
style L4 fill:#eee7f1
style L3 fill:#e4edf0
style L2 fill:#e7eedf
style L1 fill:#f4e6d5
Figure 1. AMP communication stack.
Acronyms
Definitions employed are presented (Table 1).
| Acronym | Definition |
|---|---|
| ABC | ArbyBot CAN |
| AMP | Arby Message Protocol |
| CAN | Controller Area Network |
| GNSS | Global Navigation Satellite System |
| ID | Identifier |
| MCU | Microcontroller Unit |
| PPS | Pulse Per Second |
| UTC | Coordinated Universal Time |
Table 1. Acronym Definitions
AMP Design Candidate 1
In my first design, I bought MCP2515 boards with the intention of building a robot around Arduino Uno R3s. I envisioned a simple binary protocol, with each message containing fields in a predefined order and format.
I designed the protocol for CAN 2.0B, with a maximum payload of eight bytes per frame. The arbitration ID scheme (ArbyBot CAN) described in the article Arduino CAN Bus with MCP2515 supports multi-frame messages, as some messages exceed eight bytes.
A uint64 nanosecond timestamp is already 8 bytes, an entire CAN 2.0B payload.
Messages larger than eight bytes would therefore be split across multiple CAN frames and reassembled by the receiving device.
The first byte identifies the message type, which determines how the remaining bytes are interpreted. All multibyte numeric fields use big-endian byte order. Positions in the tables below are byte offsets within the complete message.
Messages
The Heartbeat message is presented (Table 2).
| Position | Type | Size | Name | Description |
|---|---|---|---|---|
| 0 | uint8 |
1 byte | Message Type | Heartbeat message type: 0. |
| 1 | uint32 |
4 bytes | Uptime | Seconds since startup. |
| 5 | bool |
1 byte | Time Valid | Indicates whether the system has established the current Unix time from a received timestamp, regardless of PPS synchronisation. |
| 6 | bool |
1 byte | PPS Lock | Indicates whether the system is currently synchronised to the PPS signal. |
Table 2. The Heartbeat message (AMP Design Candidate 1).
The Heartbeat occupies seven bytes and fits within a single ABC packet (Figure 2). The diagram shows bit offsets within the AMP payload; both Boolean fields occupy a full byte.
---
title: AMP Heartbeat Payload
config:
packet:
bitsPerRow: 56
bitWidth: 16
---
packet
accTitle: Seven-byte AMP heartbeat payload
accDescr: Seven bytes: message type (1), uptime in seconds (4), Time Valid (1) and PPS Lock (1).
0-7: "Type = 0"
8-39: "Uptime (seconds)"
40-47: "Time Valid"
48-55: "PPS Lock"
Figure 2. Heartbeat payload layout (AMP Design Candidate 1).
The PPS Synchronisation message is presented (Table 3).
| Position | Type | Size | Name | Description |
|---|---|---|---|---|
| 0 | uint8 |
1 byte | Message Type | PPS synchronisation message type: 1. |
| 1 | uint32 |
4 bytes | Timestamp | Unix time, seconds since epoch (1970-01-01 00:00:00 UTC), corresponding to the preceding PPS pulse. |
Table 3. The PPS Synchronisation Message (AMP Design Candidate 1).
The PPS message allows for synchronisation of time with other boards within the system. A time source, such as a GNSS receiver, could provide both the current Unix time and a physical PPS signal. The pulse provides the timing reference, while the AMP PPS Synchronisation message identifies the Unix second corresponding to the preceding pulse.
The Get message is presented (Table 4).
| Position | Type | Size | Name | Description |
|---|---|---|---|---|
| 0 | uint8 |
1 byte | Message Type | Get message type: 2. |
| 1 | uint16 |
2 bytes | Key | Identifier of the value to retrieve. |
Table 4. The Get message (AMP Design Candidate 1).
The Set message is presented (Table 5).
| Position | Type | Size | Name | Description |
|---|---|---|---|---|
| 0 | uint8 |
1 byte | Message Type | Set message type: 3. |
| 1 | uint16 |
2 bytes | Key | Identifier of the value to modify. |
| 3-7 | Defined by Key | 5 bytes | Value | The value to assign to the specified key. Its data type is determined by the key. |
Table 5. The Set message (AMP Design Candidate 1).
The Emit message is presented (Table 6).
| Position | Type | Size | Name | Description |
|---|---|---|---|---|
| 0 | uint8 |
1 byte | Message Type | Emit message type: 4. |
| 1 | uint16 |
2 bytes | Key | Identifier of the value emitted. |
| 3-7 | Defined by Key | 5 bytes | Value | The current value of the specified key. |
| 8 | uint64 |
8 bytes | Timestamp | Time at which the value was read, in nanoseconds since the Unix epoch (1970-01-01 00:00:00 UTC). |
Table 6. The Emit message (AMP Design Candidate 1).
Values within the Set and Emit messages are encoded from byte 3 and limited to 5 bytes in total. Any unused trailing bytes are set to zero.
Booleans are encoded as 0 for false and 1 for true.
Conclusion
This protocol candidate allows devices to read and update values across the system.
Each device’s firmware would contain a predefined mapping between numeric keys and the variables they represent.
A uint16 key provides up to 65,536 identifiers for sensor readings, configuration settings, and other operating values.
The device with a variable for the specified key would respond to a Get or Set message with an Emit message to report the variable’s current value. Devices could also emit updates on a predetermined schedule for frequently changing variables such as wheel position or sonar readings. If the value has not changed since the last Emit message, the next scheduled update may be skipped. Sensor readouts would not support the Set message, since they are read-only measurements.
This protocol has limitations:
- Only 5 bytes are available for a value communicated within a Set or Emit message. 64-bit values are unsupported.
- Devices must have a shared definition of what each key/value is beforehand. Incompatible changes to those definitions could cause values to be silently misinterpreted.
- Responses and updates are indistinguishable. This was the intention behind the simplicity of the design in acknowledging that the value emitted is the latest value.
- Batching of messages is unsupported but introducing it could allow more efficient multi-packet communication.
In the next post, I’ll introduce AMP design candidate 2, which primarily addresses batching and value length communication.