adafruit / Adafruit_CircuitPython_RFM9x

CircuitPython module for the RFM95/6/7/8 LoRa wireless 433/915mhz packet radios.
MIT License
67 stars 44 forks source link

Non-default Spreading Factor not working #70

Open psycik opened 2 years ago

psycik commented 2 years ago

I have two other devices in the same room that are able to communicate while my LoRa Radio Bonnet on my Pi Zero cannot. The other devices can receive (FFFF0000345733E11203B22B47187E) what is sent but my Pi doesn't get anything that is sent. One device is a Wio Terminal using the LoRa-E5 with these setting:

AT+TEST=RFCFG,915,SF12,125,12,15,14,ON,OFF,OFF
//AT+TEST=RFCFG,[F],[SF],[BW],[TXPR],[RXPR],[POW],[CRC],[IQ],[NET]

The other is a Feather nRF52840 with the FeatherWing RFM95W, which I assumed would be the easiest to communicate with being the same LoRa module. I am using this library https://github.com/sandeepmistry/arduino-LoRa since the RadioHead lib doesn't compile for the nRF52. It's settings:

  long loraFreq=915E6;
  if (!LoRa.begin( loraFreq)) {             // initialize ratio at 915 MHz
    while (true);                       // if failed, do nothing
  }
  LoRa.setTxPower(12);
  LoRa.setSpreadingFactor(12);
  LoRa.enableCrc();

And finally the settings from the Pi:

rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, 915.0)
rfm9x.signal_bandwidth = 125000
rfm9x.coding_rate = 6
rfm9x.tx_power = 12
rfm9x.spreading_factor = 12
rfm9x.enable_crc = False
#True didn't work either

Any help would be appreciated.

jerryneedell commented 2 years ago

The CircuitPython RFM9X library will only work with RadioHead compliant packet headers. I don't know offhand if the Arduino-LoRa packets comply.

I may be misunderstanding this and will look at it in more detail tomorrow. Can you post your full code, or enough to provide an sample of the issue so I can try to reproduce this.

jerryneedell commented 2 years ago

Looking at your example, FFFF0000345733E11203B22B47187E, I would have expected the Pi to be able to receive this using the FFFF0000 as the header. I'm trying to set this up on my system to test.

jerryneedell commented 2 years ago

As a quick test, I am running the Arduino-LoRa LoRaSender example on a feather M0 Rfm9x -- it's packets are ceded OK by my RaspberryPi 400 with an RFM9x Bonnet. I was incorrect about the header. The pi does receive the packets ok. It just treats the first 4 bytes as the packet header but that is a different issue.

Note, In this case, I am not setting anything other than the pins.

jerryneedell commented 2 years ago

However, If I set use your configuration

 LoRa.setTxPower(12);
  LoRa.setSpreadingFactor(12);
  LoRa.enableCrc();

and

rfm9x.signal_bandwidth = 125000
rfm9x.coding_rate = 6
rfm9x.tx_power = 12
rfm9x.spreading_factor = 12
rfm9x.enable_crc = True

The Pi stops receiving the packets.

So, the default configuration on both sides works, but the specific configuration you are creating does not.

jerryneedell commented 2 years ago

This is the Adruino-Lora Code I am usiong

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

const int csPin = 8;          // LoRa radio chip select
const int resetPin = 4;       // LoRa radio reset
const int irqPin = 3;         // change for your board; must be a hardware interrupt pin

int counter = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Sender");

  // override the default CS, reset, and IRQ pins (optional)
  LoRa.setPins(csPin, resetPin, irqPin); // set CS, reset, IRQ pin

  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }

  //LoRa.setTxPower(12);
  //LoRa.setSpreadingFactor(12);
  //LoRa.enableCrc();
}

void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);

  // send packet
  LoRa.beginPacket();
  LoRa.print("hello ");
  LoRa.print(counter);
  LoRa.endPacket();

  counter++;

  delay(5000);
}

and the Pi code


#Example to display raw packets including header
# Author: Jerry Needell
#
import board
import busio
import digitalio
import adafruit_rfm9x

# Define radio parameters.
RADIO_FREQ_MHZ = 915.0  # Frequency of the radio in Mhz. Must match your
# module! Can be a value like 915.0, 433.0, etc.

# Define pins connected to the chip.
CS = digitalio.DigitalInOut(board.CE1)
RESET = digitalio.DigitalInOut(board.D25)

# Initialize SPI bus.
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

# Initialze RFM radio
rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)

# Wait to receive packets.
print("Waiting for packets...")
# initialize flag and timer
while True:
    # Look for a new packet: only accept if addresses to my_node
    packet = rfm9x.receive(with_header=True)
    # If no packet was received during the timeout then None is returned.
    if packet is not None:
        # Received a packet!
        # Print out the raw bytes of the packet:
        print("Received (raw header):", [hex(x) for x in packet[0:4]])
        print("Received (raw payload): {0}".format(packet[4:]))
        print("RSSI: {0}".format(rfm9x.last_rssi))
        # send reading after any packet received

and here is the received data on the PI

$ python3 rfm9x_header.py 
Waiting for packets...
Received (raw header): ['0x68', '0x65', '0x6c', '0x6c']
Received (raw payload): bytearray(b'o 100')
RSSI: -60
Received (raw header): ['0x68', '0x65', '0x6c', '0x6c']
Received (raw payload): bytearray(b'o 101')
RSSI: -60
Received (raw header): ['0x68', '0x65', '0x6c', '0x6c']
Received (raw payload): bytearray(b'o 102')
RSSI: -60

