PacketSerial
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
|
First, it might be worth it to read the background introduction.
This project can be installed using the Arduino IDE. Navigate to the Tools > Manage Libraries ... menu item and search for PacketSerial
.
Alternatively, this library can be downloaded or cloned from github and to your Arduino libraries
folder.
PacketSerial
class wraps the Arduino Stream
class to automatically encode and decode byte packets that are sent and received. Typically serial communication uses the default Serial
object, which implements the Stream
class. In most cases, PacketSerial
should be given exclusive access to the serial Stream
(e.g. for a default setup using Serial
, users should avoid calling functions like Serial.print()
, Serial.write()
, etc directly). Data should be sent via the send(const uint8_t* buffer, size_t size) const
method and received in a PacketSerial
callback function (see below).
To use the default Serial
object and the default communication settings (usually SERIAL_8N1
), set up PacketSerial
like this:
For a non-default Serial connection, a class implementing the Stream
interface should be configured and then set for the PacketSerial
instance.
Any class that correctly implements the Stream
interface should work, which includes some network communication objects.
In order to processing incoming serial packets, the user must call the update()
method at the end of the loop()
method.
All packets are received via handler functions. A typical handler function would be registered in the void setup()
function like:
The onPacketReceived
function can take two forms. The simplest looks like this:
For more advanced programs with multiple PacketSerial instances and a shared handler, it may be useful to know which PacketSerial instance received the packet. In this case you could define a callback like this:
Finally, it is also possible to set arbitrary packet handlers that point to member functions of a given class instance using lambda functions. For example:
To send packets call the send()
method. The send method will take a packet (an array of bytes), encode it, transmit it and send the packet boundary marker. To send the values 255
and 10
, one might do the following:
On boards with multiple serial ports, this strategy can also be used to set up two Serial streams, one for packets and one for debug ASCII (see this discussion for more).
In some cases the receive buffer may not be large enough for an incoming encoded packet.
To check for overflows, call the receiveBufferOverflowed()
method after calling update()
.
For example:
The state of the overflow flag is reset every time a new packet marker is detected, NOT when the overflow()
method is called.
The PacketSerial_
class is a templated class that allows us to statically set the encoder type, packet marker and buffer size at compile time.
The the template parameters are as follows:
The PacketMarker
has a default of 0
while the BufferSize
has a default of 256
bytes.
Thus, if you define your class as:
You will use the COBS
encoder type and a default PacketMarker of 0
and buffer size of 256
.
Currently there are three default PacketSerial_
types defined via typedef
for convenience:
To use a custom encoding type, the EncoderType
class must implement the following functions:
See the Encoding/COBS.h
and Encoding/SLIP.h
for examples and further documentation.
For example, to increase the buffer size for a standard COBS
encoder to 512, one can defined the templated class like this:
This uses the COBS encoder type, a PacketMarker of 0 and a buffer size of 512.
Likewise, a custom SLIP
encoder with a buffer size of 512 bytes would be defined like this: