RFM9x LoRa Radio returns 0 on every register

Hello,
Im using a RFM9x LoRa Radio module from Adafruit (product 3073) and I cannot get it to work with my Arduino Micro using the RadioHead library, which is recommended on the AdaFruit product page.

I get the "LoRa radio init failed" error.

Looking in the source code of the library I saw that the code errors out in the RH_RF95::init() function, where it attempts to set a mode and read it back to verify the write:

    if (spiRead(RH_RF95_REG_01_OP_MODE) != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE))
    {
        Serial.println(spiRead(RH_RF95_REG_01_OP_MODE), HEX);
        return false; // No device present?
    }

I triple checked the wiring and it looks fine to me, so I wrote a small test sketch to read the first 6 registers of the lora module, and all of them come back as 0, despite all of them having non-zero reset values:

void setup() {
  pinMode(7, OUTPUT); // set the SS pin as an output
  SPI.begin();         // initialize the SPI library
  Serial.begin(115200);
}

void loop() {

  digitalWrite(7, LOW);            // set the SS pin to LOW
  
  for(byte reg = 0; reg <= 6; reg++) {
    Serial.print(reg);
    Serial.print("\t");
    Serial.println(SPI.transfer(reg));
    delay(100); 
  }

  digitalWrite(7, HIGH);           // set the SS pin HIGH
  Serial.println("--------------------");
  delay(1000); 
}

Output of above sketch is:
0 0
1 0
2 0
3 0
4 0
5 0
6 0

Below I attach a picture of my setup, the LoRa module is attached to the default SPI interface:

Connections are:
LoRa CS --- Micro pin 7 (PE6)
LoRa MISO --- Micro pin MISO (PB3)
LoRa MOSI--- Micro pin MOSI (PB2)
LoRa SCK --- Micro pin SCK (PB1)

I tested all of this with two LoRa modules, both brand new, both give the same result.

What am I doing wrong?

where did you get the SPI pin connections from?
maybe worth doing a web search for Arduino Micro pinout?
I also find the following program useful

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-spi-communication-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

//Find the default SPI pins for your board
//Make sure you have the right board selected in Tools > Boards
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(3000);
  Serial.print("MOSI: ");
  Serial.println(MOSI);
  Serial.print("MISO: ");
  Serial.println(MISO);
  Serial.print("SCK: ");
  Serial.println(SCK);
  Serial.print("SS: ");
  Serial.println(SS);  
  Serial.print("SDA: ");
  Serial.println(SDA);  
  Serial.print("SCL: ");
  Serial.println(SCL);  
}

void loop() {
  // put your main code here, to run repeatedly:
}


I don't have a Arduino micro but the Arduino Pro Micro reports

MOSI: 16
MISO: 14
SCK: 15
SS: 17
SDA: 2
SCL: 3

which matches the pinout I have

1 Like

I have taken the pins's number from the official micro pinout:

Your program on my micro outputs:

MOSI: 16
MISO: 14
SCK: 15
SS: 17
SDA: 2
SCL: 3

Apart from the CS (SS) pin which I manually control they were all correct.

That program to read the registers of the LoRa device looks a bit weird, try this;

#include <SPI.h>

#define NSS 10

void setup() 
{
  pinMode(NSS, OUTPUT); // set the SS pin as an output
  SPI.begin();          // initialize the SPI library
  Serial.begin(115200);
}

void loop() 
{
  uint8_t regdata;
  
 for(byte reg = 0; reg <= 6; reg++) {
    Serial.print(reg);
    Serial.print("\t");
    regdata = readRegister(reg);
    Serial.println(regdata,HEX);
    delay(100); 
  }

  Serial.println("--------------------");
  delay(1000); 
}


uint8_t readRegister(uint8_t address)
{
  uint8_t regdata;
  digitalWrite(NSS, LOW);                    //set NSS low
  SPI.transfer(address & 0x7F);             //mask address for read
  regdata = SPI.transfer(0);                //read the byte
  digitalWrite(NSS, HIGH);                   //set NSS high
  return regdata;
}

connected a RFM95W to a Arduino Pro Micro using the following

// Pro Micro with RPi HAT RFM95W
// Pro Micro SCK  pin 15  to RFM95_pin SCK
// Pro Micro MISO pin 14  to RFM95_pin MISO
// Pro Micro MOSI pin 16  to RFM95_pin MOSI
// Pro Micro pin 7 to RFM95 SS
// Pro Micro pin 6 to RFM95 Reset
// Pro Micro pin 5 to RFM95 DIO0
// Pro Micro pin 4 to RFM95 DIO1

connected to LoRaWAN V3 server OK

