mayeranalytics / pySX127x

This is a python interface to the Semtech SX127x, HopeRF RFM9x, Microchip RN2483 long range, low power transceiver families.
GNU Affero General Public License v3.0
170 stars 116 forks source link

Use with Dragino Lora GPS Hat #21

Open phraktle opened 6 years ago

phraktle commented 6 years ago

Hi,

I'm trying to use the library with a Dragino Lora GPS Hat v1.4 board on a RPi3, with no luck so far (assertion error in set_freq during calibration). Has anyone successfully used this board? With what settings?

Thanks, Viktor

pointhi commented 6 years ago

You need to do some little changes to the board configuration and on the board itself:

acceleratiom commented 6 years ago

Hi, I did two changes: DIO0 =4 and the pins 22 to 24 jumper. But I still have issues when running test_lorapy or (lora_util.py) on the RPI3. I put some print in the code to get it, but I do not understand why I get an "unknown dio3 mapping!" Do you any hint ?

Thanks, Ludovic

pi@raspberrypi:~/pysx/pySX127x $ python lora_util.py
/home/pi/pysx/pySX127x/SX127x/board_config.py:51: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(BOARD.LED, GPIO.OUT)
((' self.dio_mapping[3]: ', None)'selfmode',
1Traceback (most recent call last):
  File "/home/pi/pysx/pySX127x/SX127x/LoRa.py", line 196, in _dio3
)
    raise RuntimeError("unknown dio3 mapping!")
('selfmode', 3)
RuntimeError: Traceback (most recent call last):
unknown dio3 mapping!
  File "lora_util.py", line 35, in <module>
    lora = LoRa(verbose=False)
  File "/home/pi/pysx/pySX127x/SX127x/LoRa.py", line 100, in __init__
    self.rx_chain_calibration(calibration_freq)
  File "/home/pi/pysx/pySX127x/SX127x/LoRa.py", line 858, in rx_chain_calibration
    self.set_freq(freq_bkup)
  File "/home/pi/pysx/pySX127x/SX127x/LoRa.py", line 284, in set_freq
    assert self.mode == MODE.SLEEP or self.mode == MODE.STDBY or self.mode == MODE.FSK_STDBY
(' self.dio_mapping[3]: ', None)
AssertionError
mayeranalytics commented 6 years ago

I suspect you changed the dio_mapping and entered the Raspberry pin number. (I’m not quite sure what “and the pins 22 to 24 jumper” means – I take it that you use different pins on the Raspberry.)

Background: The SX127x have 6 DIOs that you can assign a function to. DIO0, for example, can output RxDone (0), TxDone (1) or CadDone (2). These 0,1,2 values have nothing to do with Raspberry pin numbers, they just identify SX127x functionality. A value of 4 would be illegal (and actually impossible to set). If you want to know more, look at the datasheet, starting with table 18. on p.46.

Instead, change the pin numbers in board_config.py.

artificialsheep commented 6 years ago

