Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

⚠️ This library is deprecated, see the README for alternatives.

NotificationsYou must be signed in to change notification settings

matthijskooijman/arduino-lmic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

⚠️ This repository is no longer maintained. The recommendedalternative is theMCCI version of LMIC, which is based onthis one, but has seen much improvements over the years, has muchbetter documentation and is mostly a drop-in replacement. If you needsupport for the SX126x, you can considerLacuna's port ofBasicMAC, which is based on a parallel development based onthe original LMIC. Only when you have very tight constraints on RAM orflash should this version still be considered.

Seethis post for more details and background.

Arduino-LMIC library

This repository contains the IBM LMIC (LoraMAC-in-C) library, slightlymodified to run in the Arduino environment, allowing using the SX1272,SX1276 tranceivers and compatible modules (such as some HopeRF RFM9xmodules).

This library mostly exposes the functions defined by LMIC, it makes noattempt to wrap them in a higher level API that is more in the Arduinostyle. To find out how to use the library itself, see the examples, orsee the PDF file in the doc subdirectory.

This library requires Arduino IDE version 1.6.6 or above, since itrequires C99 mode to be enabled by default.

Installing

To install this library:

  • install it using the Arduino Library manager ("Sketch" -> "IncludeLibrary" -> "Manage Libraries..."), or
  • download a zipfile from github using the "Download ZIP" button andinstall it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIPLibrary..."
  • clone this git repository into your sketchbook/libraries folder.

For more info, seehttps://www.arduino.cc/en/Guide/Libraries

Features

The LMIC library provides a fairly complete LoRaWAN Class A and Class Bimplementation, supporting the EU-868 and US-915 bands. Only a limitednumber of features was tested using this port on Arduino hardware, so becareful when using any of the untested features.

What certainly works:

  • Sending packets uplink, taking into account duty cycling.
  • Encryption and message integrity checking.
  • Receiving downlink packets in the RX2 window.
  • Custom frequencies and datarate settings.
  • Over-the-air activation (OTAA / joining).

What has not been tested:

  • Receiving downlink packets in the RX1 window.
  • Receiving and processing MAC commands.
  • Class B operation.

If you try one of these untested features and it works, be sure to letus know (creating a github issue is probably the best way for that).

Configuration

A number of features can be configured or disabled by editing theconfig.h file in the library folder. Unfortunately the Arduinoenvironment does not offer any way to do this (compile-time)configuration from the sketch, so be careful to recheck yourconfiguration when you switch between sketches or update the library.

At the very least, you should set the right type of transceiver (SX1272vs SX1276) in config.h, most other values should be fine at theirdefaults.

Supported hardware

This library is intended to be used with plain LoRa transceivers,connecting to them using SPI. In particular, the SX1272 and SX1276families are supported (which should include SX1273, SX1277, SX1278 andSX1279 which only differ in the available frequencies, bandwidths andspreading factors). It has been tested with both SX1272 and SX1276chips, using the Semtech SX1272 evaluation board and the HopeRF RFM92and RFM95 boards (which supposedly contain an SX1272 and SX1276 chiprespectively).

This library contains a full LoRaWAN stack and is intended to drivethese Transceivers directly. It isnot intended to be used withfull-stack devices like the Microchip RN2483 and the Embit LR1272E.These contain a transceiver and microcontroller that implements theLoRaWAN stack and exposes a high-level serial interface instead of thelow-level SPI transceiver interface.

This library is intended to be used inside the Arduino environment. Itshould be architecture-independent, so it should run on "normal" AVRarduinos, but also on the ARM-based ones, and some success has been seenrunning on the ESP8266 board as well. It was tested on the Arduino Uno,Pinoccio Scout, Teensy LC and 3.x, ESP8266, Arduino 101.

This library an be quite heavy, especially if the fairly small ATmega328p (such as in the Arduino Uno) is used. In the default configuration,the available 32K flash space is nearly filled up (this includes somedebug output overhead, though). By disabling some features inconfig.h(like beacon tracking and ping slots, which are not typically needed),some space can be freed up. Some work is underway to replace the AESencryption implementation, which should free up another 8K or so offlash in the future, making this library feasible to run on a 328pmicrocontroller.

