LoRa >>> Long Range
LoRa is a radio modulation scheme, i.e. a way of encoding information for transmission. With LoRa you get very good receiver sensitivity and a low bit error rate. Its bandwidth is low so it is NOT a replacement for WiFi and you cant send pics or videos. However you will be able to communicate with your MCU's over huge distances.
About 2 weeks ago I knew next to nothing about LoRa. The price of the "ready to go" shields and boards was putting me off, but with claims of up to 15KM radio range I was very curious and eventually managed to get them for just under β¬8 a piece. With the NodeMCU's for about β¬5.50 each, this means you can get over 600 Metres range for a total of β¬27. Which is about half of what you would be paying if you used prebuilt.
Unfortunately I didn't realise the reason these "ready to go" boards are so expensive is because soldering SMT by hand is hard. Difficulty aside, it is very enjoyable and after spending so much time soldering you have a vested interest in making it work.
To make the connections from the SX127x to my NodeMCU, I cut standard jumper wires in half (one piece for the transmitter, one piece for the receiver). On the SX127x you will need to solder wires to:
- 2 x GND
- VCC
- NSS
- MOSI
- MISO
- SCLK
- DIO0
Id also suggest that while you're soldering, you connect the REST. It's not necessary, but I found different libraries which need it so in hindsight I wish I had done it.
A note on the soldering: Do not do what I did and use the thick gauge solder which comes free with the iron. Make life easier for yourself and get nice thin gauge solder.
I attached the antennas which came with the board (Short Thin Coils) and managed to get a range of a whole 15CM. Not exactly what I was expecting !! After a little research and desoldering, I found this page.
As you can see, they give specs on how to design your own antenna and more importantly they speak about the dipole. The second identical antenna connected to GND makes an enormous difference. Without the dipole, using just an antenna on both boards, I was only getting about 7 Metres, with the dipole I reached 570 Metres before I got to the end of the testing area, so at the time of writing the maximum range for this setup is > 570 Metres.
To make the ANT I took the cables from inside an old kettle / PC lead:
- cut them to the correct length ( this page. )
- Strip and tin both tips of all antenna (Light coat of solder to hold the stranded copper together)
- Strip the remaining wire (I used a Stanley knife / scalpel)
- Using a micro file, shape one end of each ANT into a point small enough to fit into the holes on the SX127x
- For ANT & Dipole on both boards you will need 4 of these.
I used a driver for the SX127x which was written by Wei1234c. To use Wei's code go to /examples/DuplexCallback folder and load all files onto the NodeMCUs. Both boards will flash a pattern on the onboard led on boot/reset, and afterwards will flash once for every packet received. The boards take turns sending and receiving data.
To make use of the OLED, find the on_receive(lora,payload) function contained in LoRaDuplexCallback.py. Here is where you tell the board what to do when it receives a packet. Add the following blocks of code to LoRaDuplexCallback to write to the I2C OLED.
# Add at the top of the file
#
import ssd1306
import machine
i2c = machine.I2C(-1, machine.Pin(4), machine.Pin(2))
oled = ssd1306.SSD1306_I2C(128, 32, i2c)
# Replace on_receive(lora, payload) function
#
def on_receive(lora, payload):
lora.blink_led()
try:
payload_string = payload.decode()
rssi = lora.packetRssi()
print("*** Received message ***\n{}".format(payload_string))
oled.fill(0)
oled.show()
oled.text('************', 16, 3)
oled.text('*** PING ***', 16, 12)
oled.text('************', 16, 20)
oled.show()
time.sleep(0.3)
oled.fill(0)
oled.show()
time.sleep(0.3)
oled.text('************', 16, 3)
oled.text('*** PING ***', 16, 12)
oled.text('************', 16, 20)
oled.show()
time.sleep(0.3)
oled.fill(0)
oled.show()
time.sleep(0.3)
oled.text('*** PING ***', 16, 3)
oled.text('RSSI : {}'.format(rssi), 24, 12)
oled.text('Packet : {}'.format(payload_string.split(' ')[1]), 16, 20)
oled.show()
except Exception as e:
print(e)
print("with RSSI {}\n".format(rssi))
Comments