BSFrance Lora32u4 stuck in sleep mode

Hi,

I’ve been using a BSFrance Lora32u4 board for experimenting with TTN for a few weeks. The board seems to be a clone of the Adafruit Lora32u4.

All was well until I have uploaded some code to put the device in to sleep mode.

As you’d expect, you cannot access the serial port to upload code (or do anything) when the device is asleep.

The instructions for the Adafruit board say to press the reset button twice to put the device into bootloader mode. Pressing this button just once seems to put the BSFrance board into bootloader mode (the LED pulses) but no serial device appears on my PC the board is connected to.

I am using Linux and watching the kernel ring buffer using dmesg, nothing at all happens.

The device is working and sat sending messages to TTN but I can’t gain access to it anymore to upload code.

Has anyone run in to this before with this board?

2 Likes

I guess ubuntu ? arduino IDE doesn’t work very well with 32U4 (virtual port)

Hi,

I’m using Debian and Atom IDE with Platform IO. Was all working fine until I put the device into sleep mode.

I have more of an update though. I plugged the board into a laptop (also running Debian) and it appeared in dmesg so I have install Atom & PlatformIO on there too. I do seem to be able to get somewhere with that, I can get it to at least attempt to upload. Off home now so I’ll look at this tomorrow.

I’m wondering if my code is too large for the limited memory of that board now.

So to finish my own thread off :slight_smile: I’ve fixed this now.

The answer was to just keep trying to upload the sketch and pressing the reset button at exactly the right times.

Using Atom & PlatformIO plugin, I pressed reset once (the white LED pulses), then clicked the upload button on the PlatformIO control bar, then in the command line box, waited for the message “waiting for upload port”. As soon as that message appeared, I pressed the reset button again once and the upload started.

My board is now happily sending messages to TTN again so I’m happy.

2 Likes

Just a small question: Which library did you use? I have currently Problems to flash my BSFrance Lora32u4 with the Arduino LMIC. Can you share your code?

By the way: I had the same problem with the serial port. It ended in using my AVR ISP programmer to avoid problems with the software serial. The serial port seems to be pretty unstable.

I’m using the LMIC-Arduino library:

This is my code, it’s basically the OTA example code with some stuff added to read from a BMP085 sensor and send data in Cayenne LPP format to TTN:

#include <avr/sleep.h>
#include <avr/wdt.h>
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include “LowPower.h”
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <Arduino.h>

int sleepcycles = 75; // every sleepcycle will last 8 secs, total sleeptime will be sleepcycles * 8 sec
bool joined = false;
bool sleeping = false;
#define LedPin 13
#define VBATPIN A9

static const u1_t DEVEUI[8] = { }; //LSB
static const u1_t APPEUI[8] = { }; //LSB

static const u1_t APPKEY[16] = { }; //MSB
Adafruit_BMP085 bmp;

static void initfunc (osjob_t*);

// provide APPEUI (8 bytes, LSBF)
void os_getArtEui (u1_t* buf) {
memcpy(buf, APPEUI, 8);
}

// provide DEVEUI (8 bytes, LSBF)
void os_getDevEui (u1_t* buf) {
memcpy(buf, DEVEUI, 8);
}

// provide APPKEY key (16 bytes)
void os_getDevKey (u1_t* buf) {
memcpy(buf, APPKEY, 16);
}

static osjob_t sendjob;
static osjob_t initjob;

// Pin mapping is hardware specific.
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 8,
.rxtx = LMIC_UNUSED_PIN,
.rst = 4, // Needed on RFM92/RFM95? (probably not) D0/GPIO16
.dio = {7, 6, LMIC_UNUSED_PIN}, // Specify pin numbers for DIO0, 1, 2
// connected to D7, D6, -
};

float getBatVoltage() {
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2; // Voltage is devided by two by bridge resistor so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
Serial.print("VBat: " ); Serial.println(measuredvbat);
return measuredvbat;
}

void onEvent (ev_t ev) {
int i,j;
switch (ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F(“EV_SCAN_TIMEOUT”));
break;
case EV_BEACON_FOUND:
Serial.println(F(“EV_BEACON_FOUND”));
break;
case EV_BEACON_MISSED:
Serial.println(F(“EV_BEACON_MISSED”));
break;
case EV_BEACON_TRACKED:
Serial.println(F(“EV_BEACON_TRACKED”));
break;
case EV_JOINING:
Serial.println(F(“EV_JOINING”));
break;
case EV_JOINED:
Serial.println(F(“EV_JOINED”));
// Disable link check validation (automatically enabled
// during join, but not supported by TTN at this time).
LMIC_setLinkCheckMode(0);
digitalWrite(LedPin,LOW);
// after Joining a job with the values will be sent.
joined = true;
break;
case EV_RFU1:
Serial.println(F(“EV_RFU1”));
break;
case EV_JOIN_FAILED:
Serial.println(F(“EV_JOIN_FAILED”));
break;
case EV_REJOIN_FAILED:
Serial.println(F(“EV_REJOIN_FAILED”));
// Re-init
os_setCallback(&initjob, initfunc);
break;
case EV_TXCOMPLETE:
sleeping = true;
if (LMIC.dataLen) {
// data received in rx slot after tx
// if any data received, a LED will blink
// this number of times, with a maximum of 10
Serial.print(F("Data Received: "));
Serial.println(LMIC.frame[LMIC.dataBeg],HEX);
i=(LMIC.frame[LMIC.dataBeg]);
// i (0…255) can be used as data for any other application
// like controlling a relay, showing a display message etc.
if (i>10){
i=10; // maximum number of BLINKs
}
for(j=0;j<i;j++)
{
digitalWrite(LedPin,HIGH);
delay(200);
digitalWrite(LedPin,LOW);
delay(400);
}
}
Serial.println(F(“EV_TXCOMPLETE (includes waiting for RX windows)”));
delay(50); // delay to complete Serial Output before Sleeping

  // Schedule next transmission
  // next transmission will take place after next wake-up cycle in main loop
  break;
case EV_LOST_TSYNC:
  Serial.println(F("EV_LOST_TSYNC"));
  break;
case EV_RESET:
  Serial.println(F("EV_RESET"));
  break;
case EV_RXCOMPLETE:
  // data received in ping slot
  Serial.println(F("EV_RXCOMPLETE"));
  break;
case EV_LINK_DEAD:
  Serial.println(F("EV_LINK_DEAD"));
  break;
case EV_LINK_ALIVE:
  Serial.println(F("EV_LINK_ALIVE"));
  break;
default:
  Serial.println(F("Unknown event"));
  break;

}
}

void do_send(osjob_t* j) {
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F(“OP_TXRXPEND, not sending”));
} else {
// Prepare upstream data transmission at the next possible time.
float vbat = getBatVoltage();
int vbatint = (int)(vbat*100);
Serial.print("vbatint: " ); Serial.println(vbatint);
uint8_t message[12];
message[0] = 0x01;
message[1] = 0x02;
message[2] = (uint8_t)highByte(vbatint);
message[3] = (uint8_t)lowByte(vbatint);
int pressure = (int)(bmp.readPressure() / 10);

message[4] = 0x02;
message[5] = 0x73;
message[6] = (uint8_t)highByte(pressure);
message[7] = (uint8_t)lowByte(pressure);

int temperature = (int)((bmp.readTemperature() * 100)/10);

message[8] = 0x03;
message[9] = 0x67;
message[10] = (uint8_t)highByte(temperature);
message[11] = (uint8_t)lowByte(temperature);

LMIC_setTxData2(1, message, sizeof(message), 0);
Serial.println(F("Sending: "));

}
}

// initial job
static void initfunc (osjob_t* j) {
// reset MAC state
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
// start joining
LMIC_startJoining();
// init done - onEvent() callback will be invoked…
}

void setup()
{
if (!bmp.begin()) {
Serial.println(“Could not find a valid BMP085 sensor, check wiring!”);
while (1) {}
}
delay(10000);
Serial.begin(9600);
Serial.println(F(“Starting”));
delay(10000);
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
os_setCallback(&initjob, initfunc);
LMIC_reset();
}

void loop()
{
// start OTAA JOIN
if (joined==false)
{

  os_runloop_once();

}
else
{
  do_send(&sendjob);    // Sent sensor values
  while(sleeping == false)
  {
    os_runloop_once();
  }
  sleeping = false;
  for (int i=0;i<sleepcycles;i++)
  {
      LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);    //sleep 8 seconds
  }
}

  digitalWrite(LedPin,((millis()/100) % 2) && (joined==false)); // only blinking when joining and not sleeping

}

2 Likes

Thank you. It seems that the LMIC from the Arduino Library manager caused my problems. I used the GitHub version and now it works.

yes there’s two libraries, one just called LMIC and one called LMIC-Arduino (or Arduino-LMIC, can’t remember which way round!).

I need your help, please. I tried your code but always stays in EV_JOIN_FAILED case. What I am doing wrong? I only are reading a Analog pin.

I am using an Adafruit Feather 32u4 with RFM95W. Could you help me, please?

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <LowPower.h>
#include <Arduino.h>


int sleepcycles = 75; // every sleepcycle will last 8 secs, total sleeptime will be sleepcycles * 8 sec
bool joined = false;
bool sleeping = false;
#define LedPin 13
int sensorPin = A5;

//////////// I deleted the EUIs and KEYs, but in my code I put them
 static const u1_t PROGMEM APPEUI[8]= {  };
//void os_getArtEui (u1_t* buf) {} 
 

// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]= { };
//void os_getDevEui (u1_t* buf) {}

static const u1_t PROGMEM NWKSKEY[16]= { }; 

static const u1_t PROGMEM APPKEY[16] = { };

static const u4_t DEVADDR = 0x26011453;



// provide APPEUI (8 bytes, LSBF)
void os_getArtEui (u1_t* buf) {
memcpy(buf, APPEUI, 8);
}

// provide DEVEUI (8 bytes, LSBF)
void os_getDevEui (u1_t* buf) {
memcpy(buf, DEVEUI, 8);
}