Connections

To make this library work, your Arduino (or whatever Arduino-compatibleboard you are using) should be connected to the transceiver. The exactconnections are a bit dependent on the transceiver board and Arduinoused, so this section tries to explain what each connection is for andin what cases it is (not) required.

Note that the SX1272 module runs at 3.3V and likely does not like 5V onits pins (though the datasheet is not say anything about this, and mytransceiver did not obviously break after accidentally using 5V I/O fora few hours). To be safe, make sure to use a level shifter, or anArduino running at 3.3V. The Semtech evaluation board has 100 ohm resistors inseries with all data lines that might prevent damage, but I would notcount on that.

Power

The SX127x transceivers need a supply voltage between 1.8V and 3.9V.Using a 3.3V supply is typical. Some modules have a single power pin(like the HopeRF modules, labeled 3.3V) but others expose multiple powerpins for different parts (like the Semtech evaluation board that hasVDD_RF,VDD_ANA andVDD_FEM), which can all be connected together.AnyGND pins need to be connected to the ArduinoGND pin(s).

SPI

The primary way of communicating with the transceiver is through SPI(Serial Peripheral Interface). This uses four pins: MOSI, MISO, SCK andSS. The former three need to be directly connected: so MOSI to MOSI,MISO to MISO, SCK to SCK. Where these pins are located on your Arduinovaries, see for example the "Connections" section of theArduino SPIdocumentation.

The SS (slave select) connection is a bit more flexible. On the SPIslave side (the transceiver), this must be connect to the pin(typically) labeledNSS. On the SPI master (Arduino) side, this pincan connect to any I/O pin. Most Arduinos also have a pin labeled "SS",but this is only relevant when the Arduino works as an SPI slave, whichis not the case here. Whatever pin you pick, you need to tell thelibrary what pin you used through the pin mapping (see below).

DIO pins

The DIO (digitial I/O) pins on the transceiver board can be configuredfor various functions. The LMIC library uses them to get instant statusinformation from the transceiver. For example, when a LoRa transmissionstarts, the DIO0 pin is configured as a TxDone output. When thetransmission is complete, the DIO0 pin is made high by the transceiver,which can be detected by the LMIC library.

The LMIC library needs only access to DIO0, DIO1 and DIO2, the otherDIOx pins can be left disconnected. On the Arduino side, they canconnect to any I/O pin, since the current implementation does not useinterrupts or other special hardware features (though this might beadded in the feature, see also the "Timing" section).

In LoRa mode the DIO pins are used as follows:

  • DIO0: TxDone and RxDone
  • DIO1: RxTimeout

In FSK mode they are used as follows::

  • DIO0: PayloadReady and PacketSent
  • DIO2: TimeOut

Both modes need only 2 pins, but the tranceiver does not allow mappingthem in such a way that all needed interrupts map to the same 2 pins.So, if both LoRa and FSK modes are used, all three pins must beconnected.

The pins used on the Arduino side should be configured in the pinmapping in your sketch (see below).

Reset

The transceiver has a reset pin that can be used to explicitely resetit. The LMIC library uses this to ensure the chip is in a consistentstate at startup. In practice, this pin can be left disconnected, sincethe transceiver will already be in a sane state on power-on, butconnecting it might prevent problems in some cases.

On the Arduino side, any I/O pin can be used. The pin number used mustbe configured in the pin mapping (see below).

RXTX

The transceiver contains two separate antenna connections: One for RXand one for TX. A typical transceiver board contains an antenna switchchip, that allows switching a single antenna between these RX and TXconnections. Such a antenna switcher can typically be told whatposition it should be through an input pin, often labeledRXTX.

The easiest way to control the antenna switch is to use theRXTX pinon the SX127x transceiver. This pin is automatically set high during TXand low during RX. For example, the HopeRF boards seem to have thisconnection in place, so they do not expose anyRXTX pins and the pincan be marked as unused in the pin mapping.

Some boards do expose the antenna switcher pin, and sometimes also theSX127xRXTX pin. For example, the SX1272 evaluation board calls theformerFEM_CTX and the latterRXTX. Again, simply connecting thesetogether with a jumper wire is the easiest solution.

