|
1 |
| -Arduino-LMIC proof-of-concept library |
2 |
| -===================================== |
| 1 | +Arduino-LMIC library |
| 2 | +==================== |
3 | 3 | This repository contains the IBM LMIC (LoraMAC-in-C) library, slightly
|
4 |
| -modified to run in the Arduino environment, allowing using the SX1272 |
5 |
| -LoRa tranceiver with an Arduino. |
| 4 | +modified to run in the Arduino environment, allowing using the SX1272, |
| 5 | +SX1276 tranceivers and compatible modules (such as some HopeRF RFM9x |
| 6 | +modules). |
6 | 7 |
|
7 |
| -This repository is just a proof-of-concept to send data between two |
8 |
| -SX1272 modules. It is not intended as a complete library and was not |
9 |
| -tested in a full LoraWAN setup with a gateway (though feel free to fork |
10 |
| -it and turn it into one if you want). |
| 8 | +This library mostly exposes the functions defined by LMIC, it makes no |
| 9 | +attempt to wrap them in a higher level API that is more in the Arduino |
| 10 | +style. To find out how to use the library itself, see the examples, or |
| 11 | +see the PDF file in the doc subdirectory. |
11 | 12 |
|
12 |
| -If you want to actually use this code, note that it contains version 1.4 |
13 |
| -of the library, but there are newer versions available already. Also, |
14 |
| -the LMIC library needs to be modified to not invert IQ signals, in order |
15 |
| -to allow device-to-device communication as used in the raw.ino example, |
16 |
| -at the same time breaking device-to-gateway communication. |
| 13 | +This library requires Arduino IDE version 1.6.6 or above, since it |
| 14 | +requires C99 mode to be enabled by default. |
17 | 15 |
|
18 |
| -If you need device-to-device communication, make sure you reapply commit |
19 |
| -7561aa74c (Do not invert I/Q signals to allow communication between |
20 |
| -nodes), which was reverted in master. |
| 16 | +Installing |
| 17 | +---------- |
| 18 | +To install this library: |
21 | 19 |
|
22 |
| -At this time, this code needs an hourly build of the Arduino IDE (or |
23 |
| -1.6.6 once it is released), since that enables C99 code to be compiled. |
| 20 | + - install it using the Arduino Library manager ("Sketch" -> "Include |
| 21 | + Library" -> "Manage Libraries..."), or |
| 22 | + - download a zipfile from github using the "Download ZIP" button and |
| 23 | + install it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIP |
| 24 | + Library..." |
| 25 | + - clone this git repository into your sketchbook/libraries folder. |
| 26 | + |
| 27 | +For more info, see https://www.arduino.cc/en/Guide/Libraries |
| 28 | + |
| 29 | +Features |
| 30 | +-------- |
| 31 | +The LMIC library provides a fairly complete LoRaWAN Class A and Class B |
| 32 | +implementation, supporting the EU-868 and US-915 bands. Only a limited |
| 33 | +number of features was tested using this port on Arduino hardware, so be |
| 34 | +careful when using any of the untested features. |
| 35 | + |
| 36 | +What certainly works: |
| 37 | + - Sending packets uplink, taking into account duty cycling. |
| 38 | + - Encryption and message integrity checking. |
| 39 | + - Receiving downlink packets in the RX2 window. |
| 40 | + - Custom frequencies and datarate settings. |
| 41 | + |
| 42 | +What has not been tested: |
| 43 | + - Receiving downlink packets in the RX1 window. |
| 44 | + - Receiving and processing MAC commands. |
| 45 | + - Class B operation. |
| 46 | + - Over-the-air activation (OTAA / joining). |
| 47 | + |
| 48 | +If you try one of these untested features and it works, be sure to let |
| 49 | +us know (creating a github issue is probably the best way for that). |
| 50 | + |
| 51 | +Supported hardware |
| 52 | +------------------ |
| 53 | +This library is intended to be used with plain LoRa transceivers, |
| 54 | +connecting to them using SPI. In particular, the SX1272 and SX1276 |
| 55 | +families are supported (which should include SX1273, SX1277, SX1278 and |
| 56 | +SX1279 which only differ in the available frequencies, bandwidths and |
| 57 | +spreading factors). It has been tested with both SX1272 and SX1276 |
| 58 | +chips, using the Semtech SX1272 evaluation board and the HopeRF RFM92 |
| 59 | +and RFM95 boards (which supposedly contain an SX1272 and SX1276 chip |
| 60 | +respectively). |
| 61 | + |
| 62 | +This library contains a full LoRaWAN stack and is intended to drive |
| 63 | +these Transceivers directly. It is *not* intended to be used with |
| 64 | +full-stack devices like the Microchip RN2483 and the Embit LR1272E. |
| 65 | +These contain a transceiver and microcontroller that implements the |
| 66 | +LoRaWAN stack and exposes a high-level serial interface instead of the |
| 67 | +low-level SPI transceiver interface. |
| 68 | + |
| 69 | +This library is intended to be used inside the Arduino environment. It |
| 70 | +should be architecture-independent, so it should run on "normal" AVR |
| 71 | +arduinos, but also on the ARM-based ones, and some success has been seen |
| 72 | +running on the ESP8266 board as well. It was tested on the Arduino Uno, |
| 73 | +Pinoccio Scout, Teensy LC and 3.x, ESP8266. |
| 74 | + |
| 75 | +This library an be quite heavy, especially if the fairly small ATmega |
| 76 | +328p (such as in the Arduino Uno) is used. In the default configuration, |
| 77 | +the available 32K flash space is nearly filled up (this includes some |
| 78 | +debug output overhead, though). By disabling some features in `config.h` |
| 79 | +(like beacon tracking and ping slots, which are not typically needed), |
| 80 | +some space can be freed up. Some work is underway to replace the AES |
| 81 | +encryption implementation, which should free up another 8K or so of |
| 82 | +flash in the future, making this library feasible to run on a 328p |
| 83 | +microcontroller. |
24 | 84 |
|
25 | 85 | Connections
|
26 | 86 | -----------
|
| 87 | +To make this library work, your Arduino (or whatever Arduino-compatible |
| 88 | +board you are using) should be connected to the transceiver. The exact |
| 89 | +connections are a bit dependent on the transceiver board and Arduino |
| 90 | +used, so this section tries to explain what each connection is for and |
| 91 | +in what cases it is (not) required. |
| 92 | + |
27 | 93 | Note that the SX1272 module runs at 3.3V and likely does not like 5V on
|
28 |
| -its pins, so make sure to use a level shifter, or an Arduino running at |
29 |
| -3.3V (this library was tested using a Pinoccio, which is an Arduino-like |
30 |
| -board running at 3.3V). The evaluation board has 100 ohm resistors in |
| 94 | +its pins (though the datasheet is not say anything about this, and my |
| 95 | +transceiver did not obviously break after accidentally using 5V I/O for |
| 96 | +a few hours). To be safe, make sure to use a level shifter, or an |
| 97 | +Arduino running at 3.3V. The Semtech evaluation board has 100 ohm resistors in |
31 | 98 | series with all data lines that might prevent damage, but I would not
|
32 | 99 | count on that.
|
33 | 100 |
|
34 |
| -The pins to use are shown (and can be changed) in the pinmap in example |
35 |
| -.ino files. It seems that connecting RST is not needed, and RXTX output on the |
36 |
| -Arduino side (which controls the RX/TX antenna switch) can be connected |
37 |
| -to the antenna switch (pin FEM\_CTX on the evaluation board). |
38 |
| -Alternatively, you can connect the RXTX pin of the SX1272 directly to |
39 |
| -the antenna switch (by connecting RXTX and FEM\_CTX together on the |
40 |
| -evaluation board, or moving R2 to R1). I'm not sure why you wouldn't |
41 |
| -always want this connection to be made, but apparently there is a reason |
42 |
| -to control the switch from the Arduino instead of from the SX1272. |
| 101 | +### Power |
| 102 | +The SX127x transceivers need a supply voltage between 1.8V and 3.9V. |
| 103 | +Using a 3.3V supply is typical. The SX127x chips have various supply |
| 104 | +lines (*VR_ANA*, *VR_DIG* and *VR_PA*), all of which need the same |
| 105 | +supply voltage. Some modules (like the Semtech evaluation board) expose |
| 106 | +these pins separately, just connect them all together to a 3.3V source. |
| 107 | +Some boards, like the HopeRF boards just have a single supply pin |
| 108 | +labeled *3.3V*. Any *GND* pins need to be connected to the Arduino *GND* |
| 109 | +pin(s). |
| 110 | + |
| 111 | +### SPI |
| 112 | +The primary way of communicating with the transceiver is through SPI |
| 113 | +(Serial Peripheral Interface). This uses four pins: MOSI, MISO, SCK and |
| 114 | +SS. The former three need to be directly connected: so MOSI to MOSI, |
| 115 | +MISO to MISO, SCK to SCK. Where these pins are located on your Arduino |
| 116 | +varies, see for example the "Connections" section of the [Arduino SPI |
| 117 | +documentation](SPI). |
| 118 | + |
| 119 | +The SS (slave select) connection is a bit more flexible. On the SPI |
| 120 | +slave side (the transceiver), this must be connect to the pin |
| 121 | +(typically) labeled *NSS*. On the SPI master (Arduino) side, this pin |
| 122 | +can connect to any I/O pin. Most Arduinos also have a pin labeled "SS", |
| 123 | +but this is only relevant when the Arduino works as an SPI slave, which |
| 124 | +is not the case here. Whatever pin you pick, you need to tell thlibrary what pin you used through the pin mapping (see below). |
| 125 | +library what pin you used through the pin mapping (see below). |
| 126 | + |
| 127 | +[SPI]: https://www.arduino.cc/en/Reference/SPI |
| 128 | + |
| 129 | +### DIO pins |
| 130 | +The DIO (digitial I/O) pins on the transceiver board can be configured |
| 131 | +for various functions. The LMIC library uses them to get instant status |
| 132 | +information from the transceiver. For example, when a LoRa transmission |
| 133 | +starts, the DIO0 pin is configured as a TxDone output. When the |
| 134 | +transmission is complete, the DIO0 pin is made high by the transceiver, |
| 135 | +which can be detected by the LMIC library. |
| 136 | + |
| 137 | +The LMIC library needs only access to DIO0, DIO1 and DIO2, the other |
| 138 | +DIOx pins can be left disconnected. On the Arduino side, they can |
| 139 | +connect to any I/O pin, since the current implementation does not use |
| 140 | +interrupts or other special hardware features (though this might be |
| 141 | +added in the feature, see also the "Timing" section). |
| 142 | + |
| 143 | +In LoRa mode the DIO pins are used as follows: |
| 144 | + * DIO0: TxDone and RxDone |
| 145 | + * DIO1: RxTimeout |
| 146 | + |
| 147 | +In FSK mode they are used as follows:: |
| 148 | + * DIO0: PayloadReady and PacketSent |
| 149 | + * DIO2: TimeOut |
| 150 | + |
| 151 | +Both modes need only 2 pins, but the tranceiver does not allow mapping |
| 152 | +them in such a way that all needed interrupts map to the same 2 pins. |
| 153 | +So, if both LoRa and FSK modes are used, all three pins must be |
| 154 | +connected. |
| 155 | + |
| 156 | +The pins used on the Arduino side should be configured in the pin |
| 157 | +mapping in your sketch (see below). |
| 158 | + |
| 159 | +### Reset |
| 160 | +The transceiver has a reset pin that can be used to explicitely reset |
| 161 | +it. The LMIC library uses this to ensure the chip is in a consistent |
| 162 | +state at startup. In practice, this pin can be left disconnected, since |
| 163 | +the transceiver will already be in a sane state on power-on, but |
| 164 | +connecting it might prevent problems in some cases. |
| 165 | + |
| 166 | +On the Arduino side, any I/O pin can be used. The pin number used must |
| 167 | +be configured in the pin mapping (see below). |
| 168 | + |
| 169 | +### RXTX |
| 170 | +The transceiver contains two separate antenna connections: One for RX |
| 171 | +and one for TX. A typical transceiver board contains an antenna switch |
| 172 | +chip, that allows switching a single antenna between these RX and TX |
| 173 | +connections. Such a antenna switcher can typically be told what |
| 174 | +position it should be through an input pin, often labeled *RXTX*. |
| 175 | + |
| 176 | +The easiest way to control the antenna switch is to use the *RXTX* pin |
| 177 | +on the SX127x transceiver. This pin is automatically set high during TX |
| 178 | +and low during RX. For example, the HopeRF boards seem to have this |
| 179 | +connection in place, so they do not expose any *RXTX* pins and the pin |
| 180 | +can be marked as unused in the pin mapping. |
| 181 | + |
| 182 | +Some boards do expose the antenna switcher pin, and sometimes also the |
| 183 | +SX127x *RXTX* pin. For example, the SX1272 evaluation board calls the |
| 184 | +former *FEM_CTX* and the latter *RXTX*. Again, simply connecting these |
| 185 | +together with a jumper wire is the easiest solution. |
| 186 | + |
| 187 | +Alternatively, or if the SX127x *RXTX* pin is not available, LMIC can be |
| 188 | +configured to control the antenna switch. Connect the antenna switch |
| 189 | +control pin (e.g. *FEM_CTX* on the Semtech evaluation board) to any I/O |
| 190 | +pin on the Arduino side, and configure the pin used in the pin map (see |
| 191 | +below). It is not entirely clear why would *not* want the transceiver to |
| 192 | +control the antenna directly, though. |
| 193 | + |
| 194 | +### Pin mapping |
| 195 | +As described above, most connections can use arbitrary I/O pins on the |
| 196 | +Arduino side. To tell the LMIC library about these, a pin mapping struct |
| 197 | +is used in the sketch file. |
| 198 | + |
| 199 | +For example, this could look like this: |
| 200 | + |
| 201 | + lmic_pinmap lmic_pins = { |
| 202 | + .nss = 6, |
| 203 | + .rxtx = LMIC_UNUSED_PIN, |
| 204 | + .rst = 5, |
| 205 | + .dio = {2, 3, 4}, |
| 206 | + }; |
| 207 | + |
| 208 | +The names refer to the pins on the transceiver side, the numbers refer |
| 209 | +to the Arduino pin numbers (to use the analog pins, use constants like |
| 210 | +`A0`). For the DIO pins, the three numbers refer to DIO0, DIO1 and DIO2 |
| 211 | +respectively. Any pins that are not needed should be specified as |
| 212 | +`LMIC_UNUSED_PIN`. The nss and dio0 pin is required, the others can |
| 213 | +potentially left out. |
| 214 | + |
| 215 | +The name of this struct must always be `lmic_pins`, which is a special name |
| 216 | +recognized by the library. |
| 217 | + |
| 218 | +Examples |
| 219 | +-------- |
| 220 | +This library currently provides two examples: |
| 221 | + |
| 222 | + - `ttn.ino` shows a basic transmission of a "Hello, world!" message |
| 223 | + using the LoRaWAN protocol. It contains some frequency settings and |
| 224 | + encryption keys intended for use with The Things Network, but these |
| 225 | + also correspond to the default settings of most gateways, so it |
| 226 | + should work with other networks and gateways as well. This example |
| 227 | + uses "personalization" (preconfiguring a device address and |
| 228 | + encryption keys), and does not employ over-the-air activation. |
| 229 | + |
| 230 | + Reception of packets (in response to transmission, using the RX1 and |
| 231 | + RX2 receive windows is also supported). |
| 232 | + |
| 233 | + - `raw.ino` shows how to access the radio on a somewhat low level, |
| 234 | + and allows to send raw (non-LoRaWAN) packets between nodes directly. |
| 235 | + This is useful to verify basic connectivity, and when no gateway is |
| 236 | + available, but this example also bypasses duty cycle checks, so be |
| 237 | + careful when changing the settings. |
| 238 | + |
| 239 | +Timing |
| 240 | +------ |
| 241 | +Unfortunately, the SX127x tranceivers do not support accurate |
| 242 | +timekeeping themselves (there is a sequencer that is *almost* sufficient |
| 243 | +for timing the RX1 and RX2 downlink windows, but that is only available |
| 244 | +in FSK mode, not in LoRa mode). This means that the microcontroller is |
| 245 | +responsible for keeping track of time. In particular, it should note |
| 246 | +when a packet finished transmitting, so it can open up the RX1 and RX2 |
| 247 | +receive windows at a fixed time after the end of transmission. |
| 248 | + |
| 249 | +This timing uses the Arduino `micros()` timer, which has a granularity |
| 250 | +of 4μs and is based on the primary microcontroller clock. For timing |
| 251 | +events, the tranceiver uses its DIOx pins as interrupt outputs. In the |
| 252 | +current implementation, these pins are not handled by an actual |
| 253 | +interrupt handler, but they are just polled once every LMIC loop, |
| 254 | +resulting in a bit inaccuracy in the timestamping. Also, running |
| 255 | +scheduled jobs (such as opening up the receive windows) is done using a |
| 256 | +polling approach, which might also result in further delays. |
| 257 | + |
| 258 | +Fortunately, LoRa is a fairly slow protocol and the timing of the |
| 259 | +receive windows is not super critical. To synchronize transmitter and |
| 260 | +receiver, a preamble is first transmitted. Using LoRaWAN, this preamble |
| 261 | +consists of 8 symbols, of which the receiver needs to see 4 symbols to |
| 262 | +lock on. The current implementation tries to enable the receiver for 5 |
| 263 | +symbol times at 1.5 symbol after the start of the receive window, |
| 264 | +meaning that a inacurracy of plus or minus 2.5 symbol times should be |
| 265 | +acceptable. |
| 266 | + |
| 267 | +At the fastest LoRa setting supported by the tranceiver (SF5BW500) a |
| 268 | +single preamble symbol takes 128μs, so the receive window timing should |
| 269 | +be accurate within 320 μs. This is certainly within a crystal's |
| 270 | +accuracy, but using the internal oscillator is probably not feasible |
| 271 | +(which is 1% - 10% accurate, depending on calibration). This accuracy |
| 272 | +should also be feasible with the polling approach used, provided that |
| 273 | +the LMIC loop is run often enough. |
| 274 | + |
| 275 | +It would be good to properly review this code at some point, since it |
| 276 | +seems that in some places some offsets and corrections are applied that |
| 277 | +might not be appropriate for the Arduino environment. So if reception is |
| 278 | +not working, the timing is something to have a closer look at. |
| 279 | + |
| 280 | +The LMIC library was intended to connect the DIO pins to interrupt |
| 281 | +lines and run code inside the interrupt handler. However, doing this |
| 282 | +opens up an entire can of worms with regard to doing SPI transfers |
| 283 | +inside interrupt routines (some of which is solved by the Arduino |
| 284 | +`beginTransaction()` API, but possibly not everything). One simpler |
| 285 | +alternative could be to use an interrupt handler to just store a |
| 286 | +timestamp, and then do the actual handling in the main loop (this |
| 287 | +requires modifications of the library to pass a timestamp to the LMIC |
| 288 | +`radio_irq_handler()` function). |
| 289 | + |
| 290 | +An even more accurate solution could be to use a dedicated timer with an |
| 291 | +input capture unit, that can store the timestamp of a change on the DIO0 |
| 292 | +pin (the only one that is timing-critical) entirely in hardware. |
| 293 | +Unfortunately, timer0, as used by Arduino's `millis()` and `micros()` |
| 294 | +functions does not seem to have an input capture unit, meaning a |
| 295 | +separate timer is needed for this. |
| 296 | + |
| 297 | +If the main microcontroller does not have a crystal, but uses the |
| 298 | +internal oscillator, the clock output of the transceiver (on DIO5) could |
| 299 | +be usable to drive this timer instead of the main microcontroller clock, |
| 300 | +to ensure the receive window timing is sufficiently accurate. Ideally, |
| 301 | +this would use timer2, which supports asynchronous mode (e.g. running |
| 302 | +while the microcontroller is sleeping), but that timer does not have an |
| 303 | +input capture unit. Timer1 has one, but it seems it will stop running |
| 304 | +once the microcontroller sleeps. Running the microcontroller in idle |
| 305 | +mode with a slower clock might be feasible, though. Instead of using the |
| 306 | +main crystal oscillator of the transceiver, it could be possible to use |
| 307 | +the transceiver's internal RC oscillator (which is calibrated against |
| 308 | +the transceiver crystal), or to calibrate the microcontroller internal |
| 309 | +RC oscillator using the transceiver's clkout. However, that datasheet is |
| 310 | +a bit vague on the RC oscillator's accuracy and how to use it exactly |
| 311 | +(some registers seem to be FSK-mode only), so this needs some |
| 312 | +experiments. |
| 313 | + |
| 314 | +Downlink packets |
| 315 | +---------------- |
| 316 | +Testing downlink packets is easy using the iot.semtech.com interface. |
| 317 | +However, note that it seems downlink packets from there are sent using |
| 318 | +the RX2 window and SF9BW125 settings, but LMIC defaults to SF12BW125 for |
| 319 | +the RX2 window (as indicated by the LoRaWAN specification). If downlink |
| 320 | +reception is not working, try changing the `DR_DNW2` parameter in |
| 321 | +`lorabase.h`. |
43 | 322 |
|
44 | 323 | License
|
45 | 324 | -------
|
46 | 325 | The source files in this repository are made available under the Eclipse
|
47 | 326 | Public License v1.0, except for the examples which use a more liberal
|
48 | 327 | license. Refer to each individual source file for more details.
|
49 |
| - |
|
0 commit comments