// provide APPKEY key (16 bytes)
void os_getDevKey (u1_t* buf) {
memcpy(buf, APPKEY, 16);
}

static void initfunc (osjob_t*);


//static uint8_t mydata[] = "Hello World";
static osjob_t sendjob;
static osjob_t initjob;


// Pin mapping

const lmic_pinmap lmic_pins = {
    .nss = 8, //6
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 4, //5
    .dio = {7, 6, LMIC_UNUSED_PIN}, // 7 6 11
};


void onEvent (ev_t ev) {
  int i,j;


    switch(ev) {
        case EV_SCAN_TIMEOUT:
            Serial.println(F("EV_SCAN_TIMEOUT"));
            break;
        case EV_BEACON_FOUND:
            Serial.println(F("EV_BEACON_FOUND"));
            break;
        case EV_BEACON_MISSED:
            Serial.println(F("EV_BEACON_MISSED"));
            break;
        case EV_BEACON_TRACKED:
            Serial.println(F("EV_BEACON_TRACKED"));
            break;
        case EV_JOINING:
            Serial.println(F("EV_JOINING"));
            break;
        case EV_JOINED:
            Serial.println(F("EV_JOINED"));
            LMIC_setLinkCheckMode(0);
            digitalWrite(LedPin,LOW);
          // after Joining a job with the values will be sent.
           joined = true;
            break;
        case EV_RFU1:
            Serial.println(F("EV_RFU1"));
            break;
        case EV_JOIN_FAILED:
            Serial.println(F("EV_JOIN_FAILED"));
            break;
        case EV_REJOIN_FAILED:
            Serial.println(F("EV_REJOIN_FAILED"));
            os_setCallback(&initjob, initfunc);
            break;
        case EV_TXCOMPLETE:
        sleeping = true;
   if (LMIC.dataLen) {
// data received in rx slot after tx
// if any data received, a LED will blink
// this number of times, with a maximum of 10
Serial.print(F("Data Received: "));
Serial.println(LMIC.frame[LMIC.dataBeg],HEX);
i=(LMIC.frame[LMIC.dataBeg]);
// i (0…255) can be used as data for any other application
// like controlling a relay, showing a display message etc.
if (i>10){
i=10; // maximum number of BLINKs
}
for(j=0;j<i;j++)
{
digitalWrite(LedPin,HIGH);
delay(200);
digitalWrite(LedPin,LOW);
delay(400);
}
}
   Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
delay(50); // delay to complete Serial Output before Sleeping

  // Schedule next transmission
  // next transmission will take place after next wake-up cycle in main loop
            break;
        case EV_LOST_TSYNC:
            Serial.println(F("EV_LOST_TSYNC"));
            break;
        case EV_RESET:
            Serial.println(F("EV_RESET"));
            break;
        case EV_RXCOMPLETE:
            // data received in ping slot
            Serial.println(F("EV_RXCOMPLETE"));
            break;
        case EV_LINK_DEAD:
            Serial.println(F("EV_LINK_DEAD"));
            break;
        case EV_LINK_ALIVE:
            Serial.println(F("EV_LINK_ALIVE"));
            break;
         default:
            Serial.println(F("Unknown event"));
            break;
    }
}

void convert_to_string(char * outStr, int length, double val){
    Serial.println(F("Converting..."));
    dtostrf(val,2,0,outStr);
    Serial.println(outStr);
}

void do_send(osjob_t* j) {
  uint8_t message[8];
    
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
int readVal=analogRead(sensorPin);
    convert_to_string(message,8,readVal);

Serial.print("Valor del sensor: " );
Serial.println(readVal);
//static uint8_t message[] = "Hello, world!";

 LMIC_setTxData2(1, message,3, 0);

//        LMIC_setTxData2(1, message, sizeof(message)-1, 0);
        Serial.println(F("Sending uplink packet..."));


}
}


// initial job
static void initfunc (osjob_t* j) {
// reset MAC state
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
// start joining
LMIC_startJoining();
// init done - onEvent() callback will be invoked…
}



void setup() {
  
     while (!Serial);
     delay(10000);
    Serial.begin(115200);
    Serial.println("Starting");
    delay(10000);
    os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
os_setCallback(&initjob, initfunc);
LMIC_reset();


  
}


void loop()
{
// start OTAA JOIN
if (joined==false)
{

  os_runloop_once();

}
else
{
  do_send(&sendjob);    // Sent sensor values
  while(sleeping == false)
  {
    os_runloop_once();
  }
  sleeping = false;
  for (int i=0;i<sleepcycles;i++)
  {
      LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);    //sleep 8 seconds
  }
}

  digitalWrite(LedPin,((millis()/100) % 2) && (joined==false)); // only blinking when joining and not sleeping
}

@aayk
please format your code … see How do I format my forum post?

Sorry, it was my first post. Thank you

and thank you for making this forum more beautifull :wink:

The correct library name is LMIC-Arduino.
Unfortunately the corresponding GitHub repository name is still arduino-lmic.

Did you tried to stop the ModemManager service? It takes the serial port on boot. I had to switch it off as udev rules doesn’t work anymore.