How to add Dragino Lora/gps HAT to V3

Is anybody using a decent replacement for the Dragino lora/gps hat for the pi? It is no longer available to buy so looking for something new.

I made one with just an RFM95 on a breadboard HAT - no GPS - it works. Check board_config.py for CS & DIOx pins. The DTOverlay determines the SPI pins IIRC

The wiring is simple, it’s just SPI but they chose BCOM pin 2 for the CS.

I made a KiCAD pcb design (not actual PCB) for a dragino with GPS. This will give you the pins.

Without GPS you only need RST,MOSI,MISO,SCK,DIO0,DIO1,DIO2,NSS

1 Like

Not in Aus but Raspberry Pi LoRa/GPS HAT - RobotShop is expecting 868 versions in on 12th Sept. So ought to be available. They are being made by seedstudio.

I thought the sx127x would run at any frequency 100-1000mhz so I don’t know why they are sold as 868 maybe its just marketting.

1 Like

RF components on the output side usually - 868 & 915 are generally close enough for a non-optimal board.

Uputronics have a board for both full size & zero formats:

Totally recommended.

1 Like

I might buy one…next month…to investigate it.

I am seeing a reoccurrence of this issue again. Last time I changed the dragino board and the problem resolved itself. I have now changed out two dragino boards and the problem still occurs running the ./test.py command. Of course it could be two faulty boards but these were both new and working ok before suddenly stopped with this error.

any ideas much appreciated!!

pi@unit003:~/water-quality-lorawan-dragino-pi/dragino $ ./test.py
Mode <- SLEEP
Mode <- FSK_STDBY
Traceback (most recent call last):
  File "./test.py", line 20, in <module>
    D = Dragino("dragino.toml", logging_level=logLevel)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/dragino.py", line 85, in __init__
    super(Dragino, self).__init__() # LoRa init
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 100, in __init__
    self.rx_chain_calibration(calibration_freq)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 854, in rx_chain_calibration
    self.set_mode(op_mode_bkup)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 221, in set_mode
    sys.stderr.write("Mode <- %s\n" % MODE.lookup[mode])
KeyError: 0

I replied to this at least two weeks ago on a PM reply to your PM but I have not heard back. Have you fixed it.

For the benefit of other readers:-

Somewhere in your version of the code you are trying to put the RFM9x to sleep using mode 0 (Key Error: 0), which isn’t a LoRa sleep mode listed in Constants.py. It should be 0x81 (i.e. MODE.SLEEP is defined in Constants.py as 0x81 not 0x00).

MODE.lookup[mode])

Would then return a string and not fall over.

sorry I never saw your dm reply.

The workaround I used was to swap out the dragino board and this worked for a couple of days before the problem reappeared. I then swapped out the board for the orginal one and this worked again (and is still working).

I looked at the code in LoRa.py and see this section with MODE.lookup[mode]) but I dont see this defined as 0x00.

In Constant.py the MODE.SLEEP is defined as 0X80

So I suppose I cannot find what you are saying needs to be changed, what am I doing wrong?

    def set_mode(self, mode):
        """ Set the mode
        :param mode: Set the mode. Use constants.MODE class
        :return:    New mode
        """
        # the mode is backed up in self.mode
        if mode == self.mode:
            return mode
        if self.verbose:
            sys.stderr.write("Mode <- %s\n" % MODE.lookup[mode])
        self.mode = mode
        return self.spi.xfer([REG.LORA.OP_MODE | 0x80, mode])[1]

When writing to the SX127x mode register (0x01)

0x80 = Sleep
0x81 = STDBY (Idle)

This should mask the problem but it would be better to know where the code is getting a mode value of 0 from when it should be 0x80

sys.stderr.write("Mode <- %s\n" % MODE.lookup[mode | 0x80])

or we could try raising an exception which should give a traceback showing where the value of mode was set to zero.

 def set_mode(self, mode):
        """ Set the mode
        :param mode: Set the mode. Use constants.MODE class
        :return:    New mode
        """
        # the mode is backed up in self.mode
        if mode == self.mode:
            return mode

      if mode==0:
            raise Exception("Invalid mode value")

        if self.verbose:
            sys.stderr.write("Mode <- %s\n" % MODE.lookup[mode])
        self.mode = mode
        return self.spi.xfer([REG.LORA.OP_MODE | 0x80, mode])[1]

I find it hard to believe the Dragino RFM95’s are developing faults.

I will add raising an exception and let you know what happens. I have three units now and all have behaved themselves since the last board swap. Thanks very much for your help here.

