RadioHead
Embed:
(wiki syntax)
Show/hide line numbers
RH_RF95.h
00001 // RH_RF95.h 00002 // 00003 // Definitions for HopeRF LoRa radios per: 00004 // http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf 00005 // http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf 00006 // 00007 // Author: Mike McCauley (mikem@airspayce.com) 00008 // Copyright (C) 2014 Mike McCauley 00009 // $Id: RH_RF95.h,v 1.16 2017/03/04 00:59:41 mikem Exp $ 00010 // 00011 // Ported to mbed - support only a single radio - Dan Julio - 5/2017 00012 // 00013 00014 #ifndef RH_RF95_h 00015 #define RH_RF95_h 00016 00017 #include <RHGenericDriver.h> 00018 #include "swspi.h" 00019 00020 // Max number of octets the LORA Rx/Tx FIFO can hold 00021 #define RH_RF95_FIFO_SIZE 255 00022 00023 // This is the maximum number of bytes that can be carried by the LORA. 00024 // We use some for headers, keeping fewer for RadioHead messages 00025 #define RH_RF95_MAX_PAYLOAD_LEN RH_RF95_FIFO_SIZE 00026 00027 // The length of the headers we add. 00028 // The headers are inside the LORA's payload 00029 #define RH_RF95_HEADER_LEN 4 00030 00031 // This is the maximum message length that can be supported by this driver. 00032 // Can be pre-defined to a smaller size (to save SRAM) prior to including this header 00033 // Here we allow for 1 byte message length, 4 bytes headers, user data and 2 bytes of FCS 00034 #ifndef RH_RF95_MAX_MESSAGE_LEN 00035 #define RH_RF95_MAX_MESSAGE_LEN (RH_RF95_MAX_PAYLOAD_LEN - RH_RF95_HEADER_LEN) 00036 #endif 00037 00038 // The crystal oscillator frequency of the module 00039 #define RH_RF95_FXOSC 32000000.0 00040 00041 // The Frequency Synthesizer step = RH_RF95_FXOSC / 2^^19 00042 #define RH_RF95_FSTEP (RH_RF95_FXOSC / 524288) 00043 00044 00045 // Register names (LoRa Mode, from table 85) 00046 #define RH_RF95_REG_00_FIFO 0x00 00047 #define RH_RF95_REG_01_OP_MODE 0x01 00048 #define RH_RF95_REG_02_RESERVED 0x02 00049 #define RH_RF95_REG_03_RESERVED 0x03 00050 #define RH_RF95_REG_04_RESERVED 0x04 00051 #define RH_RF95_REG_05_RESERVED 0x05 00052 #define RH_RF95_REG_06_FRF_MSB 0x06 00053 #define RH_RF95_REG_07_FRF_MID 0x07 00054 #define RH_RF95_REG_08_FRF_LSB 0x08 00055 #define RH_RF95_REG_09_PA_CONFIG 0x09 00056 #define RH_RF95_REG_0A_PA_RAMP 0x0a 00057 #define RH_RF95_REG_0B_OCP 0x0b 00058 #define RH_RF95_REG_0C_LNA 0x0c 00059 #define RH_RF95_REG_0D_FIFO_ADDR_PTR 0x0d 00060 #define RH_RF95_REG_0E_FIFO_TX_BASE_ADDR 0x0e 00061 #define RH_RF95_REG_0F_FIFO_RX_BASE_ADDR 0x0f 00062 #define RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR 0x10 00063 #define RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11 00064 #define RH_RF95_REG_12_IRQ_FLAGS 0x12 00065 #define RH_RF95_REG_13_RX_NB_BYTES 0x13 00066 #define RH_RF95_REG_14_RX_HEADER_CNT_VALUE_MSB 0x14 00067 #define RH_RF95_REG_15_RX_HEADER_CNT_VALUE_LSB 0x15 00068 #define RH_RF95_REG_16_RX_PACKET_CNT_VALUE_MSB 0x16 00069 #define RH_RF95_REG_17_RX_PACKET_CNT_VALUE_LSB 0x17 00070 #define RH_RF95_REG_18_MODEM_STAT 0x18 00071 #define RH_RF95_REG_19_PKT_SNR_VALUE 0x19 00072 #define RH_RF95_REG_1A_PKT_RSSI_VALUE 0x1a 00073 #define RH_RF95_REG_1B_RSSI_VALUE 0x1b 00074 #define RH_RF95_REG_1C_HOP_CHANNEL 0x1c 00075 #define RH_RF95_REG_1D_MODEM_CONFIG1 0x1d 00076 #define RH_RF95_REG_1E_MODEM_CONFIG2 0x1e 00077 #define RH_RF95_REG_1F_SYMB_TIMEOUT_LSB 0x1f 00078 #define RH_RF95_REG_20_PREAMBLE_MSB 0x20 00079 #define RH_RF95_REG_21_PREAMBLE_LSB 0x21 00080 #define RH_RF95_REG_22_PAYLOAD_LENGTH 0x22 00081 #define RH_RF95_REG_23_MAX_PAYLOAD_LENGTH 0x23 00082 #define RH_RF95_REG_24_HOP_PERIOD 0x24 00083 #define RH_RF95_REG_25_FIFO_RX_BYTE_ADDR 0x25 00084 #define RH_RF95_REG_26_MODEM_CONFIG3 0x26 00085 00086 #define RH_RF95_REG_27_PPM_CORRECTION 0x27 00087 #define RH_RF95_REG_28_FEI_MSB 0x28 00088 #define RH_RF95_REG_29_FEI_MID 0x29 00089 #define RH_RF95_REG_2A_FEI_LSB 0x2a 00090 #define RH_RF95_REG_2C_RSSI_WIDEBAND 0x2c 00091 #define RH_RF95_REG_31_DETECT_OPTIMIZ 0x31 00092 #define RH_RF95_REG_33_INVERT_IQ 0x33 00093 #define RH_RF95_REG_37_DETECTION_THRESHOLD 0x37 00094 #define RH_RF95_REG_39_SYNC_WORD 0x39 00095 00096 #define RH_RF95_REG_40_DIO_MAPPING1 0x40 00097 #define RH_RF95_REG_41_DIO_MAPPING2 0x41 00098 #define RH_RF95_REG_42_VERSION 0x42 00099 00100 #define RH_RF95_REG_4B_TCXO 0x4b 00101 #define RH_RF95_REG_4D_PA_DAC 0x4d 00102 #define RH_RF95_REG_5B_FORMER_TEMP 0x5b 00103 #define RH_RF95_REG_61_AGC_REF 0x61 00104 #define RH_RF95_REG_62_AGC_THRESH1 0x62 00105 #define RH_RF95_REG_63_AGC_THRESH2 0x63 00106 #define RH_RF95_REG_64_AGC_THRESH3 0x64 00107 00108 // RH_RF95_REG_01_OP_MODE 0x01 00109 #define RH_RF95_LONG_RANGE_MODE 0x80 00110 #define RH_RF95_ACCESS_SHARED_REG 0x40 00111 #define RH_RF95_LOW_FREQUENCY_MODE 0x08 00112 #define RH_RF95_MODE 0x07 00113 #define RH_RF95_MODE_SLEEP 0x00 00114 #define RH_RF95_MODE_STDBY 0x01 00115 #define RH_RF95_MODE_FSTX 0x02 00116 #define RH_RF95_MODE_TX 0x03 00117 #define RH_RF95_MODE_FSRX 0x04 00118 #define RH_RF95_MODE_RXCONTINUOUS 0x05 00119 #define RH_RF95_MODE_RXSINGLE 0x06 00120 #define RH_RF95_MODE_CAD 0x07 00121 00122 // RH_RF95_REG_09_PA_CONFIG 0x09 00123 #define RH_RF95_PA_SELECT 0x80 00124 #define RH_RF95_MAX_POWER 0x70 00125 #define RH_RF95_OUTPUT_POWER 0x0f 00126 00127 // RH_RF95_REG_0A_PA_RAMP 0x0a 00128 #define RH_RF95_LOW_PN_TX_PLL_OFF 0x10 00129 #define RH_RF95_PA_RAMP 0x0f 00130 #define RH_RF95_PA_RAMP_3_4MS 0x00 00131 #define RH_RF95_PA_RAMP_2MS 0x01 00132 #define RH_RF95_PA_RAMP_1MS 0x02 00133 #define RH_RF95_PA_RAMP_500US 0x03 00134 #define RH_RF95_PA_RAMP_250US 0x0 00135 #define RH_RF95_PA_RAMP_125US 0x05 00136 #define RH_RF95_PA_RAMP_100US 0x06 00137 #define RH_RF95_PA_RAMP_62US 0x07 00138 #define RH_RF95_PA_RAMP_50US 0x08 00139 #define RH_RF95_PA_RAMP_40US 0x09 00140 #define RH_RF95_PA_RAMP_31US 0x0a 00141 #define RH_RF95_PA_RAMP_25US 0x0b 00142 #define RH_RF95_PA_RAMP_20US 0x0c 00143 #define RH_RF95_PA_RAMP_15US 0x0d 00144 #define RH_RF95_PA_RAMP_12US 0x0e 00145 #define RH_RF95_PA_RAMP_10US 0x0f 00146 00147 // RH_RF95_REG_0B_OCP 0x0b 00148 #define RH_RF95_OCP_ON 0x20 00149 #define RH_RF95_OCP_TRIM 0x1f 00150 00151 // RH_RF95_REG_0C_LNA 0x0c 00152 #define RH_RF95_LNA_GAIN 0xe0 00153 #define RH_RF95_LNA_GAIN_G1 0x20 00154 #define RH_RF95_LNA_GAIN_G2 0x40 00155 #define RH_RF95_LNA_GAIN_G3 0x60 00156 #define RH_RF95_LNA_GAIN_G4 0x80 00157 #define RH_RF95_LNA_GAIN_G5 0xa0 00158 #define RH_RF95_LNA_GAIN_G6 0xc0 00159 #define RH_RF95_LNA_BOOST_LF 0x18 00160 #define RH_RF95_LNA_BOOST_LF_DEFAULT 0x00 00161 #define RH_RF95_LNA_BOOST_HF 0x03 00162 #define RH_RF95_LNA_BOOST_HF_DEFAULT 0x00 00163 #define RH_RF95_LNA_BOOST_HF_150PC 0x11 00164 00165 // RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11 00166 #define RH_RF95_RX_TIMEOUT_MASK 0x80 00167 #define RH_RF95_RX_DONE_MASK 0x40 00168 #define RH_RF95_PAYLOAD_CRC_ERROR_MASK 0x20 00169 #define RH_RF95_VALID_HEADER_MASK 0x10 00170 #define RH_RF95_TX_DONE_MASK 0x08 00171 #define RH_RF95_CAD_DONE_MASK 0x04 00172 #define RH_RF95_FHSS_CHANGE_CHANNEL_MASK 0x02 00173 #define RH_RF95_CAD_DETECTED_MASK 0x01 00174 00175 // RH_RF95_REG_12_IRQ_FLAGS 0x12 00176 #define RH_RF95_RX_TIMEOUT 0x80 00177 #define RH_RF95_RX_DONE 0x40 00178 #define RH_RF95_PAYLOAD_CRC_ERROR 0x20 00179 #define RH_RF95_VALID_HEADER 0x10 00180 #define RH_RF95_TX_DONE 0x08 00181 #define RH_RF95_CAD_DONE 0x04 00182 #define RH_RF95_FHSS_CHANGE_CHANNEL 0x02 00183 #define RH_RF95_CAD_DETECTED 0x01 00184 00185 // RH_RF95_REG_18_MODEM_STAT 0x18 00186 #define RH_RF95_RX_CODING_RATE 0xe0 00187 #define RH_RF95_MODEM_STATUS_CLEAR 0x10 00188 #define RH_RF95_MODEM_STATUS_HEADER_INFO_VALID 0x08 00189 #define RH_RF95_MODEM_STATUS_RX_ONGOING 0x04 00190 #define RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED 0x02 00191 #define RH_RF95_MODEM_STATUS_SIGNAL_DETECTED 0x01 00192 00193 // RH_RF95_REG_1C_HOP_CHANNEL 0x1c 00194 #define RH_RF95_PLL_TIMEOUT 0x80 00195 #define RH_RF95_RX_PAYLOAD_CRC_IS_ON 0x40 00196 #define RH_RF95_FHSS_PRESENT_CHANNEL 0x3f 00197 00198 // RH_RF95_REG_1D_MODEM_CONFIG1 0x1d 00199 #define RH_RF95_BW 0xf0 00200 00201 #define RH_RF95_BW_7_8KHZ 0x00 00202 #define RH_RF95_BW_10_4KHZ 0x10 00203 #define RH_RF95_BW_15_6KHZ 0x20 00204 #define RH_RF95_BW_20_8KHZ 0x30 00205 #define RH_RF95_BW_31_25KHZ 0x40 00206 #define RH_RF95_BW_41_7KHZ 0x50 00207 #define RH_RF95_BW_62_5KHZ 0x60 00208 #define RH_RF95_BW_125KHZ 0x70 00209 #define RH_RF95_BW_250KHZ 0x80 00210 #define RH_RF95_BW_500KHZ 0x90 00211 #define RH_RF95_CODING_RATE 0x0e 00212 #define RH_RF95_CODING_RATE_4_5 0x02 00213 #define RH_RF95_CODING_RATE_4_6 0x04 00214 #define RH_RF95_CODING_RATE_4_7 0x06 00215 #define RH_RF95_CODING_RATE_4_8 0x08 00216 #define RH_RF95_IMPLICIT_HEADER_MODE_ON 0x01 00217 00218 // RH_RF95_REG_1E_MODEM_CONFIG2 0x1e 00219 #define RH_RF95_SPREADING_FACTOR 0xf0 00220 #define RH_RF95_SPREADING_FACTOR_64CPS 0x60 00221 #define RH_RF95_SPREADING_FACTOR_128CPS 0x70 00222 #define RH_RF95_SPREADING_FACTOR_256CPS 0x80 00223 #define RH_RF95_SPREADING_FACTOR_512CPS 0x90 00224 #define RH_RF95_SPREADING_FACTOR_1024CPS 0xa0 00225 #define RH_RF95_SPREADING_FACTOR_2048CPS 0xb0 00226 #define RH_RF95_SPREADING_FACTOR_4096CPS 0xc0 00227 #define RH_RF95_TX_CONTINUOUS_MOE 0x08 00228 00229 #define RH_RF95_PAYLOAD_CRC_ON 0x04 00230 #define RH_RF95_SYM_TIMEOUT_MSB 0x03 00231 00232 // RH_RF95_REG_4B_TCXO 0x4b 00233 #define RH_RF95_TCXO_TCXO_INPUT_ON 0x10 00234 00235 // RH_RF95_REG_4D_PA_DAC 0x4d 00236 #define RH_RF95_PA_DAC_DISABLE 0x04 00237 #define RH_RF95_PA_DAC_ENABLE 0x07 00238 00239 ///////////////////////////////////////////////////////////////////// 00240 /// \class RH_RF95 RH_RF95.h <RH_RF95.h> 00241 /// \brief Driver to send and receive unaddressed, unreliable datagrams via a LoRa 00242 /// capable radio transceiver. 00243 /// 00244 /// For Semtech SX1276/77/78/79 and HopeRF RF95/96/97/98 and other similar LoRa capable radios. 00245 /// Based on http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf 00246 /// and http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf 00247 /// and http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf 00248 /// and http://www.semtech.com/images/datasheet/sx1276.pdf 00249 /// and http://www.semtech.com/images/datasheet/sx1276_77_78_79.pdf 00250 /// FSK/GFSK/OOK modes are not (yet) supported. 00251 /// 00252 /// Works with 00253 /// - the excellent MiniWirelessLoRa from Anarduino http://www.anarduino.com/miniwireless 00254 /// - The excellent Modtronix inAir4 http://modtronix.com/inair4.html 00255 /// and inAir9 modules http://modtronix.com/inair9.html. 00256 /// - the excellent Rocket Scream Mini Ultra Pro with the RFM95W 00257 /// http://www.rocketscream.com/blog/product/mini-ultra-pro-with-radio/ 00258 /// - Lora1276 module from NiceRF http://www.nicerf.com/product_view.aspx?id=99 00259 /// - Adafruit Feather M0 with RFM95 00260 /// 00261 /// \par Overview 00262 /// 00263 /// This class provides basic functions for sending and receiving unaddressed, 00264 /// unreliable datagrams of arbitrary length to 251 octets per packet. 00265 /// 00266 /// Manager classes may use this class to implement reliable, addressed datagrams and streams, 00267 /// mesh routers, repeaters, translators etc. 00268 /// 00269 /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and 00270 /// modulation scheme. 00271 /// 00272 /// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF 00273 /// RFM95/96/97/98(W), Semtech SX1276/77/78/79 and compatible radio modules in LoRa mode. 00274 /// 00275 /// The Hope-RF (http://www.hoperf.com) RFM95/96/97/98(W) and Semtech SX1276/77/78/79 is a low-cost ISM transceiver 00276 /// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and 00277 /// programmable data rates, and it also supports the proprietary LoRA (Long Range) mode, which 00278 /// is the only mode supported in this RadioHead driver. 00279 /// 00280 /// This Driver provides functions for sending and receiving messages of up 00281 /// to 251 octets on any frequency supported by the radio, in a range of 00282 /// predefined Bandwidths, Spreading Factors and Coding Rates. Frequency can be set with 00283 /// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited 00284 /// range of frequencies due to antenna tuning. 00285 /// 00286 /// Up to 2 modules can be connected to an Arduino (3 on a Mega), 00287 /// permitting the construction of translators and frequency changers, etc. 00288 /// 00289 /// Support for other features such as transmitter power control etc is 00290 /// also provided. 00291 /// 00292 /// Tested on MinWirelessLoRa with arduino-1.0.5 00293 /// on OpenSuSE 13.1. 00294 /// Also tested with Teensy3.1, Modtronix inAir4 and Arduino 1.6.5 on OpenSuSE 13.1 00295 /// 00296 /// \par Packet Format 00297 /// 00298 /// All messages sent and received by this RH_RF95 Driver conform to this packet format: 00299 /// 00300 /// - LoRa mode: 00301 /// - 8 symbol PREAMBLE 00302 /// - Explicit header with header CRC (handled internally by the radio) 00303 /// - 4 octets HEADER: (TO, FROM, ID, FLAGS) 00304 /// - 0 to 251 octets DATA 00305 /// - CRC (handled internally by the radio) 00306 /// 00307 /// \par Connecting RFM95/96/97/98 and Semtech SX1276/77/78/79 to Arduino 00308 /// 00309 /// We tested with Anarduino MiniWirelessLoRA, which is an Arduino Duemilanove compatible with a RFM96W 00310 /// module on-board. Therefore it needs no connections other than the USB 00311 /// programming connection and an antenna to make it work. 00312 /// 00313 /// If you have a bare RFM95/96/97/98 that you want to connect to an Arduino, you 00314 /// might use these connections (untested): CAUTION: you must use a 3.3V type 00315 /// Arduino, otherwise you will also need voltage level shifters between the 00316 /// Arduino and the RFM95. CAUTION, you must also ensure you connect an 00317 /// antenna. 00318 /// 00319 /// \code 00320 /// Arduino RFM95/96/97/98 00321 /// GND----------GND (ground in) 00322 /// 3V3----------3.3V (3.3V in) 00323 /// interrupt 0 pin D2-----------DIO0 (interrupt request out) 00324 /// SS pin D10----------NSS (CS chip select in) 00325 /// SCK pin D13----------SCK (SPI clock in) 00326 /// MOSI pin D11----------MOSI (SPI Data in) 00327 /// MISO pin D12----------MISO (SPI Data out) 00328 /// \endcode 00329 /// With these connections, you can then use the default constructor RH_RF95(). 00330 /// You can override the default settings for the SS pin and the interrupt in 00331 /// the RH_RF95 constructor if you wish to connect the slave select SS to other 00332 /// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53 00333 /// for Mega) or the interrupt request to other than pin D2 (Caution, 00334 /// different processors have different constraints as to the pins available 00335 /// for interrupts). 00336 /// 00337 /// You can connect a Modtronix inAir4 or inAir9 directly to a 3.3V part such as a Teensy 3.1 like 00338 /// this (tested). 00339 /// \code 00340 /// Teensy inAir4 inAir9 00341 /// GND----------GND (ground in) 00342 /// 3V3----------3.3V (3.3V in) 00343 /// interrupt 0 pin D2-----------D00 (interrupt request out) 00344 /// SS pin D10----------CS (CS chip select in) 00345 /// SCK pin D13----------CK (SPI clock in) 00346 /// MOSI pin D11----------SI (SPI Data in) 00347 /// MISO pin D12----------SO (SPI Data out) 00348 /// \endcode 00349 /// With these connections, you can then use the default constructor RH_RF95(). 00350 /// you must also set the transmitter power with useRFO: 00351 /// driver.setTxPower(13, true); 00352 /// 00353 /// Note that if you are using Modtronix inAir4 or inAir9,or any other module which uses the 00354 /// transmitter RFO pins and not the PA_BOOST pins 00355 /// that you must configure the power transmitter power for -1 to 14 dBm and with useRFO true. 00356 /// Failure to do that will result in extremely low transmit powers. 00357 /// 00358 /// If you have an Arduino M0 Pro from arduino.org, 00359 /// you should note that you cannot use Pin 2 for the interrupt line 00360 /// (Pin 2 is for the NMI only). The same comments apply to Pin 4 on Arduino Zero from arduino.cc. 00361 /// Instead you can use any other pin (we use Pin 3) and initialise RH_RF69 like this: 00362 /// \code 00363 /// // Slave Select is pin 10, interrupt is Pin 3 00364 /// RH_RF95 driver(10, 3); 00365 /// \endcode 00366 /// 00367 /// If you have a Rocket Scream Mini Ultra Pro with the RFM95W: 00368 /// - Ensure you have Arduino SAMD board support 1.6.5 or later in Arduino IDE 1.6.8 or later. 00369 /// - The radio SS is hardwired to pin D5 and the DIO0 interrupt to pin D2, 00370 /// so you need to initialise the radio like this: 00371 /// \code 00372 /// RH_RF95 driver(5, 2); 00373 /// \endcode 00374 /// - The name of the serial port on that board is 'SerialUSB', not 'Serial', so this may be helpful at the top of our 00375 /// sample sketches: 00376 /// \code 00377 /// #define Serial SerialUSB 00378 /// \endcode 00379 /// - You also need this in setup before radio initialisation 00380 /// \code 00381 /// // Ensure serial flash is not interfering with radio communication on SPI bus 00382 /// pinMode(4, OUTPUT); 00383 /// digitalWrite(4, HIGH); 00384 /// \endcode 00385 /// - and if you have a 915MHz part, you need this after driver/manager intitalisation: 00386 /// \code 00387 /// rf95.setFrequency(915.0); 00388 /// \endcode 00389 /// which adds up to modifying sample sketches something like: 00390 /// \code 00391 /// #include <SPI.h> 00392 /// #include <RH_RF95.h> 00393 /// RH_RF95 rf95(5, 2); // Rocket Scream Mini Ultra Pro with the RFM95W 00394 /// #define Serial SerialUSB 00395 /// 00396 /// void setup() 00397 /// { 00398 /// // Ensure serial flash is not interfering with radio communication on SPI bus 00399 /// pinMode(4, OUTPUT); 00400 /// digitalWrite(4, HIGH); 00401 /// 00402 /// Serial.begin(9600); 00403 /// while (!Serial) ; // Wait for serial port to be available 00404 /// if (!rf95.init()) 00405 /// Serial.println("init failed"); 00406 /// rf95.setFrequency(915.0); 00407 /// } 00408 /// ... 00409 /// \endcode 00410 /// 00411 /// For Adafruit Feather M0 with RFM95, construct the driver like this: 00412 /// \code 00413 /// RH_RF95 rf95(8, 3); 00414 /// \endcode 00415 /// 00416 /// It is possible to have 2 or more radios connected to one Arduino, provided 00417 /// each radio has its own SS and interrupt line (SCK, SDI and SDO are common 00418 /// to all radios) 00419 /// 00420 /// Caution: on some Arduinos such as the Mega 2560, if you set the slave 00421 /// select pin to be other than the usual SS pin (D53 on Mega 2560), you may 00422 /// need to set the usual SS pin to be an output to force the Arduino into SPI 00423 /// master mode. 00424 /// 00425 /// Caution: Power supply requirements of the RFM module may be relevant in some circumstances: 00426 /// RFM95/96/97/98 modules are capable of pulling 120mA+ at full power, where Arduino's 3.3V line can 00427 /// give 50mA. You may need to make provision for alternate power supply for 00428 /// the RFM module, especially if you wish to use full transmit power, and/or you have 00429 /// other shields demanding power. Inadequate power for the RFM is likely to cause symptoms such as: 00430 /// - reset's/bootups terminate with "init failed" messages 00431 /// - random termination of communication after 5-30 packets sent/received 00432 /// - "fake ok" state, where initialization passes fluently, but communication doesn't happen 00433 /// - shields hang Arduino boards, especially during the flashing 00434 /// 00435 /// \par Interrupts 00436 /// 00437 /// The RH_RF95 driver uses interrupts to react to events in the RFM module, 00438 /// such as the reception of a new packet, or the completion of transmission 00439 /// of a packet. The RH_RF95 driver interrupt service routine reads status from 00440 /// and writes data to the the RFM module via the SPI interface. It is very 00441 /// important therefore, that if you are using the RH_RF95 driver with another 00442 /// SPI based deviced, that you disable interrupts while you transfer data to 00443 /// and from that other device. Use cli() to disable interrupts and sei() to 00444 /// reenable them. 00445 /// 00446 /// \par Memory 00447 /// 00448 /// The RH_RF95 driver requires non-trivial amounts of memory. The sample 00449 /// programs all compile to about 8kbytes each, which will fit in the 00450 /// flash proram memory of most Arduinos. However, the RAM requirements are 00451 /// more critical. Therefore, you should be vary sparing with RAM use in 00452 /// programs that use the RH_RF95 driver. 00453 /// 00454 /// It is often hard to accurately identify when you are hitting RAM limits on Arduino. 00455 /// The symptoms can include: 00456 /// - Mysterious crashes and restarts 00457 /// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements) 00458 /// - Hanging 00459 /// - Output from Serial.print() not appearing 00460 /// 00461 /// \par Range 00462 /// 00463 /// We have made some simple range tests under the following conditions: 00464 /// - rf95_client base station connected to a VHF discone antenna at 8m height above ground 00465 /// - rf95_server mobile connected to 17.3cm 1/4 wavelength antenna at 1m height, no ground plane. 00466 /// - Both configured for 13dBm, 434MHz, Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range 00467 /// - Minimum reported RSSI seen for successful comms was about -91 00468 /// - Range over flat ground through heavy trees and vegetation approx 2km. 00469 /// - At 20dBm (100mW) otherwise identical conditions approx 3km. 00470 /// - At 20dBm, along salt water flat sandy beach, 3.2km. 00471 /// 00472 /// It should be noted that at this data rate, a 12 octet message takes 2 seconds to transmit. 00473 /// 00474 /// At 20dBm (100mW) with Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. 00475 /// (Default medium range) in the conditions described above. 00476 /// - Range over flat ground through heavy trees and vegetation approx 2km. 00477 /// 00478 /// Caution: the performance of this radio, especially with narrow bandwidths is strongly dependent on the 00479 /// accuracy and stability of the chip clock. HopeRF and Semtech do not appear to 00480 /// recommend bandwidths of less than 62.5 kHz 00481 /// unless you have the optional Temperature Compensated Crystal Oscillator (TCXO) installed and 00482 /// enabled on your radio module. See the refernece manual for more data. 00483 /// Also https://lowpowerlab.com/forum/rf-range-antennas-rfm69-library/lora-library-experiences-range/15/ 00484 /// and http://www.semtech.com/images/datasheet/an120014-xo-guidance-lora-modulation.pdf 00485 /// 00486 /// \par Transmitter Power 00487 /// 00488 /// You can control the transmitter power on the RF transceiver 00489 /// with the RH_RF95::setTxPower() function. The argument can be any of 00490 /// +5 to +23 (for modules that use PA_BOOST) 00491 /// -1 to +14 (for modules that use RFO transmitter pin) 00492 /// The default is 13. Eg: 00493 /// \code 00494 /// driver.setTxPower(10); // use PA_BOOST transmitter pin 00495 /// driver.setTxPower(10, true); // use PA_RFO pin transmitter pin 00496 /// \endcode 00497 /// 00498 /// We have made some actual power measurements against 00499 /// programmed power for Anarduino MiniWirelessLoRa (which has RFM96W-433Mhz installed) 00500 /// - MiniWirelessLoRa RFM96W-433Mhz, USB power 00501 /// - 30cm RG316 soldered direct to RFM96W module ANT and GND 00502 /// - SMA connector 00503 /// - 12db attenuator 00504 /// - SMA connector 00505 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set) 00506 /// - Tektronix TDS220 scope to measure the Vout from power head 00507 /// \code 00508 /// Program power Measured Power 00509 /// dBm dBm 00510 /// 5 5 00511 /// 7 7 00512 /// 9 8 00513 /// 11 11 00514 /// 13 13 00515 /// 15 15 00516 /// 17 16 00517 /// 19 18 00518 /// 20 20 00519 /// 21 21 00520 /// 22 22 00521 /// 23 23 00522 /// \endcode 00523 /// 00524 /// We have also measured the actual power output from a Modtronix inAir4 http://modtronix.com/inair4.html 00525 /// connected to a Teensy 3.1: 00526 /// Teensy 3.1 this is a 3.3V part, connected directly to: 00527 /// Modtronix inAir4 with SMA antenna connector, connected as above: 00528 /// 10cm SMA-SMA cable 00529 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set) 00530 /// - Tektronix TDS220 scope to measure the Vout from power head 00531 /// \code 00532 /// Program power Measured Power 00533 /// dBm dBm 00534 /// -1 0 00535 /// 1 2 00536 /// 3 4 00537 /// 5 7 00538 /// 7 10 00539 /// 9 13 00540 /// 11 14.2 00541 /// 13 15 00542 /// 14 16 00543 /// \endcode 00544 /// (Caution: we dont claim laboratory accuracy for these power measurements) 00545 /// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna. 00546 class RH_RF95 : public RHGenericDriver 00547 { 00548 public: 00549 /// \brief Defines register values for a set of modem configuration registers 00550 /// 00551 /// Defines register values for a set of modem configuration registers 00552 /// that can be passed to setModemRegisters() if none of the choices in 00553 /// ModemConfigChoice suit your need setModemRegisters() writes the 00554 /// register values from this structure to the appropriate registers 00555 /// to set the desired spreading factor, coding rate and bandwidth 00556 typedef struct 00557 { 00558 uint8_t reg_1d; ///< Value for register RH_RF95_REG_1D_MODEM_CONFIG1 00559 uint8_t reg_1e; ///< Value for register RH_RF95_REG_1E_MODEM_CONFIG2 00560 uint8_t reg_26; ///< Value for register RH_RF95_REG_26_MODEM_CONFIG3 00561 } ModemConfig; 00562 00563 /// Choices for setModemConfig() for a selected subset of common 00564 /// data rates. If you need another configuration, 00565 /// determine the necessary settings and call setModemRegisters() with your 00566 /// desired settings. It might be helpful to use the LoRa calculator mentioned in 00567 /// http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf 00568 /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic 00569 /// definitions and not their integer equivalents: its possible that new values will be 00570 /// introduced in later versions (though we will try to avoid it). 00571 /// Caution: if you are using slow packet rates and long packets with RHReliableDatagram or subclasses 00572 /// you may need to change the RHReliableDatagram timeout for reliable operations. 00573 /// Caution: for some slow rates nad with ReliableDatagrams youi may need to increase the reply timeout 00574 /// with manager.setTimeout() to 00575 /// deal with the long transmission times. 00576 typedef enum 00577 { 00578 Bw125Cr45Sf128 = 0, ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range 00579 Bw500Cr45Sf128, ///< Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range 00580 Bw31_25Cr48Sf512, ///< Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range 00581 Bw125Cr48Sf4096, ///< Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range 00582 } ModemConfigChoice; 00583 00584 /// Constructor. You can have multiple instances, but each instance must have its own 00585 /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface 00586 /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient 00587 /// distinct interrupt lines, one for each instance. 00588 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RH_RF22 before 00589 /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple) 00590 /// \param[in] interruptPin The interrupt Pin number that is connected to the RFM DIO0 interrupt line. 00591 /// Defaults to pin 2, as required by Anarduino MinWirelessLoRa module. 00592 /// Caution: You must specify an interrupt capable pin. 00593 /// On many Arduino boards, there are limitations as to which pins may be used as interrupts. 00594 /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin. 00595 /// On Arduino Zero from arduino.cc, any digital pin other than 4. 00596 /// On Arduino M0 Pro from arduino.org, any digital pin other than 2. 00597 /// On other Arduinos pins 2 or 3. 00598 /// See http://arduino.cc/en/Reference/attachInterrupt for more details. 00599 /// On Chipkit Uno32, pins 38, 2, 7, 8, 35. 00600 /// On other boards, any digital pin may be used. 00601 /// \param[in] spi Pointer to the SPI interface object to use. 00602 /// \param[in] ssNum the swspi slave select number to use 00603 RH_RF95(swspi& spi, int ssNum); 00604 00605 /// Initialise the Driver transport hardware and software. 00606 /// Make sure the Driver is properly configured before calling init(). 00607 /// \return true if initialisation succeeded. 00608 virtual bool init(); 00609 00610 /// Prints the value of all chip registers 00611 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform 00612 /// For debugging purposes only. 00613 /// \return true on success 00614 bool printRegisters(); 00615 00616 /// Sets all the registered required to configure the data modem in the RF95/96/97/98, including the bandwidth, 00617 /// spreading factor etc. You can use this to configure the modem with custom configurations if none of the 00618 /// canned configurations in ModemConfigChoice suit you. 00619 /// \param[in] config A ModemConfig structure containing values for the modem configuration registers. 00620 void setModemRegisters(const ModemConfig* config); 00621 00622 /// Select one of the predefined modem configurations. If you need a modem configuration not provided 00623 /// here, use setModemRegisters() with your own ModemConfig. 00624 /// \param[in] index The configuration choice. 00625 /// \return true if index is a valid choice. 00626 bool setModemConfig(ModemConfigChoice index); 00627 00628 /// Tests whether a new message is available 00629 /// from the Driver. 00630 /// On most drivers, this will also put the Driver into RHModeRx mode until 00631 /// a message is actually received by the transport, when it wil be returned to RHModeIdle. 00632 /// This can be called multiple times in a timeout loop 00633 /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv() 00634 virtual bool available(); 00635 00636 /// Turns the receiver on if it not already on. 00637 /// If there is a valid message available, copy it to buf and return true 00638 /// else return false. 00639 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted). 00640 /// You should be sure to call this function frequently enough to not miss any messages 00641 /// It is recommended that you call it in your main loop. 00642 /// \param[in] buf Location to copy the received message 00643 /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied. 00644 /// \return true if a valid message was copied to buf 00645 virtual bool recv(uint8_t* buf, uint8_t* len); 00646 00647 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent(). 00648 /// Then optionally waits for Channel Activity Detection (CAD) 00649 /// to show the channnel is clear (if the radio supports CAD) by calling waitCAD(). 00650 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length 00651 /// of 0 is permitted. 00652 /// \param[in] data Array of data to be sent 00653 /// \param[in] len Number of bytes of data to send 00654 /// specify the maximum time in ms to wait. If 0 (the default) do not wait for CAD before transmitting. 00655 /// \return true if the message length was valid and it was correctly queued for transmit. Return false 00656 /// if CAD was requested and the CAD timeout timed out before clear channel was detected. 00657 virtual bool send(const uint8_t* data, uint8_t len); 00658 00659 /// Sets the length of the preamble 00660 /// in bytes. 00661 /// Caution: this should be set to the same 00662 /// value on all nodes in your network. Default is 8. 00663 /// Sets the message preamble length in RH_RF95_REG_??_PREAMBLE_?SB 00664 /// \param[in] bytes Preamble length in bytes. 00665 void setPreambleLength(uint16_t bytes); 00666 00667 /// Returns the maximum message length 00668 /// available in this Driver. 00669 /// \return The maximum legal message length 00670 virtual uint8_t maxMessageLength(); 00671 00672 /// Sets the transmitter and receiver 00673 /// centre frequency. 00674 /// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several 00675 /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work 00676 /// \return true if the selected frquency centre is within range 00677 bool setFrequency(float centre); 00678 00679 /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running, 00680 /// disables them. 00681 void setModeIdle(); 00682 00683 /// If current mode is Tx or Idle, changes it to Rx. 00684 /// Starts the receiver in the RF95/96/97/98. 00685 void setModeRx(); 00686 00687 /// If current mode is Rx or Idle, changes it to Rx. F 00688 /// Starts the transmitter in the RF95/96/97/98. 00689 void setModeTx(); 00690 00691 /// Sets the transmitter power output level, and configures the transmitter pin. 00692 /// Be a good neighbour and set the lowest power level you need. 00693 /// Some SX1276/77/78/79 and compatible modules (such as RFM95/96/97/98) 00694 /// use the PA_BOOST transmitter pin for high power output (and optionally the PA_DAC) 00695 /// while some (such as the Modtronix inAir4 and inAir9) 00696 /// use the RFO transmitter pin for lower power but higher efficiency. 00697 /// You must set the appropriate power level and useRFO argument for your module. 00698 /// Check with your module manufacturer which transmtter pin is used on your module 00699 /// to ensure you are setting useRFO correctly. 00700 /// Failure to do so will result in very low 00701 /// transmitter power output. 00702 /// Caution: legal power limits may apply in certain countries. 00703 /// After init(), the power will be set to 13dBm, with useRFO false (ie PA_BOOST enabled). 00704 /// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA with useRFO false, 00705 /// valid values are from +5 to +23. 00706 /// For Modtronix inAir4 and inAir9 with useRFO true (ie RFO pins in use), 00707 /// valid values are from -1 to 14. 00708 /// \param[in] useRFO If true, enables the use of the RFO transmitter pins instead of 00709 /// the PA_BOOST pin (false). Choose the correct setting for your module. 00710 void setTxPower(int8_t power, bool useRFO = false); 00711 00712 /// Sets the radio into low-power sleep mode. 00713 /// If successful, the transport will stay in sleep mode until woken by 00714 /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc) 00715 /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode. 00716 /// \return true if sleep mode was successfully entered. 00717 virtual bool sleep(); 00718 00719 // Bent G Christensen (bentor@gmail.com), 08/15/2016 00720 /// Use the radio's Channel Activity Detect (CAD) function to detect channel activity. 00721 /// Sets the RF95 radio into CAD mode and waits until CAD detection is complete. 00722 /// To be used in a listen-before-talk mechanism (Collision Avoidance) 00723 /// with a reasonable time backoff algorithm. 00724 /// This is called automatically by waitCAD(). 00725 /// \return true if channel is in use. 00726 virtual bool isChannelActive(); 00727 00728 /// Enable TCXO mode 00729 /// Call this immediately after init(), to force your radio to use an external 00730 /// frequency source, such as a Temperature Compensated Crystal Oscillator (TCXO). 00731 /// See the comments in the main documentation about the sensitivity of this radio to 00732 /// clock frequency especially when using narrow bandwidths. 00733 /// Leaves the module in sleep mode. 00734 /// Caution, this function has not been tested by us. 00735 void enableTCXO(); 00736 00737 /// Returns the last measured frequency error. 00738 /// The LoRa receiver estimates the frequency offset between the receiver centre frequency 00739 /// and that of the received LoRa signal. This function returns the estimates offset (in Hz) 00740 /// of the last received message. Caution: this measurement is not absolute, but is measured 00741 /// relative to the local receiver's oscillator. 00742 /// Apparent errors may be due to the transmitter, the receiver or both. 00743 /// \return The estimated centre frequency offset in Hz of the last received message. 00744 /// If the modem bandwidth selector in 00745 /// register RH_RF95_REG_1D_MODEM_CONFIG1 is invalid, returns 0. 00746 int frequencyError(); 00747 00748 /// Returns the Signal-to-noise ratio (SNR) of the last received message, as measured 00749 /// by the receiver. 00750 /// \return SNR of the last received message in dB 00751 int lastSNR(); 00752 00753 /// This is a low level function to handle the interrupts for one instance of RH_RF95. 00754 /// Must be called from user code in mbed because the swspi library mutex cannot be 00755 /// executed in an ISR. It should be executed when the ISR pin is seen low. 00756 void handleInterrupt(); 00757 00758 protected: 00759 /// Examine the revceive buffer to determine whether the message is for this node 00760 void validateRxBuf(); 00761 00762 /// Clear our local receive buffer 00763 void clearRxBuf(); 00764 00765 private: 00766 /// SPI 00767 swspi& _spi; 00768 int _ssn; 00769 00770 /// Number of octets in the buffer 00771 volatile uint8_t _bufLen; 00772 00773 /// The receiver/transmitter buffer 00774 uint8_t _buf[RH_RF95_MAX_PAYLOAD_LEN]; 00775 00776 /// True when there is a valid message in the buffer 00777 volatile bool _rxBufValid; 00778 00779 // True if we are using the HF port (779.0 MHz and above) 00780 bool _usingHFport; 00781 00782 // Last measured SNR, dB 00783 int8_t _lastSNR; 00784 }; 00785 00786 /// @example rf95_client.pde 00787 /// @example rf95_server.pde 00788 /// @example rf95_reliable_datagram_client.pde 00789 /// @example rf95_reliable_datagram_server.pde 00790 00791 #endif 00792
Generated on Mon Jul 18 2022 11:18:50 by 1.7.2