As you see, the first 4 bytes are interpreted a header (0x68 0x65 0x6c 0x6c) = "hell" then the final "o" and the counter are reported as the payload

jerryneedell commented 2 years ago

It appears that it is the setting of the Spreading Factor that is causing the problem. I tried just setting the Coding rate to 6 as in your example and with that , by Pi still receives the packets, It also receives OK ifs I set the Spreading Factor to 7 -- setting it to 12 does not work.

I have not experimented with the spreading factors so this may well be a bug. I'l try some more tests.

I tried some other spreading factors: 8 and 10 work, but 11 and 12 do not...

jerryneedell commented 2 years ago

I "think" the issue has something to do with the setting of the "low data rate optimize flag" which if I am understanding correctly would only occur for SF 11 and 12 at the 125000 bandwidth. It is set automatically by Arduin-LoRa https://github.com/sandeepmistry/arduino-LoRa/blob/master/src/LoRa.cpp#L545 but it does not appear to be getting set by the CircuitPython code. However, setting it manually also does not work....

@psycik Can you try using a Spreading Factor 7 just to see if it works for you?

jerryneedell commented 2 years ago

The more I look at how the CircuitPython code handles the setting of the Spreading Factor, the more confused I get. SF = 6 does not appear to be working properly either.
Most applications are using SF=7 and it seems to be OK For SF 8 to 10 I am able to send and receive packets, but at SF=10 I am missing a lot of packets. SF 11 and 12 doe not work at all. According to the Data sheet, SF=6 should only be used in "implicit Header" mode and this is not being set by the CircuitPython Code. For SF 11 and 12 at Bandwidth 125000 - it appears that the low_datarate_optimize should be enabled, but I have not been able to make it work so far.

This is going to take some time to investigate and sort out. @psycik Thank you for creating the issue.

At this point, all I can suggest is try setting the SF to 7 if you want to be able to communicate with the Raspberry Pi using the CircuitPython Library.

psycik commented 2 years ago

@jerryneedell Thank you so much for looking into this. You are indeed correct, I set the SF to 7 on all devices and communication is working great now. I was aiming for longest distance with the high SF and low bandwidth, I'll have to run some tests at range. Thanks again.

jerryneedell commented 2 years ago

@jerryneedell Thank you so much for looking into this. You are indeed correct, I set the SF to 7 on all devices and communication is working great now. I was aiming for longest distance with the high SF and low bandwidth, I'll have to run some tests at range. Thanks again.

That is good news! Glad you have something that works. I plan to keep looking into this, but I have no idea how long it may take to make any progress with the other Settings for SF.

logic-switch commented 2 years ago

I was able to get SF 12 to work with the following code. The timeout is necessary or it doesn't receive any packets. Without the low_datarate_optimize there are data errors.

if __name__ == '__main__':
    # Configure LoRa Radio
    CS = DigitalInOut(board.D25)  # Pin 22
    RESET = DigitalInOut(board.D17)  # Pin 11
    spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

    rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, 915.0,
                                 preamble_length=16, baudrate=1000000, crc=False)
    rfm9x.spreading_factor = 12

    # Section 4.1.1.6 - Set low datarate automatically based on BW and SF
    symbolDuration = 1000 / ( rfm9x.signal_bandwidth / (1 << rfm9x.spreading_factor) )
    if symbolDuration > 16:
        rfm9x.low_datarate_optimize = 1
        print("low datarate on")
    else:
        rfm9x.low_datarate_optimize = 0
        print("low datarate off")

    print('- Waiting for PKT -')

    while True:
        packet = rfm9x.receive(timeout=10, with_header=True)
jerryneedell commented 2 years ago

@logic-switch Thank you for this example. It saves a lot of head-scratching!

jerryneedell commented 2 years ago

I am curious why you set the preamble length to 16?

jerryneedell commented 2 years ago

FYI, using the above, I can receive fine with SF12, but I am still having problems transmitting...

logic-switch commented 2 years ago

I was testing various settings. I thought that a longer preamble may allow it to lock on to the signal with a higher spreading factor. I don't think the preamble length matters in this case, but I haven't tested that.

ImTheBadWolf commented 1 year ago

Any update on this ? I was testing on two rpi pico devices, and spreading factor of 11 or 12 wont work. The module that Im using is rfm96.

ImTheBadWolf commented 1 year ago

I did some investigation and found hopefully useful information regarding this. When using bigger spreading factors and lower bandwidth, the time it takes for the packet to be transmitted can easily take 10-15 seconds. There is timeout xmit_timeout for sending packets, which by default is set to 2 seconds. So trying to transmit longer packet will result in timeout. @jerryneedell

After changing the xmit_timeout to 15 seconds and using the code above from @logic-switch , i was able to transmit and receive packet from one device to another (BW125, SF12, CR4/8). But only once. All other attempts failed so there is another problem somewhere else probably.

m00dawg commented 8 months ago

I don't have too much to add here other than I've run into the same issue. I also had trouble lowering the signal_bandwidth. Only 62500 and 125000 seem to work. Fortunately the coding_rate does work and using a signal_bandwidth of 62500 and coding_rate of 8 seems to be working so far though it's too soon to tell if that combination is reliable enough. I'm pulling telemetry from my solar monitoring box which is in a marginal location and am hoping LORA can have a better time compared to Wifi.

This is using 2 of the RFM9x Pi Bonnets though I plan on modifying my AirGradients to also use LORA instead of WIFI.

jerryneedell commented 3 months ago

@ImTheBadWolf Sorry for the much delayed response. Thank you for that suggestion and it makes sense. I will be looking into this issue as part of my work on #92.