Hi, I had the same issue, indeed you need to set DIO0 = 4 but make sure you change SWITCH to something else (I used 21) and change DIO3 (which is NC on the Dragino shield) to something toher than 25 or you will conflict with the SPI CS pin (since you have now soldered board-pins 22 & 24 together (which are BCM pins 25 & 8). Make sure to reboot as well as your GPIO setup will be all weird, but now I have it working. @mayeranalytics what are your thought on making a Dragino subclass with the correct pins that would allow this to work out of the box? If someone also knows to to software re-map GPIO to avoid the soldering step this could also be nice.

mayeranalytics commented 6 years ago

@artificialsheep Thanks for the input. I don't have a Dragino shield, so I can't test anything. But if you have figured it out, and if you have the time, why don't you just make a pull request?

mkshrps commented 6 years ago

Raspberry Pi stretch has an overlay for this included. To remap the SPI CE0 pin to work with the Dragino add the following to the /boot/config.txt file dtoverlay=spi0-cs,cs0_pin=25 where 25 is the BCM designation for the GPIO (physical) pin 22. you can also remap the SPI CE1 pin if you ever need to e.g. dtoverlay=spi0-cs,s0_pin=25, cs1_pin=xx The pin definitions for GPIO, BCM and wiring PI definitions can be found at https://pinout.xyz/ A couple of extra points to watch out for. Firstly if you remap the CS then you don't need to solder pin 22 to 24 and also make sure the RESET pin is asserted (high) specifically by setting the BCM pin 17 (physical pin 11).

Bakhoj commented 6 years ago

Hi,

I'm also trying to use this library with a Dragino Lora GPS Hat v1.4 board on a RPi3, which has to retrieve some data from a RN2483 on a Waspmote Pro v1.5 and is giving me some problems aswell.

I've also soldered the BCM 25 & 8 together and connected the DIO3 to BCM1 since it isn't connected on the board as seen here: PDF

At the moment I can recieve data, but only something like once a few minutes if it's sending every 2 second. Only the first 3 bytes have the correct values most of the time while the rest is partly correct, and sometimes it just gets a dump of data.

The code I'm using is a remake of the rx_cont.py:

main.py ```Python import time import sys from SX127x.LoRa import * from SX127x.board_config import BOARD print("Start Master Module") BOARD.DIO0 = 4 BOARD.DIO3 = 1 BOARD.SWITCH = 21 BOARD.setup() class LoRaMaster(LoRa): def __init(self): super(LoRaRcvCont, self).__init__(verbose) self.set_mode(MODE.STDBY) #self.set_dio_mapping([0] * 6) def on_rx_done(self): BOARD.led_on() print("\nRxDone") self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) print(bytes(payload).hex()) self.set_mode(MODE.SLEEP) self.reset_ptr_rx() BOARD.led_off() self.set_mode(MODE.RXCONT) def on_txdone(self): print("\nTxDone") print(self.get_irq_flags()) def on_cad_done(self): print("\non_CadDone") print(self.get_irq_flags()) def on_rx_timeout(self): print("\non_RxTimeout") print(self.get_irq_flags()) time.sleep(.5) self.set_mode(MODE.SLEEP) self.reset_ptr_rx() self.set_mode(MODE.RXCONT) def on_valid_header(self): print("\non_ValidHeader") print(self.get_irq_flags()) def on_payload_crc_error(self): print("\non_PayloadCrcError") print(self.get_irq_flags()) def on_fhss_change_channel(self): print("\non_Fhss_changeChannel") print(self.get_irq_flags()) def start(self): self.reset_ptr_rx() self.set_mode(MODE.RXCONT) while True: time.sleep(.5) rssi_value = self.get_rssi_value() snr_value = self.get_pkt_snr_value() status = self.get_modem_status() sys.stdout.flush() sys.stdout.write("\r%d %d %d %d" % (rssi_value, snr_value, status['rx_ongoing'], status['modem_clear'])) lora = LoRaMaster() try: lora.set_mode(MODE.STDBY) lora.set_freq(868.1) lora.set_coding_rate(CODING_RATE.CR4_5) lora.set_bw(BW.BW125) lora.set_spreading_factor(12) lora.set_pa_config(output_power=5) lora.set_preamble(12) lora.set_rx_crc(0) lora.set_implicit_header_mode(0) time.sleep(2) except: print("Error in setup") print("Closing") BOARD.teardown() print("END") print("Version: \t{}".format(lora.get_version())) print("Frequency: \t{}MHz".format(lora.get_freq())) print("Modem Config 1: {}".format(lora.get_modem_config_1())) print("Modem Config 2: {}".format(lora.get_modem_config_2())) print("PA Config: \t{}".format(lora.get_pa_config())) print(lora) assert(lora.get_agc_auto_on() == 1) # Start Listening try: lora.start() except KeyboardInterrupt: sys.stdout.flush() print("") sys.stderr.write("KeyboardInterrupt\n") finally: sys.stdout.flush() print("") lora.set_mode(MODE.SLEEP) print(lora) BOARD.teardown() ```

And when I run the code for some time:

main.py - Console ``` pi@raspberrypi:/project/python/lora_master $ python3 main.py Start Master Module Mode <- SLEEP Mode <- FSK_STDBY Mode <- SLEEP Mode <- FSK_STDBY Mode <- SLEEP Mode <- STDBY Version: 18 Frequency: 868.0999755859375MHz Modem Config 1: {'coding_rate': 1, 'bw': 7, 'implicit_header_mode': 0} Modem Config 2: {'rx_crc': 0, 'tx_cont_mode': 0, 'spreading_factor': 12} PA Config: {'max_power': 4, 'pa_select': 0, 'output_power': 5} SX127x LoRa registers: mode STDBY freq 868.099976 MHz coding_rate CR4_5 bw BW125 spreading_factor 4096 chips/symb implicit_hdr_mode OFF rx_payload_crc OFF tx_cont_mode OFF preamble 12 low_data_rate_opti OFF agc_auto_on ON symb_timeout 100 freq_hop_period 0 hop_channel {'fhss_present_channel': 0, 'crc_on_payload': 0, 'pll_timeout': 0} payload_length 1 max_payload_length 255 irq_flags_mask {'rx_done': 0, 'fhss_change_ch': 0, 'crc_error': 0, 'cad_detected': 0, 'rx_timeout': 0, 'tx_done': 0, 'cad_done': 0, 'valid_header': 0} irq_flags {'rx_done': 0, 'fhss_change_ch': 0, 'crc_error': 0, 'cad_detected': 0, 'rx_timeout': 0, 'tx_done': 0, 'cad_done': 0, 'valid_header': 0} rx_nb_byte 0 rx_header_cnt 0 rx_packet_cnt 0 pkt_snr_value 64.000000 pkt_rssi_value -164 rssi_value -164 fei 0 pa_select RFO max_power 13.200000 dBm output_power 3.200000 dBm ocp ON ocp_trim 100.000000 mA lna_gain G1 lna_boost_lf 0b0 lna_boost_hf 0b0 detect_optimize 0x3 detection_thresh 0xa sync_word 0x12 dio_mapping 0..5 [0, 0, 0, 0, 0, 0] tcxo XTAL pa_dac default fifo_addr_ptr 0x0 fifo_tx_base_addr 0x80 fifo_rx_base_addr 0x0 fifo_rx_curr_addr 0x0 fifo_rx_byte_addr 0x0 status {'signal_sync': 0, 'rx_ongoing': 0, 'signal_detected': 0, 'header_info_valid': 0, 'modem_clear': 1, 'rx_coding_rate': 0} version 0x12 Mode <- RXCONT -103 64 1 0 RxDone b8515c69303afdcc2097cb909df163fb139ce3b5f19edb15ae7a566404736325edb01fe156084f5479 Mode <- SLEEP Mode <- STDBY Mode <- RXCONT -105 64 1 0 RxDone b8515c69301afdcc80dfac57cadc2336c684d3b9478683516026a48c4673872dbb88bd82667ba147f5 Mode <- SLEEP Mode <- STDBY Mode <- RXCONT -47 64 1 00 RxDone 120588ccf2 Mode <- SLEEP Mode <- STDBY Mode <- RXCONT -105 64 1 0 RxDone b8515c69301afdcc8099f25cf13af1b2901b2fa02205e4d448490f70131a9c5c46babc650862818a27 Mode <- SLEEP Mode <- STDBY Mode <- RXCONT -107 64 1 0 ```

Notice that the printout is decoded from byte to char, so the 120588ccf2 was the only close result here which should have been 120588FF88 which was send from the waspmote.

I'm suspecting it's something with the settings not being the same on both modules maybe?

If it's any help I do get the following errors when I'm trying to run lora_util.py and test_lora.py, and I have to restart the RPi to get the main.py code to work again after:

lora_util.py - console ``` pi@raspberrypi:/usr/lib/python3.5/pySX127x $ python3 lora_util.py Traceback (most recent call last): File "lora_util.py", line 39, in lora = LoRa(verbose=False) File "/usr/lib/python3.5/pySX127x/SX127x/LoRa.py", line 101, in __init__ self.rx_chain_calibration(calibration_freq) File "/usr/lib/python3.5/pySX127x/SX127x/LoRa.py", line 857, in rx_chain_calibration self.set_freq(freq_bkup) File "/usr/lib/python3.5/pySX127x/SX127x/LoRa.py", line 283, in set_freq assert self.mode == MODE.SLEEP or self.mode == MODE.STDBY or self.mode == MODE.FSK_STDBY AssertionError ```
test_lora.py - console ``` pi@raspberrypi:/usr/lib/python3.5/pySX127x $ python3 test_lora.py F..... ====================================================================== FAIL: test_mode (__main__.TestSX127x) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_lora.py", line 43, in wrapper func(self) File "test_lora.py", line 62, in test_mode self.assertEqual(lora.get_mode(), m) AssertionError: 128 != 129 ---------------------------------------------------------------------- Ran 6 tests in 0.012s FAILED (failures=1) ```

Anyone have an idea what is missing?

Thanks, Bakhoj

EDIT: Had made some changes tolora_util.py which gave another error then the original code, it is changed now to only have the GPIO changed and is showing the correct error now.

Bakhoj commented 6 years ago

I fixed my problem with the partly incorrect data from the RN2483.

The Dragino LoRa GPS hat v.1.4's schematics referes to the LoRa module as "RFM92_93W" and I could not find out if it was using RFM92W or RFM93W. The main difference between the 2 is the spreading factor range, which for 92 is 6-12 and the 93 it is 6-9. After changing the setup to use SF9 instead of 12 it worked. The error with lora_util.py is gone aswell but the same error is still present when running test_lora.py is it something to be worried about? I understand it's something with the module being in the wrong mode?

pyflier commented 5 years ago

Hi Bakhoj I'm facing exactly the same issue. but even more over two dio0 and dio1: File "/home/pi/pySX127x-master/SX127x/LoRa.py", line 164, in _dio0 raise RuntimeError("unknown dio0mapping!") RuntimeError: unknown dio0mapping! Traceback (most recent call last): File "/home/pi/pySX127x-master/SX127x/LoRa.py", line 177, in _dio1 raise RuntimeError("unknown dio1mapping!")

Just wondering if you managed to overcome the issue

MikeRouten commented 5 years ago

I am trying to get the Dragino board running on a Pi 3 but keep getting the following error:

Traceback (most recent call last):
  File "tx_ttn.py", line 40, in <module>
    lora = LoRaWANsend(False)
  File "tx_ttn.py", line 15, in __init__
    super(LoRaWANsend, self).__init__(verbose)
  File "/home/pi/LoRaWAN/SX127x/LoRa.py", line 100, in __init__
    self.rx_chain_calibration(calibration_freq)
  File "/home/pi/LoRaWAN/SX127x/LoRa.py", line 856, in rx_chain_calibration
    self.set_freq(freq_bkup)
  File "/home/pi/LoRaWAN/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

At this point in the code, self.mode = 0

I have applied the CS remap as suggested by mkshrps and I have modified the LoRa.py file DI0=4 value.

Does anyone have any suggestions on how to resolve this issue?

mayeranalytics commented 5 years ago

This type of error usually occurs when SPI communication with the LoRa chip isn't working properly. All the error message is saying is that the LoRa chip isn't in the state it should be in.

In this case the best approach is to go back to basics: Establish reliable communication, for example by reading out the RegOpMode register (0x01) and then toggling Sleep, Standby and Receiver mode and check whether the chip does really is in the appropriate state. You can use LoRa.py in this library as a guide for how to do the communication in python. There's also plenty of info on the interweb. I suggest you install ipython on the Rasp and debug SPI/raspberry/LoRa chip in the REPL. On the Rasp in can be worthwhile trying to change the SPI frequency.

When you get stuck, establish facts by eliminating error sources: E.g. try the Dragino with an Arduino and establish the board is fine. Then work forward. When SPI communication refuses to work then a Logic analyser can be useful.

This whole process can be quite frustrating, but if you proceed logically you can figure it out.

Or maybe someone else has already done that particular dance and can contribute the solution.

artificialsheep commented 5 years ago

I've had issues with a recent upgrade in raspbian where I had to enable only SPI communication in raspi-config (disable one-wire and I2C).  Also make sure you are in the spi and gpio groups.

On 19/11/2018 12:26, Mayer Analytics wrote:

This type of error usually occurs when SPI communication with the LoRa chip isn't working properly. All the error message is saying is that the LoRa chip isn't in the state it should be in.

In this case the best approach is to go back to basics: Establish reliable communication, for example by reading out the RegOpMode register (0x01) and then toggling Sleep, Standby and Receiver mode and check whether the chip does really is in the appropriate state. You can use |LoRa.py| in this library as a guide for how to do the communication in python. There's also plenty of info on the interweb. I suggest you install ipython on the Rasp and debug SPI/raspberry/LoRa chip in the REPL. On the Rasp in can be worthwhile trying to change the SPI frequency.

When you get stuck, establish facts by eliminating error sources: E.g. try the Dragino with an Arduino and establish the board is fine. Then work forward. When SPI communication refuses to work then a Logic analyser can be useful.

This whole process can be quite frustrating, but if you proceed logically you can figure it out.

Or maybe someone else has already done that particular dance and can contribute the solution.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mayeranalytics/pySX127x/issues/21#issuecomment-439861544, or mute the thread https://github.com/notifications/unsubscribe-auth/Ag2pYWR4Fx_Y0OL3jUpLuq4YutggQ70Zks5uwpVlgaJpZM4OWFgU.

-- Gabriel Dulac-Arnold blacksheep.ai

mkshrps commented 5 years ago

Ideally you should use an oscilloscope to check what the pins are actually doing in particular the CS pin. If you can write a loop which reads a register you can then check the cs, Mosi,miso and sclk pins are doing something. This would confirm the remapping dtoverlay=spi0-cs,cs0_pin=25 is working . Also make sure the Reset pin is set high.

MikeRouten commented 5 years ago

For anyone that is interested, I got this working with the following configuration on a fresh install of Raspbian Stretch:

  1. Implement the /boot/config.txt changes that mkshrps suggested by adding "dtoverlay=spi0-cs,cs0_pin=25" to the config.txt record.

  2. Use the following values in board_config DIO0 = 4 DIO1 = 23 DIO2 = 24 DIO3 = 21 LED = 18 SWITCH = 7

  3. ADD THE FOLLOWING LINES TO constants.py @add_lookup class SPI_BAUD_RATE: MAX_SPEED_HZ = 5000 @add_lookup class SPI_MODE: SPI_MODE = 0b01

  4. ADD THE FOLLOWING LINES TO LoRa.py at the top of the class definition right after " spi = BOARD.SpiDev() ": spi.max_speed_hz = SPI_BAUD_RATE.MAX_SPEED_HZ spi.mode = SPI_MODE.SPI_MODE

With these changes / additions I was able to get the Dragino Hats talking to each other over the Pi's without having to do any soldering on the Hat.

xmrhahnx commented 5 years ago

HI there, i'm facing with similar problem. I made the modification as MikeRouten suggested and the test_lora.py works as expected. But when i run the rx_cont.py or any other example i get this:

/home/pi/pySX127x-master/SX127x/board_config.py:58: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(BOARD.LED, GPIO.OUT)
Traceback (most recent call last):
  File "rx_cont.py", line 101, in <module>
    print(lora)
  File "/home/pi/pySX127x-master/SX127x/LoRa.py", line 945, in __str__
    s += " pa_dac             %s\n" % ['default', 'PA_BOOST'][self.get_pa_dac()]
  File "/home/pi/pySX127x-master/SX127x/LoRa.py", line 56, in wrapper
    return func(self, self.spi.xfer([register_address, 0])[1])
  File "/home/pi/pySX127x-master/SX127x/LoRa.py", line 818, in get_pa_dac
    raise RuntimeError("Bad PA_DAC value %s" % hex(pa_dac))
RuntimeError: Bad PA_DAC value 0x3

any suggestion?

amotl commented 4 years ago

Hi there.

Introduction

We spent some time on revamping these libraries to be used within our Terkin Datalogger. While adding some bits from the community and general polishing, the main contribution from our pen was https://github.com/daq-tools/dragino/commit/772f552d, in order to be able to configure the Dragino class at runtime to become independent of the dragino.ini file. We hope this is as useful for the community as it was important to us.

Resources

The trees we have modified:

Usage

The code is driven by terkin.network.lora.LoRaDriverDragino. You might want to use this as an example blueprint.

Installation

This outlines an ad hoc way of getting the bits and pieces installed together in a coherent manner. Tearing the libraries apart and publishing them to PyPI would have been the better option, but we will postpone this into the future for now.

mkdir lib

# Install driver support for Dragino LoRa Hat.
curl --location https://github.com/daq-tools/dragino/archive/terkin.tar.gz | tar -C lib --strip-components=1 -xzvf - dragino-terkin/dragino

# Install updated pySX127x driver.
curl --location https://github.com/daq-tools/pySX127x/archive/dragino.tar.gz | tar -C lib/dragino --strip-components=1 -xzvf - pySX127x-dragino/SX127x

Credits

Thanks a bunch to

Cheers, Jan and Andreas.

chuanisawesome commented 2 years ago

Hi,

I am new to using LoRa and the Dragino Hat for Raspberry pi. I am currently working on a project that I would like to have the Heltec LoRa32 talk to the Dragino Hat locally. Is there any suggestions on how to get started or if this is a possibility? I've ran the lora_test.py and I get this error:

87527FF5-2FA4-4723-87DB-DAD8FEE460CE

Thank you!

mayeranalytics commented 2 years ago

The failed test tells you that the LoRa chip is not in the correct mode, or registers don't have the expected values. This usually means that there are communication problems. When I look at your log, I see that the read commands seem to always return 0, and that is quite suspicious.

chuanisawesome commented 2 years ago

I end up using Heltec LoRa32 as my gateway since I'm having so much trouble with Dragino LoRa Hat for the RPi.

amotl commented 2 years ago

Hi again,

following up on our last post at https://github.com/mayeranalytics/pySX127x/issues/21#issuecomment-620695583, we would like to bring to your attention that @BNNorman picked up the torch and has been working on his fork ^1 continuously since May 2021.

For further information, see also https://github.com/daq-tools/dragino-lorawan/issues/1 where Brian shared an overview about the improvements and features he has been working on, status November 2021.

With kind regards, Andreas.

/cc @tonkenfo

chuanisawesome commented 2 years ago

Thank you so much @amotl ! I will look into it. I really appreciate it

BNNorman commented 2 years ago

I end up using Heltec LoRa32 as my gateway since I'm having so much trouble with Dragino LoRa Hat for the RPi.

Did you really mean Gateway? Gateways are supposed to be able to receive on 8 channels simultaneously. Single channel gateways are not supported by TTN (AFAIK).

Check your Dragino LoRA/GPS HAT version is V1.4 - it has DIO signals wired that previous versions do not. That may be your real issue with RPi.