RadioHead
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:
RHGenericDriver

Public Member Functions

 RH_Serial (HardwareSerial &serial)
 
HardwareSerial & serial ()
 
virtual bool init ()
 
virtual bool available ()
 
virtual void waitAvailable (uint16_t polldelay=0)
 
virtual bool waitAvailableTimeout (uint16_t timeout, uint16_t polldelay=0)
 
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 ()
 Constructor.
 
virtual ~RHGenericDriver ()
 Generic destructor to prevent warnings when objects are dynamically allocated.
 
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 ()
 
virtual int16_t lastRssi ()
 
virtual RHMode mode ()
 
virtual 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.
 
uint8_t _rxBuf [RH_SERIAL_MAX_PAYLOAD_LEN]
 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:

DLE
STX
TO Header (1 octet)
FROM Header (1 octet)
ID Header (1 octet)
FLAGS Header (1 octet)
Message payload (0 to 60 octets)
DLE
ETX
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.

On STM32 F4 Discovery with Arduino and Arduino_STM32, there are 4 serial ports. We had success with port 2 (TX on pin PA2 and RX on pin PA3) and initialising the driver like this: RH_Serial driver(Serial2);

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.

Testing

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.ino
tools/simBuild examples/serial/serial_reliable_datagram_client/serial_reliable_datagram_client.ino
HardwareSerial & serial()

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
protected

Defines different receiver states in teh receiver state machine.

Enumerator
RxStateInitialising 

Before init() is called.

RxStateIdle 

Waiting for an STX.

RxStateDLE 

Waiting for the DLE after STX.

RxStateData 

Receiving data.

RxStateEscape 

Got a DLE while receiving data.

RxStateWaitFCS1 

Got DLE ETX, waiting for first FCS octet.

RxStateWaitFCS2 

Waiting for second FCS octet.

Constructor & Destructor Documentation

◆ RH_Serial()

RH_Serial::RH_Serial ( HardwareSerial &  serial)

Constructor

Parameters
[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()

virtual bool RH_Serial::available ( )
virtual

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

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

Implements RHGenericDriver.

◆ handleRx()

void RH_Serial::handleRx ( uint8_t  ch)
protected

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

◆ init()

virtual bool RH_Serial::init ( )
virtual

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

Returns
true if initialisation succeeded.

Reimplemented from RHGenericDriver.

◆ maxMessageLength()

virtual uint8_t RH_Serial::maxMessageLength ( )
virtual

Returns the maximum message length available in this Driver.

Returns
The maximum legal message length

Implements RHGenericDriver.

◆ recv()

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

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.

Parameters
[in]bufLocation to copy the received message
[in,out]lenPointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
Returns
true if a valid message was copied to buf

Implements RHGenericDriver.

◆ send()

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

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.

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

Implements RHGenericDriver.

◆ serial()

HardwareSerial & RH_Serial::serial ( )

Return the HardwareSerial port in use by this instance

Returns
The current HardwareSerial as a reference

◆ txData()

void RH_Serial::txData ( uint8_t  ch)
protected

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

◆ validateRxBuf()

void RH_Serial::validateRxBuf ( )
protected

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

◆ waitAvailable()

virtual void RH_Serial::waitAvailable ( uint16_t  polldelay = 0)
virtual

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

Parameters
[in]polldelayTime between polling available() in milliseconds. This can be useful in multitaking environment like Linux to prevent waitAvailableTimeout using all the CPU while polling for receiver activity

Reimplemented from RHGenericDriver.

◆ waitAvailableTimeout()

virtual bool RH_Serial::waitAvailableTimeout ( uint16_t  timeout,
uint16_t  polldelay = 0 
)
virtual

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.

Parameters
[in]timeoutThe maximum time to wait in milliseconds
[in]polldelayTime between polling available() in milliseconds. This can be useful in multitaking environment like Linux to prevent waitAvailableTimeout using all the CPU while polling for receiver activity
Returns
true if a message is available as reported by available(), false on timeout.

Reimplemented from RHGenericDriver.


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