LoPy communication with RFM95 modules
-
@constantinos It's hard to get the combination of LoRa+RFM95 running. I tried an Adafruit test sketch for the Feather M0 https://learn.adafruit.com/adafruit-feather-m0-radio-with-lora-radio-module/using-the-rfm-9x-radio#transmitter-example-code and a basic LoPy code as gateway. I got sometimes a packages received, perhaps 10% but also only one packages of 100. Do you have a simple example sketch pair that is working on your side?
-
@Clemens It was not easy and there is a drawback when combining two different tranceivers.
To be honest I tried sending messages with values like 1,2,3,4,5,6,7 in the fields of the structure. Then I located them in the byte array the LoPy represented to me.
So let's see what I managed to do:Arduino + RFM95 library from https://learn.adafruit.com/adafruit-rfm69hcw-and-rfm96-rfm95-rfm98-lora-packet-padio-breakouts/rfm9x-test
Arduino Code#include <SPI.h> #include <RH_RF95.h> #define FREQUENCY 868.0 struct tpayload { uint32_t deviceid; //4 byte seq; //1 byte indicator1; //1 byte indicator2; //1 byte stype; //1 long svalue; //4 byte check; //1 }; tpayload payload; RH_RF95 rf95(10,2); // Chip Select=D10, INT Pin = D2 void setup() { Serial.begin(57600); if (!rf95.init()) { Serial.println("init failed"); } else { Serial.print("init OK - "); Serial.print(FREQUENCY); Serial.println("mhz"); } payload.seq = 0; payload.control = 0; payload.deviceid = 8512; payload.indicator1 = 1; payload.indicator1 = 2; payload.stype = 2; payload.svalue = -10; } void loop() { payload.seq++; if (payload.seq == 0) payload.seq++; // to avoid division by zero at the next line payload.check = payload.deviceid % payload.seq; // you need this to discard corrupted messages uint16_t now = micros(); rf95.send( (const void*)&payload, sizeof(payload)); delay(5000); }LoPy Code
import struct import socket from network import LoRa import time import gc LORA_MSG_FORMAT = "LLBBBBlB" class incoming_message: def __init__(self, data): self.control, self.deviceID, self.Seq, self.indicator1, self.indicator2, self.stype, self.svalue, self.check = struct.unpack(LORA_MSG_FORMAT, data) #self.control is something added from RFM95. Just discard it. Your message starts from the 5th byte class server: def __init__(self): cfg_mode = LoRa.LORA cfg_freq = 868000000 cfg_bandwidth=LoRa.BW_125KHZ # LoRa.BW_125KHZ or LoRa.BW_250KHZ cfg_sf = 7 # Accepts values between 6 and 12. # 6 = 64 Chips/Symbol # 7 = 128 Chips/Symbol # 8 = 256 Chips/Symbol # 9 = 512 Chips/Symbol # 10 = 1024 Chips/Symbol # 11 = 2048 Chips/Symbol # 12 = 4096 Chips/Symbol cfg_preamble=8 #configures the number of pre-amble symbols. The default value is 8 cfg_coding_rate=LoRa.CODING_4_5 #LoRa.CODING_4_5, LoRa.CODING_4_6, LoRa.CODING_4_7 or LoRa.CODING_4_8 cfg_power_mode=LoRa.ALWAYS_ON #LoRa.ALWAYS_ON, LoRa.TX_ONLY or LoRa.SLEEP self.lora = LoRa(mode=cfg_mode, frequency=cfg_freq, bandwidth=cfg_bandwidth, sf=cfg_sf, preamble=cfg_preamble, coding_rate=cfg_coding_rate, rx_iq=True, power_mode=cfg_power_mode) self.lora.init(mode=LoRa.LORA, frequency=868000000, tx_power=14, bandwidth=LoRa.BW_125KHZ, sf=7, preamble=8, coding_rate=LoRa.CODING_4_5, power_mode=LoRa.ALWAYS_ON, tx_iq=False, rx_iq=False) self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) def update(self): raw_data = self.lora_sock.recv(61) if raw_data: try: msg = incoming_message(raw_data) if msg.deviceID % msg.Seq == msg.check: print("msg received. devid:", msg.deviceID, " seq:", msg.Seq) else: print("msg check failed") except: print("msg failed to parse") else: pass def test_server(): srv = server() while True: srv.update() test_server() -
@constantinos Many thanks. Unfortunately it's not working out of the box. I got some compiling errors on the Arduino side, perhaps the Arduino1.8.1 is too new. But my old 1.6.6 Arduino IDE did not work with the Feather M0 properly. And on the LoPy the firmware version is also 1.6.6 (what a chance :-)
I will check tomorrow your configuration parameters and code with my sketches so we will see.
-
@Clemens Maybe I made a mistake.
Here is the code that combiles with Arduino 1.6.8
#include <SPI.h> #include <RH_RF95.h> #define FREQUENCY 868.0 struct tpayload { uint32_t deviceid; //4 byte seq; //1 byte indicator1; //1 byte indicator2; //1 byte stype; //1 long svalue; //4 byte check; //1 }; tpayload payload; RH_RF95 rf95(10,2); // Chip Select=D10, INT Pin = D2 void setup() { Serial.begin(57600); if (!rf95.init()) { Serial.println("init failed"); } else { Serial.print("init OK - "); Serial.print(FREQUENCY); Serial.println("mhz"); } payload.seq = 0; payload.deviceid = 8512; payload.indicator1 = 1; payload.indicator1 = 2; payload.stype = 2; payload.svalue = -10; } void loop() { payload.seq++; if (payload.seq == 0) payload.seq++; // to avoid division by zero at the next line payload.check = payload.deviceid % payload.seq; // you need this to discard corrupted messages uint16_t now = micros(); rf95.send( (const void*)&payload, sizeof(payload)); delay(5000); } -
I got a compiling error and changed
rf95.send( (const uint8_t*)&payload, sizeof(payload));I did some other changes on the rf95.send line and received 3 packages. but unfortunately I cohld not replicate it.
-
@Clemens Further update about this issue.
I forgot to say that the experiment was done with firmware version 1.2.x.
Now I updated two LoPys with the latest firmware and I'm proud to announce that we have the same results: Nothing!I will keep searching...
-
@Clemens Daniel gave us the solution again!
just add public=False to Lora Initialization
cfg_mode = LoRa.LORA cfg_freq = 869000000 cfg_bandwidth=LoRa.BW_125KHZ # LoRa.BW_125KHZ or LoRa.BW_250KHZ cfg_sf = 7 # Accepts values between 6 and 12. # 6 = 64 Chips/Symbol # 7 = 128 Chips/Symbol # 8 = 256 Chips/Symbol # 9 = 512 Chips/Symbol # 10 = 1024 Chips/Symbol # 11 = 2048 Chips/Symbol # 12 = 4096 Chips/Symbol cfg_preamble=8 #configures the number of pre-amble symbols. The default value is 8 cfg_coding_rate=LoRa.CODING_4_5 #LoRa.CODING_4_5, LoRa.CODING_4_6, LoRa.CODING_4_7 or LoRa.CODING_4_8 cfg_power_mode=LoRa.ALWAYS_ON #LoRa.ALWAYS_ON, LoRa.TX_ONLY or LoRa.SLEEP self.lora = LoRa(mode=cfg_mode, frequency=cfg_freq, tx_power=14, bandwidth=cfg_bandwidth, sf=cfg_sf, preamble=cfg_preamble, coding_rate=cfg_coding_rate, power_mode=cfg_power_mode, tx_iq=False, rx_iq=False, public=False) self.lora.init(mode=cfg_mode, frequency=cfg_freq, tx_power=14, bandwidth=cfg_bandwidth, sf=cfg_sf, preamble=cfg_preamble, coding_rate=cfg_coding_rate, power_mode=cfg_power_mode, tx_iq=False, rx_iq=False, public=False) -
@constantinos Sorry for destroying your setup! ;-) (aka never change a running system) but I have seen your investigations in the thread "New firmware release 1.6.7.b1" Many thanks!
-
@Clemens Please do not apologise! My setup is not live at the moment!
-
@constantinos Yes! With the additional parameter
public=Falseit is running really smoothly. A small downside I noticed. Beside the RFM95 a second Lopy as "node" can now not connect with the LoPy Gateway in parallel to the RFM. No problem for me, because I will not use this scenario productive--just as a quick side note. -
@Clemens I think that It can be done. You may notice some additional bytes arriving from RFM95 to Lopy. These bytes are stored in msg.control field. If you want a lopy to send a message acting as an RFM95 add these "control" bytes to your message.
I'm sure about this because I was able to do a LoPy to RFM95 transmission.
-
@Clemens Try this
import struct from network import LoRa LORA_MSG_FORMAT = "LLBBBBlB" class outgoing_message: def __init__(self, control, deviceID, Seq, indicator1, indicator2, stype, svalue): global LORA_MSG_FORMAT self.data = struct.pack(LORA_MSG_FORMAT,control, deviceID, Seq, indicator1, indicator2, stype, svalue ) #sending code acting as RFM95 #lora = initialize your lora object #lora_sock = your lora socket object lora.power_mode(LoRa.TX_ONLY) msg = outgoing_message( <control_bytes:use the same RFM95 sends>, <deviceID>, <Seq>, <indicator1>, <indicator2>, <stype>, <svalue>) lora_sock.send(msg.data) -
Dear @constantinos,
thanks a bunch for providing these examples about how to decode the LoRa frame using
struct.unpack! We built upon that and gave a shot on a LoRa-to-HTTP gateway (gateway_lora_http_csv.py), which is forwarding data in CSV format to a HTTP endpoint, as this perfectly fits @Clemens' requirements. Maybe this can also spark your interest.For more details, please have a look at:
Please be aware these are only drafts and haven't been run on any real Pycom iron yet. However, the simple demo programs run successfully in a »MicroPython for Unix« sandbox. As we don't know about the coverage of the installation requirements in the Pycom MicroPython environment, we would be happy to receive any feedback about this.
There are also other examples e.g. for transmitting data using MQTT/JSON or by other means. A very basic MQTT example can be found at node_mqtt_json_basic.py. The intention and motto of this little telemetry framework is:
Using
micropython-uterkin, you can save a few lines of code and do simple things as well as more advanced ones using the very same telemetry library API, independent of transport protocol, acquisition channel address or serialization format.With kind regards,
Andreas.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login