Starting
CFG_eu868
Packet queued
315191: EV_JOINING
753520: EV_TXSTART
1075931: EV_JOINED
netid: 19
devaddr: xxxxxxxx
AppSKey: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
NwkSKey:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
1077389: EV_TXSTART
1397477: EV_TXCOMPLETE (includes waiting for RX windows)
1462012: EV_TXSTART
1843597: EV_TXCOMPLETE (includes waiting for RX windows)
Packet queued
5977015: EV_TXCOMPLETE (includes waiting for RX windows)
9728046: EV_TXSTART
Packet queued
10049120: EV_TXCOMPLETE (includes waiting for RX windows)
Received 8 bytes of payload
 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x9
13800280: EV_TXSTART
Packet queued
14182667: EV_TXCOMPLETE (includes waiting for RX windows)

will try with radiohead library

tried programs from post 1 @thiird and post 4 @srnet both display

0	0
1	0
2	0
3	0
4	0
5	0
6	0
--------------------

both using NSS pin 7

I did change the readRegister to the below code, it originally had digitalWrite(10, LOW); etc.

uint8_t readRegister(uint8_t address)
{
  uint8_t regdata;
  digitalWrite(NSS, LOW);                    //set NSS low
  SPI.transfer(address & 0x7F);             //mask address for read
  regdata = SPI.transfer(0);                //read the byte
  digitalWrite(NSS, HIGH);                   //set NSS high
  return regdata;
}

And it works here, but the OPs code in post #1 does not.

And here is a program that prints all the registers, you do need to set the;

#define NSS 10 //lora device select

To match your own setup.

/*******************************************************************************************************
  Program Operation - This program is stand alone, it is not necessary to install a LoRa library to use
  it. This test program is for the SX127X LoRa devices.

  The program checks that a lora device can be accessed by doing a test register write and read.
  If there is no device found a message is printed on the serial monitor. The contents of the registers
  from 0x00 to 0x7F are printed. 

  The Arduino pin number that NSS on the LoRa device is connected to must be specified in #define NSS
  line below. Leave the NRESET and DIOx pins not connected.

  Typical printout;

  2_Register_Test Starting
  LoRa Device found
  Device version 0x12
  Frequency at Start 434000000
  Registers at Start
  Reg    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
  0x00  00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A
  0x10  FF 70 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
  0x20  00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
  0x30  90 40 40 00 00 0F 00 00 00 F5 20 82 FD 02 80 40
  0x40  00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
  0x50  14 00 00 10 00 00 00 0F E0 00 0C FD 06 00 5C 78
  0x60  00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B
  0x70  D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00

  Note: An SX1272 will report as version 0x22 and the frequency at power up is 915000000hz.

  Serial monitor baud rate is set at 115200.
*******************************************************************************************************/

const uint8_t REG_FRMSB = 0x06;                 //register number for setting and reading frequency, high byte
const uint8_t REG_FRMID = 0x07;                 //register number for setting and reading frequency, mid byte
const uint8_t REG_FRLSB = 0x08;                 //register number for setting and reading frequency, low byte
const uint8_t REG_VERSION = 0x42;               //register containg version number of device


//*********  Setup hardware pin definition here ! **************

#define NSS 10                                  //lora device select

//**************************************************************/


#include <SPI.h>

uint32_t frequency;


void setup()
{
  Serial.begin(115200);
  Serial.println(F("2_Register_Test Starting"));

  SPI.begin();
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

  //The begin function setups the hardware pins used by device and then checks if device is found

  if (begin(NSS))
  {
    Serial.println(F("LoRa Device found"));
  }
  else
  {
    Serial.println(F("No device responding"));
  }

  Serial.print(F("Device version 0x"));
  uint8_t deviceversion = readRegister(REG_VERSION);
  if (deviceversion < 0x10)
  {
    Serial.print(F("0"));
  }
  Serial.println(deviceversion, HEX);

  frequency = getFreqInt();                  //read the set frequency following a reset
  Serial.print(F("Frequency at Start "));
  Serial.println(frequency);

  Serial.println(F("Registers at Start "));   //show the all registers following a power up
  printRegisters(0x00, 0x7F);
}


void loop()
{
  
}


uint8_t readRegister(uint8_t address)
{
  uint8_t regdata;
  digitalWrite(NSS, LOW);                    //set NSS low
  SPI.transfer(address & 0x7F);              //mask address for read
  regdata = SPI.transfer(0);                 //read the byte
  digitalWrite(NSS, HIGH);                   //set NSS high
  return regdata;
}


void writeRegister(uint8_t address, uint8_t value)
{
  digitalWrite(NSS, LOW);                    //set NSS low
  SPI.transfer(address | 0x80);              //mask address for write
  SPI.transfer(value);                       //write the byte
  digitalWrite(NSS, HIGH);                   //set NSS high
}


