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.
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
That’s very odd since it has not been a problem before. AGC improves the signal reception.
However, it’s easy enough to fix by replacing line 122 in dragino.py with:-
self.set_agc_auto_on(1)
Could you try that please.
I hasten to add that I’ve never had your problems when using the code with my project.
Note, I will be adding these changes to my dragino repo - when the dust has settled with your device since you appear to be the only one experiencing issues.
You might also be interested in my new repo GitHub - BNNorman/CircuitPython-LoRaWAN: CircuitPython LoRaWAN code to work with the HopeRF RFM95 which uses an RPi Pico with an SX127x hat or the iLabs Challenger RP2040 Lora (£24).
That repo will be updated in the future because I’m also developing a driver for the SX126x (Waveshare Pico-Lora-SX126x). The cost of those components is considerably less than a Pi+Dragino if you don’t need GPS.
Regards
Brian
Hi Brian
change made and no longer see an error…but I dont see any lora frames being sent. It waits at Jon Accept but I see no lora frames being received.
pi@unit002B:~/water-quality-lorawan-dragino-pi/dragino $ python3 test.py
Mode <- SLEEP
Mode <- FSK_STDBY
Mode <- FSK_SLEEP
Mode <- FSK_STDBY
Mode <- SLEEP
Mode <- RXCONT
Mode <- STDBY
Mode <- TX
Waiting for JOIN ACCEPT
Thanks Maurice
Hi Brian
I am seeing this ‘OverflowError: int too big to convert’ error that I havent seen before.
The log below shows the connection attempt and the error. The sensor on the rpi has been working correctly for the last 2 months and just started to report this error message yesterday.
My workaround was to delete the cache.json file and the sensor joined and started sending packets again.
Any ideas as to the problem?
2023-12-05 09:46:22,263 - registered - 550 - INFO - checking if already registered.
2023-12-05 09:46:22,264 - registered - 556 - INFO - devaddr [0, 3, 63, 145] len 4.
2023-12-05 09:46:22,264 - registered - 572 - INFO - Already registered
2023-12-05 09:46:22,264 - getSendSettings - 259 - DEBUG - using send settings: freq 868.7 sf 9 bw 7
2023-12-05 09:46:22,264 - configureRadio - 173 - INFO - freq=868.7 sf=9 bw=7
2023-12-05 09:46:22,267 - getFOpts - 560 - INFO - check for FOpts to attach to uplink len=0 FOpts=bytearray(b'')
2023-12-05 09:46:22,267 - getFOpts - 565 - INFO - no FOpts
2023-12-05 09:46:22,268 - _sendPacket - 664 - ERROR - int too big to convert
Traceback (most recent call last):
File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/dragino.py", line 635, in _sendPacket
{'devaddr': devaddr, 'fcnt': FCntUp, 'data': message, 'fport': port, 'fctrl': FCtrl})
File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/LoRaWAN/PhyPayload.py", line 32, in create
self.mac_payload.create(self.get_mhdr().get_mtype(), self.appkey, args)
File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/LoRaWAN/MacPayload.py", line 42, in create
self.fhdr.create(mtype, args)
File "/home/pi/water-quality-lorawan-dragino-pi/dragino/dragino/LoRaWAN/FHDR.py", line 31, in create
self.fcnt = args['fcnt'].to_bytes(2, byteorder='little')
OverflowError: int too big to convert
This code is preparing the Fcnt for the packet to be sent. Fcnt should only be a 16bit int at max. How many packets has your device sent?
Fcnt is used by TTN to migitage against replay attacks. It can be reset to zero by forcing the code to rejoin TTN ,which resets TTN’s expected Fcnt to zero. Forcing a rejoin can be done by deleting cache,json and calling join()
It would be interesting to see what its value is before doing that. The current value should be in the cache.json file.
Are you obeying the TTN fair use policy (30s per day) and legal duty cycle limit (1%)? Do you know the airtime of your tansmissions? If so you can calculate the length of time your device can be running before the Fcnt overflows (>65535) and a re-join is required.
Look at test.py - the final loop shows how to obey the dutycycle but you need to accumulate the airtime to be able to limit to the TTN 30s.You could also count your transmissions and re-join if it gets to 65535.
The max number of possible transmissions per day is 30/airtime. Assuming airtime is 1s that means your device can send 30 transmissions per day and it would take 65535/30 =2184 days, or 5 years, for the counter to overflow. This implies, to me, you are exceeding the Fair Use Policy and legal limits.
It should actually be a 32 bit integer of which only the lower 16 bit are included in the packet.