No callback interrupt from RFM95 LoRa using RadioHead

Hi!

I have a problem transmitting messages with the RFM95 module using a MSP430 MCU and the RadioHead library. Init() works successfully and the device sets OP_MODE into standby (idle 0x81) mode correctly.

However, I get stuck in an infinite while-loop in waitCAD() and isChannelActive(), as I am never receiving an interrupt callback from the DIO0 pin. The interrupt routine works fine itself as it fires when I connect/disconnect the cable. (it is set to RISING).

Please note that I am using the Dragino LoRa Shield without any Arduino, see attachment:

I have connected the ICSP pins for SPI, DIO0 to my interrupt pin and D10 to the slave select pin. I am NOT using any SPI interrupt pin as I don’t think it is necessary for this?

Code:

uint8_t init_RH_RF95()
{
    __disable_interrupt();
    _mode=RHModeInitialising;
    _thisAddress=RH_BROADCAST_ADDRESS;
    _promiscuous=0;
    _txHeaderTo=RH_BROADCAST_ADDRESS;
    _txHeaderFrom=RH_BROADCAST_ADDRESS;
    _txHeaderId=0;
    _txHeaderFlags=0;
    _rxGood=0;
    _txGood=0;
    _cad_timeout=10000;

    // Tell the low level SPI interface we will use SPI within this interrupt
        //spiUsingInterrupt(interruptNumber);

    RFM95W_SPISetup(); // using GPIO 6 as channel select
    _rxBufValid=0;

    // Set sleep mode, so we can also set LORA mode:
    RFM95W_SPIByteWriteReg(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE);
    __delay_cycles(240000); // Wait 10ms for sleep mode to take over from say, CAD

    // Check we are in sleep mode, with LORA set
    if (RFM95W_SPIByteReadReg(RH_RF95_REG_01_OP_MODE) != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE  ))
    {
      __enable_interrupt();
	return 0; // No device present?
    }
    // Set up FIFO
    // We configure so that we can use the entire 256 byte FIFO for either receive
    // or transmit, but not both at the same time
    RFM95W_SPIByteWriteReg(RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0);
    RFM95W_SPIByteWriteReg(RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0);

    // Packet format is preamble + explicit-header + payload + crc
    // Explicit Header Mode
    // payload is TO + FROM + ID + FLAGS + message data
    // RX mode is implmented with RXCONTINUOUS
    // max message data length is 255 - 4 = 251 octets

    setModeIdle();

    // Set up default configuration
    // No Sync Words in LORA mode.
    setModemRegisters(0x78, 0xC4, 0x0C); // slow long range (see header file for more info)
    //setModemRegisters(0x92,   0x74,    0x00); //for fast/short transmission

    setPreambleLength(8); // Default is 8
    setFrequency(868.0);
    setTxPower(13, 0); // Lowish power (PA_boost=1 for higher power)
    __enable_interrupt();

    return 1;
}

void sendToLora(void){

    uint8_t data[] = "Hello World!";

    int status=send(data, sizeof(data)); // <--- STUCK HERE
    
    waitPacketSent();

    sprintf((char *)outString, "SENT! %d \n", status);
    putsUART((unsigned char *)outString,strlen((char *)outString));
    // Now wait for a reply
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    if (waitAvailableTimeout(3000))
    {
    // Should be a reply message for us now
    if (recv(buf, &len))
    {
        sprintf((char *)outString, "RSSI: %d, got reply: ", _lastRssi);
        putsUART((unsigned char *)outString,strlen((char *)outString));
        putsUART((unsigned char *)(char*)buf,strlen((char *)outString));

    }
    else
    {
        sprintf((char *)outString, "recieve failed. ");
        putsUART((unsigned char *)outString,strlen((char *)outString));
    }
    }
    else
    {
        sprintf((char *)outString, "No reply, LoRa server running?");
        putsUART((unsigned char *)outString,strlen((char *)outString));
      }
    sprintf((char *)outString, "\n");
    putsUART((unsigned char *)outString,strlen((char *)outString));
}

Thanks in advance!

I have had the Dragino LoRa Shield working with an Arduino Uno and a Mega using the ibm-lmic-framework
The RAW (peer to peer with Adafruit feather 32u4) and TTN-OTAA (to The Things Network) examples worked OK
have you checked DIO1 is changing state to indicate an interrupt - RFM95W Pin Connections

horace:
I have had the Dragino LoRa Shield working with an Arduino Uno and a Mega using the ibm-lmic-framework
The RAW (peer to peer with Adafruit feather 32u4) and TTN-OTAA (to The Things Network) examples worked OK
have you checked DIO1 is changing state to indicate an interrupt - RFM95W Pin Connections

I was initially not using the DIO1 interrupt, but after trying with it I didn't get any interrupt from DIO1 neither...

can you check DIO1 with an oscilloscope of a multimeter?
are you attempting Lora peer-to-peer communications or LoraWAN - if the latter does the backend show uplink data has been received?

horace:
can you check DIO1 with an oscilloscope of a multimeter?
are you attempting Lora peer-to-peer communications or LoraWAN - if the latter does the backend show uplink data has been received?

I just checked and DIO0 is always high (3.3V) and DIO1 is Low (0V) after initialising. I am just using peer-to-peer communication.

I seem to remember that DIO1 goes high on recipt of OTAA downlink message not sure about peer-to-peer though
does the peer receive the transmission OK?

horace:
I seem to remember that DIO1 goes high on recipt of OTAA downlink message not sure about peer-to-peer though
does the peer receive the transmission OK?

I think that only DIO0 is required for normal LoRa. I haven't tried receiving yet as I first wanted to succeed sending something, But I could try that.

But is it normal that it is always high as it is triggered on RISING? Maybe some pull-up problem?

The functions of the LoRa DIO pins can vary depending on how the device is setup.

See table 18 in the latest SX1278 data sheet.

Okay I got Tx and Rx working now with three different workarounds:

  1. Connecting DIO0 and DIO1 together into one interrupt input on Falling edge.
  2. Connecting DIO0 and DIO1 together into one interrupt input on Rising edge.
  3. Using only DIO0 on Rising edge.

What is the right way to go?

Thanks for your help!

thelle:
Okay I got Tx and Rx working now with three different workarounds:

  1. Connecting DIO0 and DIO1 together into one interrupt input on Falling edge.
  2. Connecting DIO0 and DIO1 together into one interrupt input on Rising edge.
  3. Using only DIO0 on Rising edge.

What is the right way to go?

Rather depends on how you connected them together don't you think ?

srnet:
Rather depends on how you connected them together don't you think ?

They are sharing the same line into one interrupt pin input on my MCU.

thelle:
They are sharing the same line into one interrupt pin input on my MCU.

Not a lot of help.

Do you have DIO0 and DIO1 directly wired to gether ?

DIO0 and DIO1 are outputs and as each of them could be either high or low, connecting them together is a bad idea.

Yes directly together. The interrupt handler reads the RFM95s IFG register through SPI to identify who triggered the interrupt, so it should be fine right? Or do I need to add OR diods and a resistor as described here:?

GPIO25  <---->  DIO0 OR DIO1 OR DIO2 (Hardware OR done with 1N4148 Diode and R3)

thelle:
Or do I need to add OR diods and a resistor as described here:?

Yes, you cannot connect two outputs directly together and expect to be able to detect when one of them goes high, which indicates the condition.

If DIO0 is low and DIO1 goes high, and both are wired together, what is the logic level that the MSP430 sees, is it high or low ?