RadioHead
RH_E32.h
1// RH_E32.h
2//
3// Definitions for E32-TTL-1W family serial radios:
4// http://www.cdebyte.com/en/product-view-news.aspx?id=108
5//
6// Author: Mike McCauley (mikem@airspayce.com)
7// Copyright (C) 2017 Mike McCauley
8// $Id: RH_E32.h,v 1.5 2020/04/09 23:40:34 mikem Exp $
9//
10
11#ifndef RH_E32_h
12#define RH_E32_h
13
14#include <RHGenericDriver.h>
15#include <Stream.h>
16
17// The buffer in the E32 is 512 bytes, but we arbitrarily limit messages to a maximum of 58 octets
18// We use some for headers, keeping fewer for RadioHead messages
19// The E32 sends messages longer than 58 octets in several packets of 58 octets each, and since we dont have any
20// framing or message level checksums there is a risk that long messages from 2 different sources
21// could be incorrectly interpreted as a single message
22#define RH_E32_MAX_PAYLOAD_LEN 58
23
24// The length of the headers we add:
25// message length (including these headers)
26// to
27// from
28// id
29// flags
30// The headers are inside the E32 payload
31#define RH_E32_HEADER_LEN 5
32
33// This is the maximum RadioHead user message length that can be supported by this module. Limited by
34#define RH_E32_MAX_MESSAGE_LEN (RH_E32_MAX_PAYLOAD_LEN-RH_E32_HEADER_LEN)
35
36// Commands to alter module behaviour
37#define RH_E32_COMMAND_WRITE_PARAMS_SAVE 0xC0
38#define RH_E32_COMMAND_READ_PARAMS 0xC1
39#define RH_E32_COMMAND_WRITE_PARAMS_NOSAVE 0xC2
40#define RH_E32_COMMAND_READ_VERSION 0xC3
41#define RH_E32_COMMAND_RESET 0xC4
42
43// Various flags and masks for param bytes
44#define RH_E32_PARAM_SPED_UART_MODE_MASK 0xC0
45#define RH_E32_PARAM_SPED_UART_MODE_8N1 0x00
46#define RH_E32_PARAM_SPED_UART_MODE_8O1 0x40
47#define RH_E32_PARAM_SPED_UART_MODE_8E1 0x80
48
49#define RH_E32_PARAM_SPED_UART_BAUD_MASK 0x38
50#define RH_E32_PARAM_SPED_UART_BAUD_1200 0x00
51#define RH_E32_PARAM_SPED_UART_BAUD_2400 0x08
52#define RH_E32_PARAM_SPED_UART_BAUD_4800 0x10
53#define RH_E32_PARAM_SPED_UART_BAUD_9600 0x18
54#define RH_E32_PARAM_SPED_UART_BAUD_19200 0x20
55#define RH_E32_PARAM_SPED_UART_BAUD_38400 0x28
56#define RH_E32_PARAM_SPED_UART_BAUD_57600 0x30
57#define RH_E32_PARAM_SPED_UART_BAUD_115200 0x38
58
59#define RH_E32_PARAM_SPED_DATARATE_MASK 0x07
60#define RH_E32_PARAM_SPED_DATARATE_1KBPS 0x00
61#define RH_E32_PARAM_SPED_DATARATE_2KBPS 0x01
62#define RH_E32_PARAM_SPED_DATARATE_5KBPS 0x02
63#define RH_E32_PARAM_SPED_DATARATE_8KBPS 0x03
64#define RH_E32_PARAM_SPED_DATARATE_10KBPS 0x04
65#define RH_E32_PARAM_SPED_DATARATE_15KBPS 0x05
66#define RH_E32_PARAM_SPED_DATARATE_20KBPS 0x06
67#define RH_E32_PARAM_SPED_DATARATE_25KBPS 0x07
68
69#define RH_E32_PARAM_OPTION_FIXED_MASK 0x80
70
71#define RH_E32_PARAM_OPTION_IODRIVE_MASK 0x40
72
73#define RH_E32_PARAM_OPTION_WAKEUP_TIME_MASK 0x38
74#define RH_E32_PARAM_OPTION_WAKEUP_TIME_250MS 0x00
75#define RH_E32_PARAM_OPTION_WAKEUP_TIME_500MS 0x08
76#define RH_E32_PARAM_OPTION_WAKEUP_TIME_750MS 0x10
77#define RH_E32_PARAM_OPTION_WAKEUP_TIME_1000MS 0x18
78#define RH_E32_PARAM_OPTION_WAKEUP_TIME_1250MS 0x20
79#define RH_E32_PARAM_OPTION_WAKEUP_TIME_1500MS 0x28
80#define RH_E32_PARAM_OPTION_WAKEUP_TIME_1750MS 0x30
81#define RH_E32_PARAM_OPTION_WAKEUP_TIME_2000MS 0x38
82
83#define RH_E32_PARAM_OPTION_FEC_MASK 0x04
84
85#define RH_E32_PARAM_OPTION_POWER_MASK 0x03
86#define RH_E32_PARAM_OPTION_POWER_30DBM 0x00
87#define RH_E32_PARAM_OPTION_POWER_27DBM 0x01
88#define RH_E32_PARAM_OPTION_POWER_24DBM 0x02
89#define RH_E32_PARAM_OPTION_POWER_21DBM 0x03
90
91/////////////////////////////////////////////////////////////////////
92/// \class RH_E32 RH_E32.h <RH_E32.h>
93/// \brief Driver to send and receive unaddressed, unreliable datagrams via a EBYTE E32-TTL-1W
94/// and similar serial radio transceiver.
95///
96/// Works with
97/// E32-TTL-1W
98///
99/// Note: it should also be possible to use the E32-TTL-1W with the RadioHead RH_Serial module,
100/// which will also you to send longer packets, but will require you to use the EBYTE Wireless Module Setting program
101/// to configure the radio first. In this arrangement the E32 would act as a transparent serial connection.
102/// This has not been tested by us.
103///
104/// \par Overview
105///
106/// This class provides basic functions for sending and receiving unaddressed,
107/// unreliable datagrams of arbitrary length to 53 octets per packet.
108///
109/// Manager classes may use this class to implement reliable, addressed datagrams and streams,
110/// mesh routers, repeaters, translators etc.
111///
112/// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
113/// modulation scheme.
114///
115/// This Driver provides an object-oriented interface for sending and receiving data messages with EBYTE
116/// RFM95/96/97/98(W), Semtech SX1276/77/78/7E32-TTL-1W9 and compatible radio modules. These modules implement
117/// long range LORA transcivers with a transparent serial interface. With 1W power output the manufacturer
118/// claims up to 6km range.
119///
120/// This Driver provides functions for sending and receiving messages of up
121/// to 53 octets on any frequency supported by the radio, in a range of
122/// data rates and power outputs. Frequency can be set with
123/// 1MHz precision to any frequency from 410 to 441MHz.
124///
125/// You can use either a hardware or software serial connection.
126///
127/// Tested with Arduino Uno and software serial.
128///
129/// \par Packet Format
130///
131/// All messages sent and received by this Driver conform to this packet format:
132///
133/// - 5 octets HEADER: (LENGTH, TO, FROM, ID, FLAGS)
134/// - 0 to 53 octets DATA
135///
136/// \par Connecting E32-TTL-1W to Arduino
137///
138/// We tested with Arduino Uno. We used SoftwareSerial on pins 6 and 7) to connect to the E32 module, so
139/// we could continue to use the only hardware serial port for debugging
140/// \code
141/// Arduino E32
142/// GND----------GND (ground in)
143/// 5V-----------VCC (5V in)
144/// pin D4-----------M0 (mode control pin input to radio)
145/// pin D5-----------M1 (mode control pin input to radio)
146/// pin D6-----------RXD (serial data input from Arduino to radio)
147/// pin D7-----------TXD (serial data output from radio to Arduino)
148/// pin D8-----------AUX (Aux pin output from radio to Arduino)
149/// \endcode
150/// With this connection, you can initialise the serial port and RH_E32 like this:
151/// \code
152/// SoftwareSerial mySerial(7, 6);
153/// RH_E32 driver(&mySerial, 4, 5, 8);
154/// \endcode
155///
156/// For Adafruit M0 Feather:
157/// \code
158/// Feather E32
159/// GND----------GND (ground in)
160/// 3V-----------VCC (3.3V in)
161/// pin D5-----------M0 (mode control pin input to radio)
162/// pin D6-----------M1 (mode control pin input to radio)
163/// pin D1/Tx--------RXD (serial data input from M0 to radio)
164/// pin D0/Rx--------TXD (serial data output from radio to M0)
165/// pin D9-----------AUX (Aux pin output from radio to M0)
166/// \endcode
167/// With this connection, you can initialise serial port 1 and RH_E32 like this:
168/// \code
169/// RH_E32 driver(&Serial1, 5, 6, 9);
170/// \endcode
171/// Other connection schems are possible provided the approporiate constructors are used for SoftwareSerial and RH_E32
172///
173/// \par Memory
174///
175/// The RH_RF95 driver requires non-trivial amounts of memory. The sample
176/// programs all compile to about 8kbytes each, which will fit in the
177/// flash proram memory of most Arduinos. However, the RAM requirements are
178/// more critical. Therefore, you should be vary sparing with RAM use in
179/// programs that use the RH_E32 driver.
180///
181/// It is often hard to accurately identify when you are hitting RAM limits on Arduino.
182/// The symptoms can include:
183/// - Mysterious crashes and restarts
184/// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
185/// - Hanging
186/// - Output from Serial.print() not appearing
187///
188/// \par Performance
189///
190/// This radio supports a range of different data rates and powers.
191/// The lowest speeds are the most reliable, however you should note that at 1kbps and with an 13 octet payload,
192/// the transmission time for one packet approaches 5 seconds. Therefore you should be cautious about trying to
193/// send too many or too long messages per unit of time, lest you monopolise the airwaves.
194/// Be a good neighbour and use the lowest power and fastest speed that you can.
195///
196/// Forward Error Correction (FEC) is always enabled in these radios by RH_E32.
197///
198/// \par Range
199///
200/// When running with a power output of 1W and at the slowest speed of 1kbps, this module has an impressive range.
201/// We tested with:
202/// E32-TTL-1W (1 W power, 1kbps data rate)
203/// Single wire antenna with a small meta ground plane at about 1m above ground level
204/// Arduino Uno
205/// RadioHead RH_E32 module with e32_client and e32_server sketches
206/// Packet length 13 octets (total payload 18 octets)
207/// (and yes, we have an appropriate radio license for that power output)
208///
209/// We were able to get reliable reception over 7km (6 km over ocean and 1 km through low rise residential area)
210///
211/// You can expect less range with lower power outputs and faster speeds.
212/// You can expect less range in highrise cities.
213/// You can expect more range with directional antennas.
214/// You can expect more range with shorter messages.
215///
216/// \par Transmitter Power
217/// TBA
218///
219/// Caution: the maximum power output of this radio (1W = 30dbM) is almost certainly more than the
220/// permitted power level for unlicensed users in the ISM bands in most countries. Be sure you comply with your local
221/// regulations. Be a good neighbour and use the lowest power and fastest speed that you can.
222///
224{
225 public:
226
227 /// \brief Values to be passed to setDataRate() to control the on-air data rate
228 ///
229 /// This is NOT to be used to control the baud rate of the serial connection to the radio
230 typedef enum
231 {
232 DataRate1kbps = RH_E32_PARAM_SPED_DATARATE_1KBPS,
233 DataRate2kbps = RH_E32_PARAM_SPED_DATARATE_2KBPS,
234 DataRate5kbps = RH_E32_PARAM_SPED_DATARATE_5KBPS,
235 DataRate8kbps = RH_E32_PARAM_SPED_DATARATE_8KBPS,
236 DataRate10kbps = RH_E32_PARAM_SPED_DATARATE_10KBPS,
237 DataRate15kbps = RH_E32_PARAM_SPED_DATARATE_15KBPS,
238 DataRate20kbps = RH_E32_PARAM_SPED_DATARATE_20KBPS,
239 DataRate25kbps = RH_E32_PARAM_SPED_DATARATE_25KBPS
240 } DataRate;
241
242 /// \brief Values to be passed to setPower() to control the transmitter power
243 ///
244 typedef enum
245 {
246 Power30dBm = RH_E32_PARAM_OPTION_POWER_30DBM,
247 Power27dBm = RH_E32_PARAM_OPTION_POWER_27DBM,
248 Power24dBm = RH_E32_PARAM_OPTION_POWER_24DBM,
249 Power21dBm = RH_E32_PARAM_OPTION_POWER_21DBM,
250 } PowerLevel;
251
252 /// \brief Values to be passed to setBaudRate() to control the radio serial connection baud rate
253 ///
254 /// This is NOT to be used to control the on-air data rate the radio transmits and receives at
255 typedef enum
256 {
257 BaudRate1200 = RH_E32_PARAM_SPED_UART_BAUD_1200,
258 BaudRate2400 = RH_E32_PARAM_SPED_UART_BAUD_2400,
259 BaudRate4800 = RH_E32_PARAM_SPED_UART_BAUD_4800,
260 BaudRate9600 = RH_E32_PARAM_SPED_UART_BAUD_9600,
261 BaudRate19200 = RH_E32_PARAM_SPED_UART_BAUD_19200,
262 BaudRate38400 = RH_E32_PARAM_SPED_UART_BAUD_38400,
263 BaudRate57600 = RH_E32_PARAM_SPED_UART_BAUD_57600,
264 BaudRate115200 = RH_E32_PARAM_SPED_UART_BAUD_115200,
265 } BaudRate;
266
267 /// \brief Values to be passed to setBaudRate() to control the parity of the serial connection to the radio
268 typedef enum
269 {
270 Parity8N1 = RH_E32_PARAM_SPED_UART_MODE_8N1,
271 Parity8O1 = RH_E32_PARAM_SPED_UART_MODE_8O1,
272 Parity8E1 = RH_E32_PARAM_SPED_UART_MODE_8E1,
273 } Parity;
274
275 /// Contructor. You can have multiple instances, but each instance must have its own
276 /// serial connection, M0 M1 and AUX connections. Initialises the mode of the referenced pins
277 /// Does NOT set the baud rate of the serial connection to the radio.
278 /// \param[in] s Reference to the SoftwareSerial or HardwareSerial port used to connect to the radio
279 /// \param[in] m0_pin Pin number of the Arduino pin that connects to the radio M0 input
280 /// \param[in] m1_pin Pin number of the Arduino pin that connects to the radio M1 input
281 /// \param[in] aux_pin Pin number of the Arduino pin that connects to the radio AUX output
282 RH_E32(Stream *s=&Serial, uint8_t m0_pin = 4, uint8_t m1_pin = 5, uint8_t aux_pin = 8);
283
284 /// Initialise the Driver transport hardware and software.
285 /// Make sure the Driver is properly, including setting the serial port baud rate and parity to that
286 /// configured in the radio (typically 9600 baud, 8N1) before calling init().
287 /// Sets the module to 443MHz, 21dBm power and 5kbps data rate (you can change these after initialisation with
288 /// the various set* functions).
289 /// This function may not return if the AUX pin is not connected.
290 /// Initialisation failure can be caused by:
291 /// Electrical connections to the radio incorrect or incomplete
292 /// Radio configured to use a different baud rate to the one configured to the Ardiono serial port
293 /// Incorrect radio module connected tot he serial port.
294 /// Other serial communicaitons problems between the Arduino and the radio
295 /// \return true if initialisation succeeded.
296 bool init();
297
298 /// Tests whether a new message is available
299 /// from the Driver.
300 /// This can and should be called multiple times in a timeout loop. You should call this as frequently as possible
301 /// whenever a message might be received
302 /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv().
303 bool available();
304
305 /// If there is a valid message available, copy it to buf and return true
306 /// else return false.
307 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
308 /// You should be sure to call this function frequently enough to not miss any messages
309 /// It is recommended that you call it in your main loop.
310 /// \param[in] buf Location to copy the received message
311 /// \param[in,out] len Pointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
312 /// \return true if a valid message was copied to buf
313 bool recv(uint8_t* buf, uint8_t* len);
314
315 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
316 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
317 /// of 0 is permitted.
318 /// \param[in] data Array of data to be sent
319 /// \param[in] len Number of bytes of data to send
320 /// \return true if the message length was valid and it was correctly queued for transmit. Return false
321 /// if CAD was requested and the CAD timeout timed out before clear channel was detected.
322 bool send(const uint8_t* data, uint8_t len);
323
324 /// Returns the maximum message length
325 /// available in this Driver.
326 /// \return The maximum legal message length
328
329 /// Waits for any currently transmitting packet to be completely sent
330 /// Returns true if successful
332
333 /// Sets the on-air data rate to be used by the transmitter and receiver
334 /// \param[in] rate A valid data rate from the DataRate enum
335 /// \return true if successful
337
338 /// Sets the transmitter power output
339 /// \param[in] level A valid power setting from the Power enum
340 /// \return true if successful
341 bool setPower(PowerLevel level);
342
343 /// Sets the radio serial port baud rate and parity (not the on-air data rate)
344 /// Does not set the Aruino rate or parity: you wil nned to do this afterwards
345 /// \param[in] rate A valid baud rate from the BaudRate enum
346 /// \param[in] parity A valid parity from the PArity enum
347 /// \return true if successful
348 bool setBaudRate(BaudRate rate = BaudRate9600, Parity parity = Parity8N1);
349
350 /// Sets the tarnsmitter and receiver frequency.
351 /// \param[in] frequency Desired frequency in MHx from 410 to 441 MHz inclusive
352 /// \return true if successful
353 bool setFrequency(uint16_t frequency);
354
355protected:
356
357 /// \brief Defines values to be passed to setOperatinMode
358 ///
359 /// For internal driver user only
360 typedef enum
361 {
362 ModeNormal = 0, ///< Normal mode for sending and receiving messages
363 ModeWakeUp, ///< Adds a long preamble to transmission to allow destination receivers to wake up
364 ModePowerSaving, ///< Receiver sleeps until a message is received
365 ModeSleep ///< Use during parameter setting
367
368 /// \brief Structure for reading and writing radio control parameters
369 ///
370 /// For internal driver user only
371 typedef struct
372 {
373 uint8_t head; ///< 0xc2 (no save) or 0xc0 (save)
374 uint8_t addh; ///< High address byte (not used by this driver)
375 uint8_t addl; ///< Low address byte (not used by this driver)
376 uint8_t sped; ///< Data and baud rate parameters
377 uint8_t chan; ///< Radio channel
378 uint8_t option; ///< Various control options
379
380 } Parameters;
381
382 /// Sets the operating mode of the radio.
383 /// For internal use only
385
386 /// Retrieves the version number for the radio and checks that it is valid
387 /// \return true if the version could be retrieved and is radio model number is correct
389
390 /// Waits for the AUX pin to go high
391 /// For internal use only
393
394 /// Waits for the AUX pin to go low
395 /// For internal use only
397
398 /// Issues a reset command to the radio
399 /// WARNING: this seems to break reception. Why?
400 /// \return true if successful
401 bool reset();
402
403 /// Read the radio configuration parameters into
404 /// local memory
405 /// \param[in] params Reference to a Parameter structure which will be filled if successful
406 /// \return true if successful
408
409 /// Write radio configuration parameters from local memory
410 /// to the radio. You can choose whether the parameter will be saved across power down or not
411 /// \param[in] params Reference to a Parameter structure containing the radio configuration parameters
412 /// to be written to the radio.
413 /// \param[in] save If true, the parameters will be saved across power down in the radio
414 /// \return true if successful
415 bool writeParameters(Parameters& params, bool save = false);
416
417 /// Examine the receive buffer to determine whether the message is for this node
418 /// For internal use only
420
421 /// Clear our local receive buffer
422 /// For internal use only
424
425private:
426 /// Serial stream (hardware or software serial)
427 Stream* _s;
428
429 /// Pin number connected to M0
430 uint8_t _m0_pin;
431
432 /// Pin number connected to M1
433 uint8_t _m1_pin;
434
435 /// Pin number connected to AUX
436 uint8_t _aux_pin;
437
438 /// Number of octets in the buffer
439 uint8_t _bufLen;
440
441 /// The receiver/transmitter buffer
442 uint8_t _buf[RH_E32_MAX_PAYLOAD_LEN];
443
444 /// True when there is a valid message in the buffer
445 bool _rxBufValid;
446
447};
448
449/// @example e32_client.ino
450/// @example e32_server.ino
451
452#endif
453
Abstract base class for a RadioHead driver.
Definition: RHGenericDriver.h:42
virtual RHMode mode()
Definition: RHGenericDriver.cpp:165
Driver to send and receive unaddressed, unreliable datagrams via a EBYTE E32-TTL-1W and similar seria...
Definition: RH_E32.h:224
bool setDataRate(DataRate rate)
bool setBaudRate(BaudRate rate=BaudRate9600, Parity parity=Parity8N1)
bool waitPacketSent()
OperatingMode
Defines values to be passed to setOperatinMode.
Definition: RH_E32.h:361
@ ModeNormal
Normal mode for sending and receiving messages.
Definition: RH_E32.h:362
@ ModePowerSaving
Receiver sleeps until a message is received.
Definition: RH_E32.h:364
@ ModeSleep
Use during parameter setting.
Definition: RH_E32.h:365
@ ModeWakeUp
Adds a long preamble to transmission to allow destination receivers to wake up.
Definition: RH_E32.h:363
bool available()
PowerLevel
Values to be passed to setPower() to control the transmitter power.
Definition: RH_E32.h:245
void clearRxBuf()
bool setFrequency(uint16_t frequency)
void validateRxBuf()
bool readParameters(Parameters &params)
bool recv(uint8_t *buf, uint8_t *len)
Parity
Values to be passed to setBaudRate() to control the parity of the serial connection to the radio.
Definition: RH_E32.h:269
bool getVersion()
bool setPower(PowerLevel level)
void waitAuxLow()
BaudRate
Values to be passed to setBaudRate() to control the radio serial connection baud rate.
Definition: RH_E32.h:256
RH_E32(Stream *s=&Serial, uint8_t m0_pin=4, uint8_t m1_pin=5, uint8_t aux_pin=8)
bool reset()
bool writeParameters(Parameters &params, bool save=false)
void setOperatingMode(OperatingMode mode)
bool init()
DataRate
Values to be passed to setDataRate() to control the on-air data rate.
Definition: RH_E32.h:231
uint8_t maxMessageLength()
void waitAuxHigh()
bool send(const uint8_t *data, uint8_t len)
Structure for reading and writing radio control parameters.
Definition: RH_E32.h:372
uint8_t head
0xc2 (no save) or 0xc0 (save)
Definition: RH_E32.h:373
uint8_t option
Various control options.
Definition: RH_E32.h:378
uint8_t sped
Data and baud rate parameters.
Definition: RH_E32.h:376
uint8_t addl
Low address byte (not used by this driver)
Definition: RH_E32.h:375
uint8_t chan
Radio channel.
Definition: RH_E32.h:377
uint8_t addh
High address byte (not used by this driver)
Definition: RH_E32.h:374