-
Notifications
You must be signed in to change notification settings - Fork 2
Lowcar Protocol
- 1. Motivation & Overview
- 2. Message Types
- 3. General Message Flow
- 4. Anatomy of a Packet
- 5. Message Types (Anatomy of a Payload)
Runtime communicates with the lowcar devices over a serial connection; that is, through a stream of bytes. This means if we want to say, "update me with the state of the limit switch every millisecond," or, "set the motor to 50% speed backward," it has to be expressed through a series of bytes.
In a sense, dev handler and lowcar agree upon a language (the lowcar protocol) so they can understand each other when each entity says to the other a series of sounds (bytes). The goal of the lowcar protocol is to be able to say as much as possible with the fewest number of bytes to reduce the computing time spent on encoding and decoding messages.
In the rest of this page, we will refer to the entity sending a message as the speaker, and the entity receiving the message as the listener.
Below is a chart of the types of messages and a brief description of its purpose. Each of these will be covered in more detail in later sections.
Type | Speaker | Listener | Description |
---|---|---|---|
PING | DEV_HANDLER | LOWCAR | Periodic status update |
ACK | LOWCAR | DEV_HANDLER | Lowcar verification; Device identification |
DEVICE_WRITE | DEV_HANDLER | LOWCAR | Write to specific device parameters |
DEVICE_DATA | LOWCAR | DEV_HANDLER | Data on readable paramters |
LOG | LOWCAR | DEV_HANDLER | Message string for human-readable logs |
- Dev handler notices a new device connected and sends a
PING
. If the device is a lowcar device, it will send anACKNOWLEDGEMENT
as a response. - If dev handler does not receive an
ACK
, it does not proceed with communicating with the device. Otherwise, proceed with step 3. - From now on, dev handler will send
PING
messages to the Lowcar approximately once per second. If the Lowcar device doesn't get aPING
for a specified amount of time (about a few seconds), then we clean up. If dev handler doesn't receive any messages from Lowcar for a specified amount of time, we clean up. - From now on, the lowcar devices will send
DEVICE_DATA
messages with all readable parameters at a hardcoded interval. - From now on, dev handler will parse incoming
DEVICE_DATA
messages and update shared memory accordingly. - From now on when shared memory is updated with a device command, dev handler will send
DEVICE_WRITE
messages to write to the appropriate parameters. - From now on whenever dev handler receives
LOG
messages, it sends them to the runtime logger to be outputted tostdout
and/or Dawn.
Delimiter | Cobs Length | Cobs-encoded Message | |
---|---|---|---|
Size | One Byte | One byte | Cobs Length Bytes |
-
Delimiter: A
0x00
byte indicating the start of a message The listener will be constantly reading the byte stream, and if it sees the delimiter, it knows that a message is coming in. -
Cobs Length: The number of bytes in Cobs-encoded Message.
The listener reads this byte after reading the delimiter, knowing to read exactly Cobs Length bytes to get the Cobs-encoded Message -
Cobs-encoded Message: A message (see below) that has been cobs-encoded, which is an encoding scheme that eliminates all
0x00
bytes in the original message.
The listener can cobs-decode this message to get the original message
After reading the cobs-encoded message in a packet, the listener will cobs-decode it to get a message of this form:
Message Type | Payload Length | Payload | Checksum | |
---|---|---|---|---|
Size | One Byte | One Byte | Payload Length Bytes | One Byte |
-
Message Type: A number indicating the type of message this is (see below for message types).
The listener uses this to know how to interpret the payload. - Payload Length: Indicates how many bytes to read to get the payload.
- Payload: The core of the message--it is the data being sent over. The payload's anatomy differs based on the receive Message Type (see below).
-
Checksum: A byte used to tell whether or not the message was corrupted while sent over serial.
The speaker computes the checksum by bitwise XOR-ing all the bytes in Message Type, Payload Length, and Payload and appends it to the end of the message.
The listener reads the speaker's recomputed checksum and computes the checksum himself. If the listener's checksum and the speaker's checksum differ, then the listener knows that the message is corrupted and should be dropped.
There are 6 types of messages that are sent between the Raspberry Pi and the Arduino devices. The message type determines how to build/interpret the payload. For each message type below, we describe the purpose of each message and the anatomy of the corresponding payload.
A ping is a message with no payload. It is sent by the speaker to the listener to say "I'm still on"
Direction: Dev handler --> Lowcar
Payload Length: 0
Payload:
None | |
---|---|
Size | 0 |
A one-time message sent by a lowcar device to dev handler, containing information uniquely identifying the device. It is sent by the lowcar device when it receives its very first PING
. The device is "disabled" until it sends an ACK
.
Direction: Lowcar --> Dev handler
Payload Length: 10 Bytes
Payload:
Device Type | Device Year | UID | |
---|---|---|---|
Size | One Byte | One Byte | 8 Bytes |
-
Device Type: A number indicating what type of device the speaker is (ex:
0x00
for LimitSwitch) -
Device Year: A number indicating what PiE year the lowcar device is from
It is hardcoded into the lowcar device when it is flashed, and is used by the student to verify they have the most recent devices. - UID: Also hardcoded into the device when flashed. All devices should have a unique UID. The students use this directly in their code to refer to a specific device.
The lowcar device continuously sends DEVICE_DATA
messages. It contains the current values of all of its readable parameters.
Direction: Lowcar --> Dev handler
Payload Length: Variable
Payload:
Parameter Bitmap | Values | |
---|---|---|
Size | 32 Bits | Variable |
- Parameter Bitmap: It tells dev handler which (readable) parameters we are sending.
-
Values: A variable-length "chunk" of the payload with the actual values being read. Only the parameters turned "on" in parameter bitmap will be included in values, and vice-versa.
Let's say a lowcar device has only two readable parameters with indices 0 and 2 of types INT
and BOOL
, respectively.
- The parameter bitmap will be
0b0101
(bits 4 through 31 are zeroes)
- Let's say the respective values are
7
andTrue
The values will besizeof(INT) + sizeof(BOOL)
bytes long, containing,7
and1
with no separator between each individual value.
A message sent to the device to write to specified parameters (ex: writing 0.5
to duty_cycle
to move motors forward at 50% speed). A DEVICE_WRITE
message is capable of writing to all writeable parameters at once, and the payload length depends on how many parameters are being written to.
The structure of this payload is exactly like a DEVICE_DATA
message, except this is used by dev handler to write to a lowcar device, while a DEVICE_DATA
message is a lowcar device reading data to dev handler.
Direction: Dev handler --> lowcar
Payload Length: Variable
Payload:
Parameter Bitmap | Values | |
---|---|---|
Size | 32 Bits | Variable |
- Parameter Bitmap: It tells the lowcar device which (writable) parameters we will be writing to.
-
Values: A variable-length "chunk" of the payload with the actual values to write. Only the parameters turned "on" in parameter bitmap will be included in values, and vice-versa.
Let's write to 3 parameters with indices 2, 5, and 7 which are types INT
, FLOAT
, and BOOL
, respectively.
- The parameter bitmap will be
0b1010 0100
(bits 8 through 31 are zeroes)
- Let's write
7
,3.14
, andTrue
to the respective parameters.
The values will besizeof(INT) + sizeof(FLOAT) + sizeof(BOOL)
bytes long, containing,7
,3.14
, and1
with no separator between each individual value.
A message sent to dev handler (which will be sent to the runtime logger) from the lowcar device. It carries a string invoked by lowcar_printf()
in the lowcar code.
This message is used as a reliable way to print messages from the lowcar code to debug.
Direction: Lowcar --> Dev handler
Payload Length: Variable
Payload:
Message String | |
---|---|
Size | Variable |
- Important
- Advanced/Specific