Got Adafruit Feather 32u4 LoRa Radio to work and here is how

not making much progress on the Adafruit feather 32U4 device
I am now testing using the example code from
which on the Dragino Lora Shield and the TTN node joins and transmits and receives data without problems

for the Adafruit feather 32U4 the code was modified to use the correct pins

// Lora OTAA for Adafruit Feather 32u4 

// Pin mapping
const lmic_pinmap lmic_pins = {
    .nss = 8,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 4,
    .dio = {7, 6, LMIC_UNUSED_PIN},
   // .dio = {3, 6, LMIC_UNUSED_PIN},

 * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
 * Permission is hereby granted, free of charge, to anyone
 * obtaining a copy of this document and accompanying files,
 * to do whatever they want with them without any restriction,
 * including, but not limited to, copying, modification and redistribution.
 * This example sends a valid LoRaWAN packet with payload "Hello,
 * world!", using frequency and encryption settings matching those of
 * the The Things Network.
 * This uses OTAA (Over-the-air activation), where where a DevEUI and
 * application key is configured, which are used in an over-the-air
 * activation procedure where a DevAddr and session keys are
 * assigned/generated for use with all further communication.
 * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
 * g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
 * violated by this sketch when left running for longer)!

 * To use this sketch, first register your application and device with
 * the things network, to set or generate an AppEUI, DevEUI and AppKey.
 * Multiple devices can use the same AppEUI, but each device has its own
 * DevEUI and AppKey.
 * Do not forget to define the radio type correctly in config.h.

//#define Serial Serial1
#include <lmic.h>
#include <hal\hal.h>
#include <SPI.h>
//#define Serial Serial1
// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ 0xCB, 0x81, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70  };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={  0x89, 0x49, 0x65, 0x98, 0xEF, 0xAB, 0x12, 0x00};
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}

// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
// The key shown here is the semtech default key.
static const u1_t PROGMEM APPKEY[16] = { 0x0A, 0xC2, 0x09, 0xCD, 0x16, 0x5E, 0x1E, 0x7D, 0xA3, 0xA1, 0xD6, 0x38, 0x23, 0xFD, 0x65, 0x0C  };
void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY, 16);}

static uint8_t mydata[] ={01,02};//"Hello, world!";
static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 60;

