LoRa with ESPNow

Published on Jun 27, 2023


A black and white topographic map

After writing a component for ESP-Now with ESPHome, it was time to add LoRa.

Semtech says this about LoRa:

LoRa (short for long range) is a spread spectrum modulation technique derived from chirp spread spectrum (CSS) technology. Semtech’s LoRa is a long range, low power wireless platform that has become the de facto wireless platform of Internet of Things (IoT).

Currently, ESPHome doesn’t have a native method to use LoRa. A simple-to-implement way to add it is to create a bridge. In this case, it will bridge a formatted LoRa transmission from a sensor node to a LoRa-MQTT bridge device.

To avoid repeating the same thing, you can read a bit more about the bridge device on the ESP-Now page. It uses the same format and works the same way.

Bonus points for being able to run this LoRa bridge concurrently with the ESP-Now bridge components. So if you wanted to use LoRa and ESP-Now sensors, you only need one bridge device.

BOM

  • 2x ESP32 boards with a LoRa radio
  • any sensor for testing, I’ll be using an SHT30

1.

Make sure your MQTT broker is set up for Home Assistant. The instructions can be found in the addon inside Home Assistant. You’ll probably want to follow the instructions by making a new MQTT user and configuring it as an integration. Or you can use your own and just add it as an integration. When you are done, you’ll have an MQTT box in Settings > Devices & Services.

2.

For the bridge, have a look at the ESPHome YAML below.

esphome:
  name: now-lora-mqtt-bridge
esp32:
  board: esp32dev
  variant: esp32
  framework:
    type: arduino
logger:

# import the components
external_components:
  - source:
      type: git
      url: https://github.com/u-fire/ESPHomeComponents/

# Setup SPI for the LoRa radio https://esphome.io/components/spi.html
spi:
  clk_pin: GPIO05
  mosi_pin: GPIO27
  miso_pin: GPIO19
  
lora_mqtt_bridge:
  cs_pin: GPIO18            # chip-select pin for LoRa radio, defaults to 18
  reset_pin: GPIO14         # reset pin for LoRa radio, defaults to 14
  dio_pin: GPIO26           # DIO0 pin for LoRa radio, defaults to 26
  frequency: 915000000      # frequency to use, defaults to 915 MHz
  # the options below are very dependent on your particular board and chip
  # not all combinations work
  # sync: 0xF3              # sets the sync word, defaults to 0x12
  # coding: 5               # sets the coding rate, defaults to 5
  # bandwidth: 250000       # sets the bandwidth, defaults to 125,000
  # spread: 12              # sets the spread, defaults to 7

# ESP-Now bridge works concurrently
now_mqtt_bridge:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

mqtt:
  id: mqtt_broker
  broker: !secret mqtt_broker
  username: !secret mqtt_username
  password: !secret mqtt_password

Setup the mqtt for your broker. You can change the Home Assistant discovery prefix (if you changed it for some reason), and it will also be used in the MQTT bridge.

Find your ESP32 pinout and match all the needed pins for SPI and the LoRa radio connections. Fill them in at the appropriate spots in the above YAML. Make sure you pick the right frequency for your device/antenna/location as well. This firmware doesn’t implement any limiting to work within rate-limited locations, so keep that in mind.

3.

For our sensor device, look at the YAML below.

esphome:
  name: example-sht3x-lora
esp32:
  board: esp32dev
  framework:
    type: arduino
logger:

# https://esphome.io/components/spi.html for LoRa radio
spi:
  clk_pin: GPIO05
  mosi_pin: GPIO27
  miso_pin: GPIO19

# https://esphome.io/components/i2c.html
i2c:
  sda: 32
  scl: 33

# import the components
external_components:
  - source:
      type: git
      url: https://github.com/u-fire/ESPHomeComponents/

lora_mqtt:
  cs_pin: GPIO18            # chip-select pin for LoRa radio, defaults to 18
  reset_pin: GPIO14         # reset pin for LoRa radio, defaults to 14
  dio_pin: GPIO26           # DIO0 pin for LoRa radio, defaults to 26
  frequency: 915000000      # frequency to use, defaults to 915 MHz

sensor:
  - platform: sht3xd
    temperature:
      name: "Outside Temperature"
    humidity:
      name: "Outside Humidity"

The ESP-Now component is the lora_mqtt block. There’s no need for the api or wifi block. The component works by waiting for each sensor to update its state. When that happens, it creates a line similar to the one explained in the ESPNow article and sends it out as a LoRa message.

Make any changes for your particular sensors and upload the YAML through the Home Assistant ESPHome addon or the ESPHome command line. You’ll start to see the scrolling of sensor measurements and notifications of sending LoRa messages. You’ll also see those same messages in the bridge serial output, and if you are paying attention to your MQTT broker, you’ll see new entries being added.

And most importantly, you’ll also see the new sensor inside the MQTT section of Settings -> Devices and Services.

4.

The sensor also has the option to get an on_sent notification. This allows you to enter deep sleep the moment all of the sensor measurements have been sent, saving awake time.

...
globals:
  - id: sent
    type: int
    restore_value: no
    initial_value: '0'

lora_mqtt:
  on_sent:
    then:
      - lambda: id(sent)++; 
      - if:
          condition:
            lambda: 'return id(sent) == 5;'
          then:
          - deep_sleep.enter:
              id: sleep_
              sleep_duration: 5m


deep_sleep:
  id: sleep_
...

The code creates a global variable named sent. Then it increases the value each time a sensor measurement is sent. If sent equals 5, which in this case is the number of sensors, it goes to sleep for 5 minutes.


You can look at all the code on our GitHub. There are a lot of other components there as well.

We’re on Discord, too.