Yes do let me know. I’m wondering if its an uninitialised value.

I’m working on conversion to CircuitPython and have LoRaWAN running on Pico+rfm95 talking to TTN. I’m doing testing and documenting it. If the problem is buried in the code it would affect the new setup too.

A dumb question but is it possible to send a remote boot command over lorawan to the raspberry pi end device which has the dragino board installed?

Not dumb. One of my projects was configured to reboot if a certain downlink message was received.
You could use port numbers.
There are a number of ways to do it. If you use systemd you can configure your task to auto start if it stops. Then send a downlink which tells your task to exit.

1 Like

hi
The KeyError: 0 problem returned and I have implemented the change in LoRa.py to raise the ecception. I am not sure if the output sheds any light on the issue

The code you provided I had to modify as it raised an indent issue(which I thought was strange ) when run. My LoRa.py is below.

Below is the output after running the test.py.

pi@unit002B:~/water-quality-lorawan-dragino-pi/dragino $ python3 test.py
Mode <- SLEEP
Mode <- FSK_STDBY
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    D = Dragino("dragino.toml", logging_level=logLevel)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/dragino.py", line 85, in __init__
    super(Dragino, self).__init__() # LoRa init
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 100, in __init__
    self.rx_chain_calibration(calibration_freq)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 860, in rx_chain_calibration
    self.set_mode(op_mode_bkup)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 223, in set_mode
    raise Exception("Invalid mode value")
Exception: Invalid mode value
pi@unit002B:~/water-quality-lorawan-dragino-pi/dragino $

LoRa.py

    def set_mode(self, mode):
        """ Set the mode
        :param mode: Set the mode. Use constants.MODE class
        :return:    New mode
        """
        # the mode is backed up in self.mode
        if mode == self.mode:
            return mode

        if mode==0:
            raise Exception("Invalid mode value")

        if self.verbose:
            sys.stderr.write("Mode <- %s\n" % MODE.lookup[mode])
        self.mode = mode
        return self.spi.xfer([REG.LORA.OP_MODE | 0x80, mode])[1]

I’m wondering if it is a race condition in rx_chain_calibration() which stores the current mode then attempts to restore it with

self.set_mode(op_mode_bkup)

Mode 0x00 is FSK_SLEEP which is used by rx_chain_calibration().

Your code, below, will always raise an exception when FSK_SLEEP is attempted so remove both lines.

       if mode==0:
            raise Exception("Invalid mode value")

instead, lets put a valid entry in constants.py

@add_lookup
class MODE:
    SLEEP    = 0x80
    STDBY    = 0x81
    FSTX     = 0x82
    TX       = 0x83
    FSRX     = 0x84
    RXCONT   = 0x85
    RXSINGLE = 0x86
    CAD      = 0x87
    FSK_STDBY= 0x01     # needed for calibration

at the end add FSK_SLEEP=0x00

Now the code will print <–FSK_SLEEP instead of crashing.

Could you try that please.

Brian

Hi Brian
this is the error message I now receive after making the changes.

pi@unit002B:~/water-quality-lorawan-dragino-pi/dragino $ python3 test.py
Mode <- SLEEP
Mode <- FSK_STDBY
Mode <- FSK_SLEEP
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    D = Dragino("dragino.toml", logging_level=logLevel)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/dragino.py", line 85, in __init__
    super(Dragino, self).__init__() # LoRa init
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 100, in __init__
    self.rx_chain_calibration(calibration_freq)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 856, in rx_chain_calibration
    self.set_freq(freq_bkup)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/SX127x/LoRa.py", line 282, in set_freq
    assert self.mode == MODE.SLEEP or self.mode == MODE.STDBY or self.mode == MODE.FSK_STDBY
AssertionError

change the assert to

 assert self.mode == MODE.SLEEP or self.mode == MODE.STDBY or self.mode == MODE.FSK_STDBY or self.mode==MODE.FSK_SLEEP

It’s been a long while since I developed that code.

Brian

Hi Brian
change made and this is now the output.

pi@unit002B:~/water-quality-lorawan-dragino-pi/dragino $ python3 test.py
Mode <- SLEEP
Mode <- FSK_STDBY
Mode <- FSK_SLEEP
Mode <- FSK_STDBY
Mode <- SLEEP
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    D = Dragino("dragino.toml", logging_level=logLevel)
  File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/dragino.py", line 122, in __init__
    assert self.get_agc_auto_on() == 1
AssertionError