Alternatively, or if the SX127xRXTX pin is not available, LMIC can beconfigured to control the antenna switch. Connect the antenna switchcontrol pin (e.g.FEM_CTX on the Semtech evaluation board) to any I/Opin on the Arduino side, and configure the pin used in the pin map (seebelow). It is not entirely clear why wouldnot want the transceiver tocontrol the antenna directly, though.

Pin mapping

As described above, most connections can use arbitrary I/O pins on theArduino side. To tell the LMIC library about these, a pin mapping structis used in the sketch file.

For example, this could look like this:

lmic_pinmap lmic_pins = {    .nss = 6,    .rxtx = LMIC_UNUSED_PIN,    .rst = 5,    .dio = {2, 3, 4},};

The names refer to the pins on the transceiver side, the numbers referto the Arduino pin numbers (to use the analog pins, use constants likeA0). For the DIO pins, the three numbers refer to DIO0, DIO1 and DIO2respectively. Any pins that are not needed should be specified asLMIC_UNUSED_PIN. The nss and dio0 pin is required, the others canpotentially left out (depending on the environments and requirements,see the notes above for when a pin can or cannot be left out).

The name of this struct must always belmic_pins, which is a special namerecognized by the library.

LoRa Nexus by Ideetron

This board uses the following pin mapping:

const lmic_pinmap lmic_pins = {    .nss = 10,    .rxtx = LMIC_UNUSED_PIN,    .rst = LMIC_UNUSED_PIN, // hardwired to AtMega RESET    .dio = {4, 5, 7},};

Examples

This library currently provides three examples:

  • ttn-abp.ino shows a basic transmission of a "Hello, world!" messageusing the LoRaWAN protocol. It contains some frequency settings andencryption keys intended for use with The Things Network, but thesealso correspond to the default settings of most gateways, so itshould work with other networks and gateways as well. This exampleuses activation-by-personalization (ABP, preconfiguring a deviceaddress and encryption keys), and does not employ over-the-airactivation.

    Reception of packets (in response to transmission, using the RX1 andRX2 receive windows is also supported).

  • ttn-otaa.ino also sends a "Hello, world!" message, but uses overthe air activation (OTAA) to first join a network to establish asession and security keys. This was tested with The Things Network,but should also work (perhaps with some changes) for other networks.

  • raw.ino shows how to access the radio on a somewhat low level,and allows to send raw (non-LoRaWAN) packets between nodes directly.This is useful to verify basic connectivity, and when no gateway isavailable, but this example also bypasses duty cycle checks, so becareful when changing the settings.

Timing

Unfortunately, the SX127x tranceivers do not support accuratetimekeeping themselves (there is a sequencer that isalmost sufficientfor timing the RX1 and RX2 downlink windows, but that is only availablein FSK mode, not in LoRa mode). This means that the microcontroller isresponsible for keeping track of time. In particular, it should notewhen a packet finished transmitting, so it can open up the RX1 and RX2receive windows at a fixed time after the end of transmission.

This timing uses the Arduinomicros() timer, which has a granularityof 4μs and is based on the primary microcontroller clock. For timingevents, the tranceiver uses its DIOx pins as interrupt outputs. In thecurrent implementation, these pins are not handled by an actualinterrupt handler, but they are just polled once every LMIC loop,resulting in a bit inaccuracy in the timestamping. Also, runningscheduled jobs (such as opening up the receive windows) is done using apolling approach, which might also result in further delays.

Fortunately, LoRa is a fairly slow protocol and the timing of thereceive windows is not super critical. To synchronize transmitter andreceiver, a preamble is first transmitted. Using LoRaWAN, this preambleconsists of 8 symbols, of which the receiver needs to see 4 symbols tolock on. The current implementation tries to enable the receiver for 5symbol times at 1.5 symbol after the start of the receive window,meaning that a inacurracy of plus or minus 2.5 symbol times should beacceptable.

At the fastest LoRa setting supported by the tranceiver (SF5BW500) asingle preamble symbol takes 64μs, so the receive window timing shouldbe accurate within 160μs (for LoRaWAN this is SF7BW250, needing accuracywithin 1280μs). This is certainly within a crystal's accuracy, but usingthe internal oscillator is probably not feasible (which is 1% - 10%accurate, depending on calibration). This accuracy should also befeasible with the polling approach used, provided that the LMIC loop isrun often enough.

It would be good to properly review this code at some point, since itseems that in some places some offsets and corrections are applied thatmight not be appropriate for the Arduino environment. So if reception isnot working, the timing is something to have a closer look at.

The LMIC library was intended to connect the DIO pins to interruptlines and run code inside the interrupt handler. However, doing thisopens up an entire can of worms with regard to doing SPI transfersinside interrupt routines (some of which is solved by the ArduinobeginTransaction() API, but possibly not everything). One simpleralternative could be to use an interrupt handler to just store atimestamp, and then do the actual handling in the main loop (thisrequires modifications of the library to pass a timestamp to the LMICradio_irq_handler() function).

An even more accurate solution could be to use a dedicated timer with aninput capture unit, that can store the timestamp of a change on the DIO0pin (the only one that is timing-critical) entirely in hardware.Unfortunately, timer0, as used by Arduino'smillis() andmicros()functions does not seem to have an input capture unit, meaning aseparate timer is needed for this.

If the main microcontroller does not have a crystal, but uses theinternal oscillator, the clock output of the transceiver (on DIO5) couldbe usable to drive this timer instead of the main microcontroller clock,to ensure the receive window timing is sufficiently accurate. Ideally,this would use timer2, which supports asynchronous mode (e.g. runningwhile the microcontroller is sleeping), but that timer does not have aninput capture unit. Timer1 has one, but it seems it will stop runningonce the microcontroller sleeps. Running the microcontroller in idlemode with a slower clock might be feasible, though. Instead of using themain crystal oscillator of the transceiver, it could be possible to usethe transceiver's internal RC oscillator (which is calibrated againstthe transceiver crystal), or to calibrate the microcontroller internalRC oscillator using the transceiver's clkout. However, that datasheet isa bit vague on the RC oscillator's accuracy and how to use it exactly(some registers seem to be FSK-mode only), so this needs someexperiments.

The code can currently compensate for an inaccurate clock, by callingtheLMIC_setClockError() function somewhere during setup. You can passa clock error percentage, e.g. to correct for 1% clock error:

LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

Problems with downlink and OTAA

Uplink will often work right away, but sometimes downlink (and thus alsoOTAA) will not work directly. In practice, this is often due toinaccuracies in the receive window timing (see the previous section fordetails). If you run into problems with OTAA or downlink, it is a goodidea to relax the RX mode timings to see if that helps by adding this toyour setup somewhere:

LMIC_setClockError(MAX_CLOCK_ERROR * 10 / 100);

This function is intended to compensate for clock inaccuracy (up to ±10%in this example), but that also works to compensate for inaccuracies dueto software delays. The downside of this compensation is a longerreceive window, which means a higher battery drain. So if this helps,you might want to try to lower the percentage (i.e. lower the 10 in theabove call), often 1% works well already.

Downlink datarate

Note that the datarate used for downlink packets in the RX2 windowdefaults to SF12BW125 according to the specification, but some networksuse different values (iot.semtech.com and The Things Network both useSF9BW). When using personalized activate (ABP), it is yourresponsibility to set the right settings, e.g. by adding this to yoursketch (after callingLMIC_setSession).ttn-abp.ino already doesthis.

 LMIC.dn2Dr = DR_SF9;

When using OTAA, the network communicates the RX2 settings in thejoin accept message, but the LMIC library does not currently processthese settings. Until that is solved (see issue #20), you shouldmanually set the RX2 rate,after joining (see the handling ofEV_JOINED in thettn-otaa.ino for an example.

License

Most source files in this repository are made available under theEclipse Public License v1.0. The examples which use a more liberallicense. Some of the AES code is available under the LGPL. Refer to eachindividual source file for more details.

About

⚠️ This library is deprecated, see the README for alternatives.

Resources

Stars

Watchers

Forks

Sponsor this project

 

[8]ページ先頭

©2009-2025 Movatter.jp