Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | List of all members
RH_Serial Class Reference

Driver to send and receive unaddressed, unreliable datagrams via a serial connection. More...

#include <RH_Serial.h>

Inheritance diagram for RH_Serial:

Public Member Functions

 RH_Serial (HardwareSerial &serial)
HardwareSerial & serial ()
virtual bool init ()
virtual bool available ()
virtual void waitAvailable ()
virtual bool waitAvailableTimeout (uint16_t timeout)
virtual bool recv (uint8_t *buf, uint8_t *len)
virtual bool send (const uint8_t *data, uint8_t len)
virtual uint8_t maxMessageLength ()
- Public Member Functions inherited from RHGenericDriver
 RHGenericDriver ()
virtual bool waitPacketSent ()
virtual bool waitPacketSent (uint16_t timeout)
virtual bool waitCAD ()
void setCADTimeout (unsigned long cad_timeout)
virtual bool isChannelActive ()
virtual void setThisAddress (uint8_t thisAddress)
virtual void setHeaderTo (uint8_t to)
virtual void setHeaderFrom (uint8_t from)
virtual void setHeaderId (uint8_t id)
virtual void setHeaderFlags (uint8_t set, uint8_t clear=RH_FLAGS_APPLICATION_SPECIFIC)
virtual void setPromiscuous (bool promiscuous)
virtual uint8_t headerTo ()
virtual uint8_t headerFrom ()
virtual uint8_t headerId ()
virtual uint8_t headerFlags ()
int16_t lastRssi ()
RHMode mode ()
void setMode (RHMode mode)
 Sets the operating mode of the transport.
virtual bool sleep ()
virtual uint16_t rxBad ()
virtual uint16_t rxGood ()
virtual uint16_t txGood ()

Protected Types