// Pin mapping
const lmic_pinmap lmic_pins = {
    .nss = 8,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 4,
    .dio = {7, 6, LMIC_UNUSED_PIN},
   // .dio = {3, 6, LMIC_UNUSED_PIN},

void onEvent (ev_t ev) {
    Serial.print(": ");
    switch(ev) {
        case EV_SCAN_TIMEOUT:
        case EV_BEACON_FOUND:
        case EV_BEACON_MISSED:
        case EV_BEACON_TRACKED:
        case EV_JOINING:
        case EV_JOINED:

            // Disable link check validation (automatically enabled
            // during join, but not supported by TTN at this time).
        case EV_RFU1:
        case EV_JOIN_FAILED:
        case EV_REJOIN_FAILED:
        case EV_TXCOMPLETE:
            Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
            if (LMIC.txrxFlags & TXRX_ACK)
              Serial.println(F("Received ack"));
            if (LMIC.dataLen) {
              Serial.println(F("Received "));
              Serial.println(F(" bytes of payload"));
              Serial.print(F("Data Received: "));
              for(int i=0;i< LMIC.dataLen;i++)
                 { Serial.print(" 0x"); Serial.print((LMIC.frame+LMIC.dataBeg)[i],  HEX);}
            // Schedule next transmission
            os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
        case EV_LOST_TSYNC:
        case EV_RESET:
        case EV_RXCOMPLETE:
            // data received in ping slot
        case EV_LINK_DEAD:
        case EV_LINK_ALIVE:
            Serial.println(F("Unknown event"));

void do_send(osjob_t* j){
    // Check if there is not a current TX/RX job running
    if (LMIC.opmode & OP_TXRXPEND) {
        Serial.println(F("OP_TXRXPEND, not sending"));
    } else {
        // Prepare upstream data transmission at the next possible time.
        LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
        Serial.println(F("Packet queued"));
    // Next TX is scheduled after TX_COMPLETE event.

void setup() {

    #ifdef VCC_ENABLE
    // For Pinoccio Scout boards
    pinMode(VCC_ENABLE, OUTPUT);
    digitalWrite(VCC_ENABLE, HIGH);

    // LMIC init
    // Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
    // Start job (sending automatically starts OTAA too)

void loop() {

while working on the TTN node I had changed the default SF7 to SF9 - changing it back to SF7 helped the connecting and also moving the gateway further away helped
I have three of the Adafruit feather 32u4 devices - all give inconsistent results
sometimes join fails, when it works data is sometimes transmitted, sooner or later the device hangs at Packet queued if I place my hand near the device it then wakes up and displays
12127800: EV_TXCOMPLETE (includes waiting for RX windows)

any ideas?

I have been working with a module that’s equal to adafruits feather 32u4.



// Set up the channels used by the Things Network, which corresponds
// to the defaults of most gateways. Without this, only three base
// channels from the LoRaWAN specification are used, which certainly
// works, so it is good for debugging, but can overload those
// frequencies, so be sure to configure the full frequency range of
// your network here (unless your network autoconfigures them).
// Setting up channels should happen after LMIC_setSession, as that
// configures the minimal channel set.

#if defined(CFG_eu868)
LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band


2 key tips to make it work with the generic lmic examples:

  1. Don’t use OTAA - use APB
  2. Reset the Frame Counter every time you reset your device (otherwise you see traffic from your device on your gateway (yes, its better to have one around for testing) but it never reaches your device due to the frame counter check)

I posted similar instructions for the feather m0 lora here: Adafruit feather m0 lora 900 end-to-end instructions

the APB example from \IBM_LIMC_Framerwork\ttn-abp gives
Packet queued
it then hangs - when I place my hand near the device it then gives
13145803: EV_TXCOMPLETE (includes waiting for RX windows)
D:\OneDrive - Environmental Products and Services Ltd\Documents\Arduino\libraries\arduino-lmic-master\src\lmic\lmic.c:1890

  1. Check if DIO1 connection to D6 is wired correctly. Measure from RFM95 DIO1 pin, not the pin at the end of the longer pin header as there seem to be boards where connection between the RFM and that pin is missing.
  2. Could you try with the code at I’ve been using it for two workshops without issues. (The only issue constantly reoccurring is people not using LSB for the EUIs and MSB for the APPKEY)

Kersing noted
Check if DIO1 connection to D6 is wired correctly. Measure from RFM95 DIO1 pin, not the pin at the end of the longer pin header as there seem to be boards where connection between the RFM and that pin is missing.
this proved to be the case on all three boards I have (one from the UK two from China) in that the RFM95 DIO1 pin was not connected!
Connecting DIO1 to pin 6 on one of my boards worked transmitting and receiving data

Packet queued
126195: EV_JOINING
888098: EV_JOINED
4901286: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
8783081: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
12664725: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
39774617: EV_TXCOMPLETE (includes waiting for RX windows)
2 bytes of payload
Data Received:  0x11 0x22
Packet queued
43656533: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
47476518: EV_TXCOMPLETE (includes waiting for RX windows)
2 bytes of payload
Data Received:  0xFB 0xFC
Packet queued
51358293: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
55239949: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
59060251: EV_TXCOMPLETE (includes waiting for RX windows)
4 bytes of payload
Data Received:  0x34 0x56 0x78 0x90

1 Like

Had the same issues, as after some time I again built up the Feather 32u4 LoRa on a breadboard. Like @kersing already said, it is important to do the wiring from DIO1 to Pin 6 correctly.
I actually made the mistake to make the wire connection to pin PD6 (which is the sixth pin counted down from the connector for the LiPo battery. Instead, use pin 6 as counted in the Arduino IDE, which has label “6” printed on the board and is the fourth pin (on the side of the LiPo connector) counted from the opposite direction of the LiPo connector).

I have three of the 32u4 Lora boards two from china and one from UK
two of the boards worked OK with OTTA once I connected the FRM95 DIO1 to pin 6 the other did not
Looking with a scope DIO1 to pin 6 was going high as expected once the Tx was complete
In the end I connected DIO1 to pin 5 and changed the FRM95 pin mapping to reflect this and it then worked OK joining, transmitting and recieving data using the Things network
it looks like there is a PCB fault in that 6 is not connected correctly on this particular PCB

I assume that the original Adafruit 32u4 Lora boards do not have these problems

You also might want to have a look at the LMIC stack by @Charles Hallard. This stack allows you to use any DIO configuration including no DIO’s attached to the microprocessor at all.

1 Like

But beware that one has last changed Aug 11, 2016, while the original meanwhile has greatly decreased the time for the EV_TXCOMPLETE event to fire, which might be nice to have.

To see the differences with @matthijs’ original:

Agree, it would be great to have this nice feature integrated in the “mainstream” stack from @matthijs
I guess that’s what the pull request by @charles was meant for :blush:

UPDATE: Simpler now and worked right away:

I used Arduino 1.8.5 on a Mac - your milage may vary.

1 Get an Adafruit Feather 32u4 lora with the right frequency range for your region (866 for Europe)

2 Follow instructions on the adafruit site to hook up antenna and power supply

3 Connect pin 6 with IO1 (as labeled on the feather)

4 In Arduino 1.8.5 IDE do not use the built-in support for finding and downloading the lmic library - instead rather download the zip file from github instead at

5 Open the apb example from this library from the examples menu and change the following lines:

const lmic_pinmap lmic_pins = {
.nss = 8,
.rst = 4,
.dio = {7,6,LMIC_UNUSED_PIN},

6 Get an account on the things network, create a new application in it and create a new device. Change the device to use abp instead of otaa. Copy all of the settings required from the device to your source code.

7 reset the frame counter for the device (you might need to do this again once you reset your device)

-> It worked at first attempt with a Gateway now installed at the top of my house to serve my local community in Heidelberg-Schlierbach.

8 Do whatever you want to hook up any sensor and send its data

One day I will dare to go back to otaa - but not now.

1 Like

I have similar problems with LoRa32U4 and OTAA.

LoRa32U4 II by BSFrance (868MHz) (with LoRa module replaced, see my next post).
Using LMIC-Arduino library version 1.5.0+arduino-2
RAK831 based gateway.
Distance between node and gateway is around 4m (with a concrete floor in between).

Activation using ABP just works.
Activation using OTAA first fails, but after waiting several minutes the OTAA join succeeds
(on a different spreading factor).

t0: First OTAA join attempt (SF7) failed.
t1: Second attempt (SF7) failed.
t2: Third attempt (SF8) failed.
t3: Fourth attempt (SF8) failed.
t4: Fifth attempt (SF9) SUCCEEDED.
From there communication went as expected.

LoRa32U4 OTAA issues

What causes this?

The LoRa32U4 contains an ATmega32U4 3.3V MCU.
I then tried the same test with a board with a similar (not identical) MCU: Arduino Pro Mini 3.3V connected to a Hope RFM95 LoRa module.
This setup showed problems with OTAA identical to the LoRa32U4, but the join succeeded only at SF 10 (SF 9 failed).
What’s happening here? What causes this?

When I used the exact same RFM95 module with ESP8266 and ESP32 based boards the issues with OTAA did not occur and OTAA just succeeded using SF 7.

Maybe power / speed of the MCU is at play here. But in that case I would have expected others to have similar problems and this to be a know issue.

Pin mappings used for LoRa32U4:


RFM9x/SX127x LoRa module
NSS - 8
SCK - 15/SCK
RST - 4
DIO0 - 7
DIO1 - 6 (Not wired onboard, must be explicitly wired).

OLED display

1 Like

The SX1276 LoRa module on my LoRa32U4 II (by BSFrance) was very poorly aligned. Soldering pads of the LoRa module almost seemed to shortcut neighbouring pads on the LoRa32U4 PCB.
Because I was having unexpected OTAA issues (described above) where OTAA join requests failed, the misaligned LoRa module appeared a plausible cause. So I removed the LoRa module from the LoRa32U4 board.

I was told that my LoRa32U4 II was a 868MHz version.
The bottom of the removed SX1276 LoRa module was marked 915MHz however. This also appeared a possible cause for OTAA requests.
To fix it I mounted a compatible Hope RFM95 868MHz module onto the LoRa32U4 board. I hoped this would fix the OTAA join issues but it did not.

After some further testing I experienced the behavior described in my previous post: that the join succeeds only starting at SF 9.

(I did not wait minutes when the original SX1276 LoRa module was still mounted, so I cannot comment on if the original module would have joined on higher spreading factors).

Have you relaxed the timing by using

   LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

between the LMIC reset and the join attempt?


Thanks. I had not, but adding it fixed the issues for both the LoRa32U4 and the Pro Mini setups. :+1:

1 Like


When buying pre-wired JST-PH connector plugs for the LoRa 32U4 battery connector:

Be aware that polarity may not be what you expect.


When looking at the red and black wires coming out of the connector one can easily assume that red is +3.7V and black is ground and then wire the battery correspondingly (at least I did).
But how the connector is wired may not correspond to how the board is wired. The red and black wires may be reversed on the connector.

If that is the case connecting the battery/connector will toast the LoRa 32U4 board.
When noticing the smoke (and smell) I quickly disconnected the battery, but it was already too late.
The battery controller chip was toasted. The LoRa 32U4 is still working but the power led does not light and the battery controller is damaged (will have to replace it).

So be careful with pre-wired battery connectors, they can toast your board unsuspectingly.
Check first if the connector wiring matches the board before trusting the wire colors.

I used these: JST-PH connectors with wires from AliExpress.
They have red and black wires reversed for LoRa 32U4.
It is not difficult to switch the wires on the connector but better do it before, not after.


Thanks for the heads-up @bluejedi, I have some of these wires sitting in our postal system somewhere!

Just a question for other LoRa 32U4II users…?

Range? Is it universally poor?
I have only set up one board which uses LMIC and OTAA. The antenna is one of the small (about 50mm SMA type) 868MHz jobs that ship with some of the AliExpress products. I am finding that the node only connects to my (RAK831) gateway when within say 300m and then with SF7 or occasionally SF8. I am sure I read that ADR doesn’t adjust SF if I am TTNMapping for example but even getting the node to connect with a SF that will work over a few hundred metres seems to be a trick?

I know I should try to eliminate possibly poor antenna and I guess the pig-tail also before I condemn the LoRa 32U4II but any consensus among us or hints to get a more robust connection for longer range?

G,8.7598985/In+der+Aue+20,+69118+Heidelberg/@49.4142399,8.7599525,17z/data=!3m1!4b1!4m8!4m7!1m0!1m5!1m1!1s0x4797c1d88a12d833:0x8bb7f33bf0819a5!2m2!1d8.76404!2d49.41265?hl=de - on this stretch of 500m with no clear line of sight from the gateway at the top of my house to the node with a 8.2cm wire antenna (bent twice) I did get data from the device in average 2 times out of 3 over a 4 day period every 3 minutes. I used the default settings from the apb example ino file. it sometimes did take 20 minutes for the first one to come through (I assume this is where ADR and other channel hoping magic happens between the node and the gateway) but then it was quiet reliable. I’m sure with line of sight I could go much further.