uint32_t getFreqInt()
{
  //get the current set LoRa device frequency, return as long integer

  uint8_t Msb, Mid, Lsb;
  uint32_t uinttemp;
  float floattemp;
  Msb = readRegister(REG_FRMSB);
  Mid = readRegister(REG_FRMID);
  Lsb = readRegister(REG_FRLSB);
  floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb);
  floattemp = ((floattemp * 61.03515625) / 1000000ul);
  uinttemp = (uint32_t)(floattemp * 1000000);
  return uinttemp;
}


void printRegisters(uint16_t Start, uint16_t End)
{
  //prints the contents of lora device registers to serial monitor

  uint16_t Loopv1, Loopv2, RegData;

  Serial.print(F("Reg    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F"));
  Serial.println();

  for (Loopv1 = Start; Loopv1 <= End;)
  {
    Serial.print(F("0x"));
    if (Loopv1 < 0x10)
    {
      Serial.print(F("0"));
    }
    Serial.print((Loopv1), HEX);
    Serial.print(F("  "));
    for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
    {
      RegData = readRegister(Loopv1);
      if (RegData < 0x10)
      {
        Serial.print(F("0"));
      }
      Serial.print(RegData, HEX);
      Serial.print(F(" "));
      Loopv1++;
    }
    Serial.println();
  }
}


bool begin(int8_t pinNSS)
{
  pinMode(pinNSS, OUTPUT);
  digitalWrite(pinNSS, HIGH);

  if (checkDevice())
  {
    return true;
  }

  return false;
}


bool checkDevice()
{
  //check there is a device out there, writes a register and reads back

  uint8_t Regdata1, Regdata2;
  Regdata1 = readRegister(REG_FRMID);               //low byte of frequency setting
  writeRegister(REG_FRMID, (Regdata1 + 1));
  Regdata2 = readRegister(REG_FRMID);               //read changed value back
  writeRegister(REG_FRMID, Regdata1);               //restore register to original value

  if (Regdata2 == (Regdata1 + 1))
  {
    return true;
  }
  else
  {
    return false;
  }
}

displays

2_Register_Test Starting
LoRa Device found
Device version 0x12
Frequency at Start 434000000
Registers at Start 
Reg    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0x00  00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A 
0x10  FF 70 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40 
0x20  00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55 
0x30  90 40 40 00 00 0F 00 00 00 F5 20 82 F7 02 80 40 
0x40  00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B 
0x50  14 00 00 11 00 00 00 0F E0 00 0C F7 07 00 5C 78 
0x60  00 19 0C 4B CC 0E 7F 20 04 47 AF 3F 5C 3F D6 0B 
0x70  D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 

That looks correct.

There is a longer version that changes the frequency registers as a check to be sure the device can be written to, but the begin() function does as an initial check write then read back a change to REG_FRMID (0x07) as a check to see if there is a read\write device there.

I tried this and it works, thank you very much.

Final code for the SPI test is:

#include <SPI.h>

#define NSS 7

void setup() 
{
  pinMode(NSS, OUTPUT); // set the SS pin as an output
  SPI.begin();          // initialize the SPI library
  Serial.begin(115200);
}

void loop() 
{
  uint8_t regdata;
  
 for(byte reg = 0; reg <= 6; reg++) {
    Serial.print(reg);
    Serial.print("\t");
    regdata = readRegister(reg);
    Serial.println(regdata,HEX);
    delay(100); 
  }

  Serial.println("--------------------");
  delay(1000); 
}

uint8_t readRegister(uint8_t address)
{
  uint8_t regdata;
  digitalWrite(7, LOW);                    //set NSS low
  SPI.transfer(address & 0x7F);             //mask address for read
  regdata = SPI.transfer(0);                //read the byte
  digitalWrite(7, HIGH);                   //set NSS high
  return regdata;
}

And in the Feather9x_TX example I was using I set the pins to:
#define RFM95_CS 7
#define RFM95_INT 3
#define RFM95_RST 4

So although you can now read the LoRa device over SPI, the library you are using does not work ?

although the pin settings of post 5 worked with the lmic library to communicate with LoRaWAN they did not work with the Arduino LoRa library using callbacks or the Radiohead RH_RF95 library
I switched to using the same pins as the Adafruit Feather 32u4 LoRa (which uses same processor as the Pro micro) for SS, reset and DIO0, e.g.

// Pro Micro with RPi HAT RFM95W
// Pro Micro pin 8 to RFM95 SS    // same pins as Feather 32u4 LoRa
// Pro Micro pin 4 to RFM95 Reset
// Pro Micro pin 7 to RFM95 DIO0
// Pro Micro pin 6 to RFM95 DIO1

both LoRa.h and Radiohead examples then worked OK, e.g. radiohead settings for RH_RF95

// for feather32u4 and Pro Micro 
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.