enum  RxState {
  RxStateInitialising = 0, RxStateIdle, RxStateDLE, RxStateData,
  RxStateEscape, RxStateWaitFCS1, RxStateWaitFCS2
 Defines different receiver states in teh receiver state machine. More...

Protected Member Functions

void handleRx (uint8_t ch)
void clearRxBuf ()
 Empties the Rx buffer.
void appendRxBuf (uint8_t ch)
 Adds a charater to the Rx buffer.
void validateRxBuf ()
void txData (uint8_t ch)

Protected Attributes

HardwareSerial & _serial
 Reference to the HardwareSerial port we will use.
RxState _rxState
 The current state of the Rx state machine.
uint16_t _rxFcs
 Progressive FCS calc (CCITT CRC-16 covering all received data (but not stuffed DLEs), plus trailing DLE, ETX)
uint16_t _rxRecdFcs
 The received FCS at the end of the current message.
 The Rx buffer.
uint8_t _rxBufLen
 Current length of data in the Rx buffer.
bool _rxBufValid
 True if the data in the Rx buffer is value and uncorrupted and complete message is available for collection.
uint16_t _txFcs
 FCS for transmitted data.
- Protected Attributes inherited from RHGenericDriver
volatile RHMode _mode
 The current transport operating mode.
uint8_t _thisAddress
 This node id.
bool _promiscuous
 Whether the transport is in promiscuous mode.
volatile uint8_t _rxHeaderTo
 TO header in the last received mesasge.
volatile uint8_t _rxHeaderFrom
 FROM header in the last received mesasge.
volatile uint8_t _rxHeaderId
 ID header in the last received mesasge.
volatile uint8_t _rxHeaderFlags
 FLAGS header in the last received mesasge.
uint8_t _txHeaderTo
 TO header to send in all messages.
uint8_t _txHeaderFrom
 FROM header to send in all messages.
uint8_t _txHeaderId
 ID header to send in all messages.
uint8_t _txHeaderFlags
 FLAGS header to send in all messages.
volatile int16_t _lastRssi
 The value of the last received RSSI value, in some transport specific units.
volatile uint16_t _rxBad
 Count of the number of bad messages (eg bad checksum etc) received.
volatile uint16_t _rxGood
 Count of the number of successfully transmitted messaged.
volatile uint16_t _txGood
 Count of the number of bad messages (correct checksum etc) received.
volatile bool _cad
 Channel activity detected.
unsigned int _cad_timeout
 Channel activity timeout in ms.

Additional Inherited Members

- Public Types inherited from RHGenericDriver
enum  RHMode {
  RHModeInitialising = 0, RHModeSleep, RHModeIdle, RHModeTx,
  RHModeRx, RHModeCad
 Defines different operating modes for the transport hardware. More...
- Static Public Member Functions inherited from RHGenericDriver
static void printBuffer (const char *prompt, const uint8_t *buf, uint8_t len)

Detailed Description

Driver to send and receive unaddressed, unreliable datagrams via a serial connection.

This class sends and received packetized messages over a serial connection. It can be used for point-to-point or multidrop, RS232, RS488 or other serial connections as supported by your controller hardware. It can also be used to communicate via radios with serial interfaces such as:

Compiles and runs on Linux, OSX and all the microprocessers and MCUs suported by radiohead. On Linux and OSX, a RadioHead specific version of HardwareSerial (in RHutil/HardwareSerial.*) encapsulates access to any serial port (or suported USB-serial converter)

The packetised messages include message encapsulation, headers, a message payload and a checksum. It therefore can support robust binary message passing with error-detection and retransmission when used with the appropriate manager. This allows reliable serial communicaitons even over very long lines where noise might otherwise affect reliablity of the communications.

Packet Format

All messages sent and received by this RH_Serial Driver conform to this packet format:

TO Header (1 octet)
FROM Header (1 octet)
ID Header (1 octet)
FLAGS Header (1 octet)
Message payload (0 to 60 octets)
Frame Check Sequence FCS CCITT CRC-16 (2 octets)

If any of octets from TO header through to the end of the payload are a DLE, then they are preceded by a DLE (ie DLE stuffing). The FCS covers everything from the TO header to the ETX inclusive, but not any stuffed DLEs

Physical connection

The physical connection to your serial port will depend on the type of platform you are on.

For example, many arduinos only support a single Serial port on pins 0 and 1, which is shared with the USB host connections. On such Arduinos, it is not possible to use both RH_Serial on the Serial port as well as using the Serial port for debugand other printing or communications.

On Arduino Mega and Due, there are 4 serial ports:

On Uno32, there are 2 serial ports:

On Maple and Flymaple, there are 4 serial ports:

On Linux and OSX there can be any number of serial ports.

Note that it is necessary for you to select which Serial port your RF_Serial will use and pass it to the contructor. On Linux you must pass an instance of HardwareSerial.


You can test this class and the RHReliableDatagram manager on Unix and OSX with back-to-back connected FTDI USB-serial adapters. Back-to-back means the TX of one is connected to the RX of the other and vice-versa. You should also join the ground pins.

Assume the 2 USB-serial adapters are connected by USB and have been assigned device names: /dev/ttyUSB0 and /dev/ttyUSB1. Build the example RHReliableDatagram client and server programs:

tools/simBuild examples/serial/serial_reliable_datagram_server/serial_reliable_datagram_server.pde
tools/simBuild examples/serial/serial_reliable_datagram_client/serial_reliable_datagram_client.pde

In one window run the server, specifying the device to use as an environment variable:

RH_HARDWARESERIAL_DEVICE_NAME=/dev/ttyUSB1 ./serial_reliable_datagram_server

And in another window run the client, specifying the other device to use as an environment variable:

RH_HARDWARESERIAL_DEVICE_NAME=/dev/ttyUSB0 ./serial_reliable_datagram_client

You should see the 2 programs passing messages to each other.

Member Enumeration Documentation

◆ RxState

enum RH_Serial::RxState

Defines different receiver states in teh receiver state machine.


Before init() is called.


Waiting for an STX.


Waiting for the DLE after STX.


Receiving data.


Got a DLE while receiving data.


Got DLE ETX, waiting for first FCS octet.


Waiting for second FCS octet.

Constructor & Destructor Documentation

◆ RH_Serial()

RH_Serial::RH_Serial ( HardwareSerial &  serial)


[in]serialReference to the HardwareSerial port which will be used by this instance. On Unix and OSX, this is an instance of RHutil/HardwareSerial. On Arduino and other, it is an instance of the built in HardwareSerial class.

Member Function Documentation

◆ available()

bool RH_Serial::available ( )

Tests whether a new message is available This can be called multiple times in a timeout loop.

true if a new, complete, error-free uncollected message is available to be retreived by recv()

Implements RHGenericDriver.

References _rxBufValid, _serial, and handleRx().

Referenced by recv(), waitAvailable(), and waitAvailableTimeout().

◆ handleRx()

void RH_Serial::handleRx ( uint8_t  ch)

HAndle a character received from the serial port. IMplements the receiver state machine

References _rxFcs, _rxRecdFcs, _rxState, appendRxBuf(), clearRxBuf(), RxStateData, RxStateDLE, RxStateEscape, RxStateIdle, RxStateWaitFCS1, RxStateWaitFCS2, and validateRxBuf().

Referenced by available().

◆ init()

bool RH_Serial::init ( )

Initialise the Driver transport hardware and software. Make sure the Driver is properly configured before calling init().

true if initialisation succeeded.

Reimplemented from RHGenericDriver.

References _rxState, RHGenericDriver::init(), and RxStateIdle.

◆ maxMessageLength()

uint8_t RH_Serial::maxMessageLength ( )

Returns the maximum message length available in this Driver.

The maximum legal message length

Implements RHGenericDriver.

◆ recv()

bool RH_Serial::recv ( uint8_t *  buf,
uint8_t *  len 

If there is a valid message available, copy it to buf and return true else return false. If a message is copied, *len is set to the length (Caution, 0 length messages are permitted). You should be sure to call this function frequently enough to not miss any messages It is recommended that you call it in your main loop.

[in]bufLocation to copy the received message
[in,out]lenPointer to available space in buf. Set to the actual number of octets copied.
true if a valid message was copied to buf

Implements RHGenericDriver.

References _rxBuf, _rxBufLen, available(), and clearRxBuf().

◆ send()

bool RH_Serial::send ( const uint8_t *  data,
uint8_t  len 

Waits until any previous transmit packet is finished being transmitted with waitPacketSent(). Then loads a message into the transmitter and starts the transmitter. Note that a message length of 0 is NOT permitted.

[in]dataArray of data to be sent
[in]lenNumber of bytes of data to send (> 0)
true if the message length was valid and it was correctly queued for transmit

Implements RHGenericDriver.

References _serial, _txFcs, RHGenericDriver::_txHeaderFlags, RHGenericDriver::_txHeaderFrom, RHGenericDriver::_txHeaderId, RHGenericDriver::_txHeaderTo, txData(), and RHGenericDriver::waitCAD().

◆ serial()

HardwareSerial & RH_Serial::serial ( )

Return the HardwareSerial port in use by this instance

The current HardwareSerial as a reference

References _serial.

◆ txData()

void RH_Serial::txData ( uint8_t  ch)

Sends a single data octet to the serial port. Implements DLE stuffing and keeps track of the senders FCS

References _serial, and _txFcs.

Referenced by send().

◆ validateRxBuf()

void RH_Serial::validateRxBuf ( )

Checks whether the Rx buffer contains valid data that is complete and uncorrupted Check the FCS, the TO address, and extracts the headers

References RHGenericDriver::_promiscuous, RHGenericDriver::_rxBad, _rxBuf, _rxBufValid, _rxFcs, RHGenericDriver::_rxGood, RHGenericDriver::_rxHeaderFlags, RHGenericDriver::_rxHeaderFrom, RHGenericDriver::_rxHeaderId, RHGenericDriver::_rxHeaderTo, _rxRecdFcs, and RHGenericDriver::_thisAddress.

Referenced by handleRx().

◆ waitAvailable()

void RH_Serial::waitAvailable ( )

Wait until a new message is available from the driver. Blocks until a complete message is received as reported by available()

Reimplemented from RHGenericDriver.

References _serial, available(), and RHGenericDriver::waitAvailable().

◆ waitAvailableTimeout()

bool RH_Serial::waitAvailableTimeout ( uint16_t  timeout)

Wait until a new message is available from the driver or the timeout expires. Blocks until a complete message is received as reported by available() or the timeout expires.

[in]timeoutThe maximum time to wait in milliseconds
true if a message is available as reported by available(), false on timeout.

Reimplemented from RHGenericDriver.

References _serial, available(), and RHGenericDriver::waitAvailableTimeout().

The documentation for this class was generated from the following files: