RFM95W transceiver module burning out at runtime

Hi!
I am working on a project where I interface a RFM95W (915MHz) transceiver to an Arduino Pro Mini 3.3V. I have removed the in-built voltage regulator on it and replaced it with MCP1702 (which has a 250mA max supply current). The regulator is powering the arduino, RFM95W and INA219. I am powering the setup with a 9V battery and using an INA219 to measure the battery voltage. DIO0 is connected to Pin 2 on the Promini (using the default pins).
This node communicates to a single channel gateway Dragino LG01-N (I am not using LoRaWAN. Just updating the data to a cloud via https). The gateway on receiving a packet from the node sends some data back to the node.
The node waits for the gateway and if the packet is received it goes to sleep for ā€˜xā€™ minutes (as set from the cloud) after which it again wakes up and re-transmits the data. If it does not receive any data from the gateway then it waits for 20secs and then goes to sleep for 1min.
For the node, I am using a 824-960-mhz-1710-2170-mhz-2-3-dbi-magetic-mount-antenna connected to the RFM95W via an SMA connector and a 3m long coaxial cable.

The problem:
Now, this setup is running great at first (the RSSI of the received packet is a bit weak, -50 to -70 @ 1m distance from the gateway). However, the problem occurs after I leave the node to run for more than 15-16hrs continuously. The node suddenly stops receiving data from the gateway. It transmits just fine though (the gateway is able to receive). But it will not receive any data.
After I checked the "dio0 pin of the RFM95W module, I found out that it is always HIGH and when I check it with a multimeter (on continuity test mode), it shows a short to Vcc of the same module.
Does this mean that the module gets damaged somehow while running? Is there a way to fix this? This has happened twice with the same circuit. The last reported battery voltage seems to be 8.7V before the node stops receiving, so the battery does not seem to be the issue here.
The antenna could be the problem here but Iā€™m not sure.
Here is the code for the arduino pro mini 3.3V:

#include <LowPower.h>
#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_INA219.h>

/* CONSTANTS (DO NOT MODIFY THESE) */
#define ON                           true
#define OFF                          false
#define RCV_BUFFER_SIZE_MAX          100
/* CONSTANTS */

/* USER CONFIGURABLE PARAMETERS */
#define USB_DEBUGGING                ON //Set as ON to use serial monitor debugging. Set as OFF during standalone operation
#define USB_DEBUGGING_BAUD_RATE      115200 //Set the baud rate for USB debugging
#define DEVICE_ID                    1 //Identity of the node. Same ID should be present in the cloud database for it to work
#define DEFAULT_CALL_HOME_FREQUENCY  1 //Set the default call home frequency for this node. This frequency will be used until data from cloud is synced after power-up
#define FAILSAFE_CALL_HOME_FREQUENCY 1 //Call Home Frequency if anything goes wrong during communication
#define DEFAULT_STATE                OFF //Default state of remote device on first power-up or after reset
#define SPREADING_FACTOR             10 //Set spreading factor for radio. Should be the same as Gateway
#define PREAMBLE_LENGTH              8 //Set the preamble length for radio. Should be the same as Gateway
#define SYNC_WORD                    0x34 //Set sync word for radio. Should be the same as Gateway (in decimal)
#define RADIO_FREQUENCY              915E6 //Set the radio frequency. Should be same as Gateway. Keep this at 915MHz (915E6) for best results
#define RADIO_TX_POWER               20 //2(min) - 20(max). HIgher number for greater range (!!!more power consumption)
#define RCV_TIMEOUT                  20000 //Set the time for which this node will wait for Gateway in receive mode in milli-seconds
#define ON_WIRE_PIN                  8 //Set the pin corresponding to ON-WIRE of remote device. !!!Need to change HW connection to change this!!!
#define OFF_WIRE_PIN                 7 //Set the pin corresponding to OFF-WIRE of remote device. !!!Need to change HW connection to change this!!!
#define ON_OFF_SIG_DURATION          3000 //Duration for which ON or OFF wire is shorted to GND in milli-seconds
/* USER CONFIGURABLE PARAMETERS */

/* INIT VALUES */
#define INIT_VOLTAGE                 0.0 //in Volts
#define INIT_CURRENT                 0.0 //in mA (milli-amperes)
/* INIT VALUES */

/*Global Variables */
const int device_id = DEVICE_ID; // ID of this End node
const float cutoff_volt = 3.5; //Device goes to sleep until next power-up at or below this voltage
float volt = INIT_VOLTAGE;   // Default voltage.
float amp = INIT_CURRENT;   // Default current.
bool device_state = DEFAULT_STATE; //Default Device State
int call_home_freq = DEFAULT_CALL_HOME_FREQUENCY; //Default Call Home Frequency
int sleep_flag = 0;
int count = 0;
int buff_size = RCV_BUFFER_SIZE_MAX;
char rcv_buffer[RCV_BUFFER_SIZE_MAX];
bool data_changed_flag = false;
/*Global Variables */

/*INA219 voltage/current sensor object */
Adafruit_INA219 ina219;
/*INA219 voltage/current sensor object */

/*  Function    : LoRa_rxMode()
 *  Return Val  : None
 *  Parameters  : None
 *  Description : Changes LoRa transceiver to receive mode and activates invert I,Q signals
 */ 
void LoRa_rxMode() {
  LoRa.enableInvertIQ();                // active invert I and Q signals
  LoRa.receive();                       // set receive mode
}

/*  Function    : LoRa_txMode()
 *  Return Val  : None
 *  Parameters  : None
 *  Description : Changes LoRa transceiver to transmit mode and deactivates invert I,Q signals
 */ 

void LoRa_txMode() {
  LoRa.idle();                          // set standby mode
  LoRa.disableInvertIQ();               // normal mode
}

/*  Function    : LoRa_sendData()
 *  Return Val  : Type: bool
 *                'true' - when transmission succeeds
 *                'false' - when transmission fails
 *  Parameters  : id (int) - device id of the LoRa node
 *                call_home_freq (int) - call home frequency of the LoRa node in minutes
 *                state (bool) - current state of the device, 'true' means ON and 'false' means OFF
 *                volt (float) - last read voltage of the battery upto 2 decimal places
 *  Description : Transmits data to gateway
 */ 

bool LoRa_sendData(int id, int call_home_freq, bool state, float volt)
{
  // compose and send packet
  LoRa.beginPacket();
  LoRa.print("<");
  LoRa.print(id);
  LoRa.print(">CHF=");
  LoRa.print(call_home_freq);
  LoRa.print("&State=");
  LoRa.print(state);
#if USB_DEBUGGING == ON
  Serial.println(state);
#endif
  LoRa.print("&Voltage=");
  LoRa.print(volt);
  if (LoRa.endPacket())
  {
#if USB_DEBUGGING == ON
    Serial.println("Sent Data");
#endif
    return true;
  }
  else
  {
#if USB_DEBUGGING == ON
    Serial.println("Could not send data");
#endif
    return false;
  }
}

/*  Function    : LoRa_sendData()
 *  Return Val  : Type: char *
 *                returns the extracted value as character array corresponding to the key
 *  Parameters  : key (char *) - the field whose value is to be extracted 
 *  Description : extracts the value from received packet corresponding to a key (for e.g. "CHF=" or "state=").
 */ 
 
char * extract_param(char *key)
{
  int index_start = 0, index_end = 0, i, j;
  char param[5];
#if USB_DEBUGGING == ON
  Serial.print("Key =");
  Serial.println(key);
#endif
  index_start = strstr(rcv_buffer, key) + strlen(key);
#if USB_DEBUGGING == ON
  Serial.print("Start Index =");
  Serial.println(index_start);
#endif
  index_end = strstr(rcv_buffer, '&');
#if USB_DEBUGGING == ON
  Serial.print("End Index =");
  Serial.println(index_end);
#endif

  for (i = index_start, j = 0; i < index_end; i++, j++)
  {
    param[j] = rcv_buffer[i];
  }
  param[j] = '\0';
#if USB_DEBUGGING == ON
  Serial.print("Parameter =");
  Serial.println(param);
#endif
  return param;
}

/*  Function    : onReceive()
 *  Return Val  : None
 *  Parameters  : packetSize (int) - Size of the received packet
 *  Description : Receiver callback function. Processed whenever a packet is received by the node.
 */ 

void onReceive(int packetSize) {
  //int packetSize = LoRa.parsePacket();
  // received a packet
  char *temp;
#if USB_DEBUGGING == ON
  Serial.print("Packet Size = ");
  Serial.println(packetSize);
#endif
  if (packetSize) {
    buff_size = packetSize <= RCV_BUFFER_SIZE_MAX ? packetSize : RCV_BUFFER_SIZE_MAX;
#if USB_DEBUGGING == ON
    Serial.println(buff_size);
    Serial.print("Received packet '");
#endif

    // read packet
    for (int i = 0; i < buff_size; i++) {
      rcv_buffer[i] = (char)LoRa.read();
#if USB_DEBUGGING == ON
      Serial.print(rcv_buffer[i]);
#endif
    }
#if USB_DEBUGGING == ON
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
#endif
    //call_home_freq=atoi(extract_param("CHF="));

    //Extracting Device ID
    temp = strtok(rcv_buffer, "=");
#if USB_DEBUGGING == ON
    Serial.print("First token=");
    Serial.println(temp);
#endif
    if (!strcmp(temp, "DevID")) //If received packet does not contain DevID as header then ignore it.
    {
#if USB_DEBUGGING == ON
      Serial.print("Value=");
#endif
      temp = strtok(NULL, "&");
#if USB_DEBUGGING == ON
      Serial.println(temp);
#endif
      if (atoi(temp) == DEVICE_ID)
      {

        //Extracting Call Home Frequency
        temp = strtok(NULL, "=");
#if USB_DEBUGGING == ON
        Serial.print("Second token=");
        Serial.println(temp);
#endif
        if (!strcmp(temp, "CHF")) //If Acknowledgement is NOT received and gateway sends fresh data from cloud
        {
#if USB_DEBUGGING == ON
          Serial.print("Value=");
#endif
          temp = strtok(NULL, "&");
#if USB_DEBUGGING == ON
          Serial.println(temp);
#endif
          call_home_freq = atoi(temp);
          call_home_freq = call_home_freq > 0 ? call_home_freq : FAILSAFE_CALL_HOME_FREQUENCY;
#if USB_DEBUGGING == ON
          Serial.print("Call Home Freq = ");
          Serial.println(call_home_freq);
          //Serial.println(sleep_flag);
#endif
        }

        //Extracting Device State
        temp = strtok(NULL, "=");
#if USB_DEBUGGING == ON
        Serial.print("Third token=");
        Serial.println(temp);
#endif
        if (!strcmp(temp, "State")) //If Acknowledgement is NOT received and gateway sends fresh data from cloud
        {
#if USB_DEBUGGING == ON
          Serial.print("Value=");
#endif
          temp = strtok(NULL, "\0");
#if USB_DEBUGGING == ON
          Serial.println(temp);
#endif
          if(device_state != atoi(temp))
          {
            device_state = atoi(temp);
            data_changed_flag = true;
          }
          else
          {
            data_changed_flag = false;
          }
#if USB_DEBUGGING == ON
          Serial.print("Device State = ");
          Serial.println(device_state);
#endif          
        }
        
        if (!strcmp(temp, "ACK"))
        {
          data_changed_flag = false;
        }
        else
        {
          //Do nothing
        }
        sleep_flag = 1;
      }
    } // Header Verification end
    else
    {
      //Do nothing as data received is not meant for this node.
    }
  }// Packet size check end
  else
  {
    //Do nothing
  }
} //onReceive() end


/*  Function    : setup()
 *  Return Val  : None
 *  Parameters  : None
 *  Description : First function executed after power-up. All modules are initialised here.
 */ 

void setup() {
  pinMode(ON_WIRE_PIN, OUTPUT);
  pinMode(OFF_WIRE_PIN, OUTPUT);

  digitalWrite(ON_WIRE_PIN, LOW);
  digitalWrite(OFF_WIRE_PIN, LOW);

#if USB_DEBUGGING == ON
  Serial.begin(USB_DEBUGGING_BAUD_RATE);
  while (!Serial);
#endif

#if USB_DEBUGGING == ON
  Serial.println("Initialised serial...");
  delay(100);
#endif

  LoRa.setPins(10, 9, 2);
  //Initialize the INA219. Will fail if jumpers are not connected on the board
  if (!ina219.begin()) {
#if USB_DEBUGGING == ON
    Serial.println("Failed to find INA219 chip");
#endif
    {
      delay(10);
    }
  }
  //use a lower 16V, 400mA range (higher precision on volts and amps)
  ina219.setCalibration_16V_400mA();

#if USB_DEBUGGING == ON
  Serial.println("Measuring voltage and current with INA219 ...");

  //Initialise LoRa module
  Serial.println("LoRa Sender");
#endif

  if (!LoRa.begin(RADIO_FREQUENCY)) {
#if USB_DEBUGGING == ON
    Serial.println("Starting LoRa failed!");
#endif
    while (1);
  }

  //Congifure LoRa module
  LoRa.setSyncWord(SYNC_WORD);
  LoRa.setSpreadingFactor(SPREADING_FACTOR);
#if USB_DEBUGGING != ON
  LoRa.setTxPower(RADIO_TX_POWER);
#else
  LoRa.setTxPower(2);
#endif
  // Uncomment the next line to disable the default AGC and set LNA gain, values between 1 - 6 are supported
  // LoRa.setGain(6);
  // register the receive callback
  LoRa.onReceive(onReceive);
}

/*  Function    : loop()
 *  Return Val  : None
 *  Parameters  : None
 *  Description : Main function executing all routines.
 */ 
 
void loop() {
  float busvoltage = 0; //Store the battery voltage
  unsigned long startedWaiting; //Store the time at which receive window is opened
#if USB_DEBUGGING == ON
  Serial.print("Sending packet: ");
  Serial.println(count);
#endif

  /* Measuring battery voltage */
  ina219.powerSave(false);
  delay(10);
  busvoltage = ina219.getBusVoltage_V();
  ina219.powerSave(true);
  /* Measuring battery voltage */

#if USB_DEBUGGING != ON
  
  if (busvoltage >= cutoff_volt)
  {
#endif
    /* If voltage is greater than cutoff then begin normal operation */
    LoRa_txMode();
    while (!LoRa_sendData(device_id, call_home_freq, device_state, busvoltage)) {
#if USB_DEBUGGING == ON
      Serial.println("Sending failed!");
#endif
      delay(10);
    }
    count++;
    LoRa_rxMode();
    startedWaiting = millis();
#if USB_DEBUGGING == ON
    Serial.println("Waiting for Gateway");
#endif
    while (!sleep_flag && (millis() - startedWaiting <= RCV_TIMEOUT)) //sleep_flag is set inside receiver callback function onReceive()
    {
      /*Loop will exit if either data is received from gateway or configured timeout is acheived */
    }
    if (!sleep_flag)
    {
#if USB_DEBUGGING == ON
      Serial.println("Did not receive data!");
#endif
      call_home_freq = FAILSAFE_CALL_HOME_FREQUENCY; //If no data received from gateway then change callback frequency to failsafe value
    }
    else
    {
      LoRa.sleep(); //Put LoRa module to sleep
      if (data_changed_flag) //data_changed_flag is set whenever device state received from cloud is different from current device state
      {
        if (device_state) //is device state ON
        {
          //Set On wire of remote device to GND for 3 secs
          digitalWrite(ON_WIRE_PIN, HIGH);
          delay(ON_OFF_SIG_DURATION);
          digitalWrite(ON_WIRE_PIN, LOW);
        }
        else
        {
          //Set Off wire of remote device to GND for3 secs
          digitalWrite(OFF_WIRE_PIN, HIGH);
          delay(ON_OFF_SIG_DURATION);
          digitalWrite(OFF_WIRE_PIN, LOW);
        }
        data_changed_flag = false; //Reset Flag after changing state
      }
    }
#if USB_DEBUGGING == ON
    Serial.println("Going to Sleep");
#endif
    delay(10);
    sleep_flag = 0;

    /* Sleep count is calculated using a 4 second interval
     *  1 minute has 15 sleep cycles (60s/4s)
     *  For a call home freqeuncy of 5 minutes, the node should sleep for 5*15 cycles
     *  The additional "(2 * call_home_freq)" is for compensating the Arduino's clock error
     */
    int sleep_count = (call_home_freq * 15) - (2 * call_home_freq);
    while (sleep_count)
    {
      LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF);
      sleep_count--;
    }
#if USB_DEBUGGING == ON
    Serial.println("Waking up from Sleep");
#endif
    delay(100); //Giving time to the CPU to settle down after waking
    //LoRa.receive();
#if USB_DEBUGGING != ON
  }//If battery is not dead

  else
  {
    /* If voltage is less than cutoff then sleep until next forced power up or battery change*/
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  }
#endif
}

Has anyone ever encountered this before with a RFM95W module?

Hi,

Instead of a continuity test do a DIODE test in both directions, to make sure you are not detecting the protection diode between the pin and Vcc.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

The DIO0 pin on the RFM95W is used as a logic out pin, it goes logic high when some internal event of the RFM95W occurs, such as transmission complete or received a packet.

Measure its state with a multimeter on voltage, not continuity.

Regardless of that, DIO0 it bieng high most of the time might be normal.

Try using an antenna designed just for that particular frequency, those so called multi frequency things might not be a good match.

Actually the continuity test and the diode test are on the same option on my multimeter. Regardless, on a working RFM95W module, there is no continuity between the Vcc pin and the dio0 pin (when the module is removed from the circuit). However, the module that is not receiving the data has Vcc and dio0 pin shorted.

Blockquote The DIO0 pin on the RFM95W is used as a logic out pin, it goes logic high when some internal event of the RFM95W occurs, such as transmission complete or received a packet.

I understand.

But is the VCC and dio0 pin supposed to be a short circuit? When I measure it in the voltage mode, it has the same voltage as Vcc always.
What I am suspecting is maybe the module got damaged somehow because of repeated use with an incompatible antenna. What do you think?

Blockquote Try using an antenna designed just for that particular frequency, those so called multi frequency things might not be a good match.

I will also try with a wire antenna of 7.8cm.

Very unlikly.

I cannot see how possible problems with the antenna or on the TX side could damage one of the DIO pins.

This happened while the LoRa node was running at night. No other possible causes coming to mind other than antenna. Because I am not driving anything with the circuit, so there are no possible voltage spikes or anything else. The circuit was also not touched. It is built on a perfboard with soldered wires. I have thoroughly tested for any dry solder or disconnections and have not found any.
Funny thing is when I try to check the voltage between the Vcc and the Dio0 pin, it actually received the packet and correctly. Do you know how this could happen?

Whilst a shorted DIO1 pin, soldering fault, wiring fault etc, could cause problems with either transmit or receive, I would not think it possible for the antenna to cause that problem, unless perhaps you connected a wire between the antenna and DIO0 pin.

That would suggest that the the microcontroller pin is not correctly connected to the DIO0 pin on the LoRa module.

A generic fault whereby the antenna is somehow affecting the DIO0 pin and has damadged two modules seems weird. LoRa modules have been around since 2014, I have never heard of that 'fault'.

Your probably trying to fix a problem at too high a level, if you think there are issues with a module always failing in 15-16 hours it would be easier to test it using the basic send and transmit examples in the library you are using.

But would that not cause a problem if I use another RFM95W module? Apparently it is receiving just fine when I replace it with another module in the same circuit.

Ok. So, I reoriented the RFM95W on the perf board, and resoldered the connections appropriately. I am also using a 915MHz LoRa antenna this time around.
I used a new RFM95W module and it was working fine until again it stopped working suddenly (stuck at sending). After I reset the arduino, this time around the LoRa module won't even initialise. Now when I check the module, the MOSI and MISO pins seems to be shorted. I don't know what the hell is happening! How can two pins become shorted while the circuit is running? The node was running fine for more than 24 hrs continuously.
Could it be because the RFM95W module does not have a metal cap (for RF shielding) and is placed too close to the Arduino Pro Mini? Please help!!

Yes you are correct! I have changed the antenna to a 915MHz one and it still causes problems!

Lots of RFM95s dont have caps and they dont blow up.

If you keep burning modules, that strongly suggests you have them wired wrong or there is some sort of problem with the power supply.

And when you say 'shorted' what is the measured resistance of this short ?

1 Like

The older module in which Vcc and Dio0 was shorted has a resistance of 12ohm.
The newer one in which the MOSI and MISO pins are shorted showed a resistance of 14ohms when I first recovered it but is now showing around 65ohms.

I am using a 9V battery and the voltage regulator is a MCP1702 that has a max supply current of 250mA.

Do you think I should change the voltage regulator?
I have also attached the schematic that I have used (using MCP1702 instead of MCP1700):


The MCP1702 is also powering the INA219 sensor and the Arduino is switching to BC337 transistors (1K resistor between arduino pins and base of transistors) that are not connected to any load for now.

Show us a picture of it all wired up ?


Top view


Bottom view

Some additional info that I remember observing-

  1. The RFM95W module always burns out with a short between adjacent pins. In the older circuit when the main IC on the module was near the Arduino, the DIO0 pin and Vcc where shorted. In the newer circuit, with the orientation of the board reversed and connections changed, the MISO and MOSI pins were shorted.
  2. I had also powered this circuit with a 12V 5A SMPS. The SMPS outputs 12.25V (as measured by the INA219) while the Arduino is running and the RFM95W is sleeping. However, on a few occasions the voltage dropped to 11.2V (again measured by INA219). Since the SMPS has a max rating of 5A (which is much more than what is needed), should the voltage suddenly drop like this? Could this have anything to do with the MCP1702 regulator? Can a linear regulator cause a module to burn out like this?

I have checked the circuit for any shorts or wrong connections quite a few times. Maybe I am overlookng something obvious here but at the moment I can't think of anything other than a faulty MCP1702. @srnet What do you think? Or do you have anything specific in mind that I should check about the connections?

**My biggest confusion is how the RFM95 module burns out after running for more than 25-30hrs (with a 10-15min sleep cycle, so around 100-120 transmissions and receptions) **