Skip to Content

Envoyer des données environnementales avec LoRa

Envoyer des données environnementales avec LoRa

Dans ce tutoriel, vous apprendrez comment envoyer des données environnementales avec LoRa. LoRa vous permet de transmettre des données de capteurs sur de longues distances (plusieurs kilomètres) tout en consommant très peu d’énergie. Nous allons utiliser cela pour transmettre les données de température, d’humidité et de pression atmosphérique mesurées par un BME280 entre deux ESP32 connectés à des modules LoRa SX1276.

Si vous ne connaissez pas LoRa, je vous suggère de lire d’abord notre Long range communication with LoRa SX1276 and ESP32 tutoriel, car il vous fournira les informations de base nécessaires pour ce tutoriel.

Pièces requises

Vous trouverez ci-dessous les composants nécessaires. J’ai utilisé une ancienne carte ESP32, qui est obsolète mais que vous pouvez encore obtenir à très bas prix. Cependant, n’importe quelle autre ESP32 fonctionnera très bien aussi. N’oubliez pas que vous aurez besoin de deux cartes et de deux modules SX1276 – un pour l’envoi et un pour la réception.

Pour les modules transceivers LoRa SX1276, faites attention à la version que vous achetez ! Selon le pays, les fréquences autorisées sont différentes (link). C’est 868 MHz en Europe, 915 MHz en Amérique du Nord et 433 MHz en Asie.

La description du module indique soit la fréquence, soit un numéro tel que 868 ou 915 dans le nom. J’ai listé un module en 868 MHz, car je suis en Europe. Mais vous pouvez aussi obtenir ce module pour la bande 915 MHz.

Pour le capteur environnemental, j’ai choisi le BME280, car il est compact, dispose d’un mode veille et peut mesurer la température, l’humidité, la pression atmosphérique et l’altitude. Notez qu’il existe des versions 5V et 3.3V de la carte breakout BME280. Assurez-vous d’acheter la version 3.3V ! Si vous avez seulement besoin de température et d’humidité, le Si7021 est une bonne alternative.

2 x Module LoRa 868/915M SX1276

ESP32 lite Lolin32

2 x ESP32 lite

BME280

Capteur BME280

USB data cable

Câble USB de données

Dupont wire set

Jeu de fils Dupont

Half_breadboard56a

2x Breadboard

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Module LoRa SX1276

Le SX1276 est un transceiver LoRa fabriqué par Semtech. La plupart des modules (cartes breakout) basés sur ce circuit intégré sont configurés pour 433 MHz (Asie), 868 MHz (Europe) ou 915 MHz (Amérique du Nord), selon votre région. Au dos du module, vous trouverez généralement un petit tableau indiquant la fréquence de fonctionnement du module spécifique. L’image ci-dessous montre un module qui fonctionne dans la bande 915 MHz et qui pourrait donc être utilisé en Amérique du Nord :

Back of SX1276 LoRa Module
Dos du module LoRa SX1276

Assurez-vous d’utiliser un module avec la fréquence de transmission correcte pour votre pays ! Le module peut communiquer sur des distances de 2 à plus de 15 kilomètres, selon la qualité de l’antenne, le terrain et les réglages. Le SX1276 supporte des débits de données de 0,018 kbps à 37,5 kbps. Pour plus de détails techniques, consultez la fiche technique liée ci-dessous :

Le module possède 16 broches. Une pour l’antenne (ANT), une pour l’alimentation (VCC), plusieurs broches de masse (GND), les broches pour SPI (RST, NSS, SCK, MOSI, MISO) et six broches configurables Digital IO (DIO).

Notez que le SX1276 utilise une logique 3.3V et ne peut donc pas être connecté directement à un Arduino UNO, qui fonctionne en logique 5V. Si vous souhaitez utiliser un Arduino au lieu d’un ESP32, vous devez soit utiliser un logic level shifter, soit une carte Arduino qui utilise 3.3V logic.

Capteur BME280

Pour mesurer les données environnementales telles que la température, l’humidité et la pression atmosphérique, nous allons utiliser le BME280 sensor.

Une des raisons est qu’il dispose d’un mode veille à faible consommation, où il ne consomme que 0,1 µA (3,6 µA en mode normal). En combinaison avec un module LoRa et l’ESP32-lite avec un courant de deep-sleep de 5,65 mA (à 5V), cela constitue une configuration très basse consommation pouvant fonctionner longtemps sur batterie.

Le capteur BME280 lui-même est minuscule et est généralement livré sur une carte breakout avec une interface I2C ; voir l’image ci-dessous.

BME280 breakout board
Carte breakout BME280

Le capteur peut mesurer une pression de 300 hPa à 1100 hPa, une température de -40°C à +85°C, et une humidité de 0% à 100%. Pour plus d’informations sur le BME280, consultez notre tutoriel sur How To Use BME280 Pressure Sensor With Arduino ou le Weather Station on e-Paper Display tutoriel.

Connexion du SX1276 à l’ESP32

Le SX1276 est contrôlé via une interface SPI. Lors du câblage avec un ESP32, nous devons effectuer les connexions suivantes :

SX1276ESP32
MOSI23
MSIO19
SCK18
RST17
NSS5
DIO04
GNDGND
VCC3.3V

Assurez-vous de connecter VCC à la broche 3.3V de votre ESP32. Nous n’utilisons pas vraiment DIO0, vous pouvez donc omettre cette connexion. DIO0 est nécessaire si vous souhaitez ajouter un gestionnaire d’interruption appelé lorsque la mesure est terminée. L’image ci-dessous montre le schéma de câblage complet (y compris DIO0) :

Connecting SX1276 to ESP32
Connexion du SX1276 à l’ESP32

Si vous utilisez une autre carte ESP32, les broches SPI matérielles sur lesquelles repose ce câblage peuvent différer. Si vous ne savez pas quelles broches utiliser sur votre carte, consultez le Find I2C and SPI default pins tutoriel.

La photo ci-dessous montre le câblage du récepteur LoRa SX1276 avec l’ESP32 sur une breadboard :

SX1276 LoRa Receiver with the ESP32 on a breadboard
Récepteur LoRa SX1276 avec ESP32 sur breadboard

Notez que le module SX1276 a un espacement des broches de 2 mm et ne s’adapte pas directement à une breadboard. Consultez le Long range communication with LoRa SX1276 and ESP32 tutoriel pour apprendre à fabriquer une version compatible breadboard du module.

Connexion du BME280 à l’ESP32

Nous voulons mesurer la température ambiante, l’humidité et la pression atmosphérique avec le capteur BME280. Comme les broches I2C/SPI matérielles de l’ESP32 sont déjà utilisées par le SX1276, nous utilisons un I2C logiciel avec les broches libres 33 pour SDA et 25 pour SCL comme montré ci-dessous.

Connecting BME280 to ESP32
Connexion du BME280 à l’ESP32

Voici le tableau de connexion pour le BME280 et l’ESP32. Vous pouvez utiliser d’autres broches pour l’I2C, mais si vous le faites, n’oubliez pas d’ajuster le code dans la section suivante en conséquence.

BME280 ESP32
SDA33
SCL25
GNDGND
VCC3.3V

Notez qu’il existe des versions 5V et 3.3V de la carte breakout BME280. J’utilise la version 3.3V et connecte donc VCC à la broche 3.3V de l’ESP32.

Comme le WEMOS LOLIN32 Lite dispose d’un port batterie et d’un chargeur intégrés, vous pouvez alimenter tout le système avec une batterie LiPo. L’image ci-dessous montre le câblage complet avec une batterie LiPo connectée :

SX1276 LoRa Sender with ESP32 and LiPo on breadboard
Émetteur LoRa SX1276 avec ESP32 et LiPo sur breadboard

J’ai mesuré un courant de deep sleep de 0,2 mA et un courant de 140 mA lors de la transmission des données. Si vous utilisez une 18650 battery, qui a une capacité d’environ 3300 mAh (selon la marque spécifique), vous pouvez probablement faire fonctionner le capteur pendant environ un an si vous mesurez et transmettez les données toutes les minutes.

Code pour le récepteur LoRa

Dans cette section, nous écrivons d’abord le code pour le récepteur, car il est plus simple. Le code suivant reçoit la température, l’humidité et la pression du capteur BME280 envoyées via le module LoRa SX1276 et affiche la mesure sur le moniteur série :

#include <SPI.h>
#include <LoRa.h>

// WEMOS LOLIN32 Lite
// MOSI ->  23
// MISO ->  19
// SCK  ->  18
#define SS 5
#define RST 17
#define DIO0 4


void initLoRa() {
  LoRa.setPins(SS, RST, DIO0);
  // 433E6: Asia, 868E6: Europe, 915E6: North America
  while (!LoRa.begin(868E6)) {
    Serial.println(".");
    delay(500);
  }
  LoRa.setSyncWord(0xF3);          // 0-0xFF sync word to match the receiver
  LoRa.setSpreadingFactor(12);     // (6-12) higher value increases range but decreases data rate
  LoRa.setSignalBandwidth(125E3);  // lower value increases range but decreases data rate
  LoRa.setCodingRate4(8);          // higher value increases range but decreases data rate
  LoRa.enableCrc();
}

void readLoRaData() {
  static char data[128];
  int i = 0;
  while ((i < 128) && LoRa.available()) {
    data[i++] = LoRa.read();
  }
  data[i] = '\0';
  //Serial.println(data);

  float temp, hum, pres;
  sscanf(data, "%f|%f|%f", &temp, &hum, &pres);

  Serial.printf("%.1fC  %.0f%%  %.0fhPa  (%d)\n",
                temp, hum, pres, LoRa.packetRssi());
}

void setup() {
  Serial.begin(115200);
  initLoRa();
}

void loop() {
  if (LoRa.parsePacket()) {
    readLoRaData();
  }
}

Bibliothèques

Pour commencer, le code inclut les bibliothèques nécessaires. La bibliothèque SPI.h gère la communication entre l’ESP32 et le module LoRa, tandis que LoRa.h nous offre une interface simple avec le module SX1276.

#include <SPI.h>
#include <LoRa.h>

Vous pouvez installer la bibliothèque LoRa library de Sandeep Mistry via le gestionnaire de bibliothèques dans l’IDE Arduino. L’image ci-dessous montre une installation réussie de la bibliothèque :

LoRa library in LIBRARY MANAGER
Bibliothèque LoRa dans le gestionnaire de bibliothèques

Constantes

Ensuite, le code définit les broches SPI spécifiques au WEMOS LOLIN32 Lite, une carte de développement ESP32 compacte. Les broches SS, RST et DIO0 sont essentielles pour la communication LoRa et doivent être configurées correctement selon votre câblage.

#define SS 5
#define RST 17
#define DIO0 4

initLoRa

Voici la fonction initLoRa(). Cette fonction initialise la radio LoRa et la configure pour votre région et vos besoins de performance. D’abord, elle configure les broches de contrôle avec LoRa.setPins().

LoRa.setPins(SS, RST, DIO0);

Ensuite, le code tente de démarrer la radio LoRa à une fréquence de 868 MHz, utilisée en Europe. Si l’initialisation échoue, il réessaie toutes les 500 millisecondes en affichant des points sur le moniteur série.

while (!LoRa.begin(868E6)) {
  Serial.println(".");
  delay(500);
}

Une fois le module LoRa démarré, plusieurs paramètres sont configurés pour maximiser la portée. Le mot de synchronisation est réglé à 0xF3, ce qui aide à filtrer les paquets qui ne proviennent pas de votre réseau. Le facteur d’étalement est augmenté à 12 pour une portée plus longue, et la largeur de bande du signal est réduite à 125 kHz pour améliorer encore la portée. Le taux de codage est fixé à 4/8, privilégiant la portée sur la vitesse. Enfin, la vérification CRC est activée pour garantir l’intégrité des données.

LoRa.setSyncWord(0xF3);
LoRa.setSpreadingFactor(12);
LoRa.setSignalBandwidth(125E3);
LoRa.setCodingRate4(8);
LoRa.enableCrc();

readLoRaData

La fonction readLoRaData() est déclenchée à chaque arrivée d’un paquet. Elle lit les octets disponibles du module LoRa dans un tampon de caractères, en veillant à ne pas dépasser 128 caractères. Une fois terminé, elle termine la chaîne par un caractère nul.

static char data[128];
int i = 0;
while ((i &lt; 128) &amp;&amp; LoRa.available()) {
  data[i++] = LoRa.read();
}
data[i] = '\0';

Ensuite, elle utilise sscanf() pour extraire trois valeurs flottantes — température, humidité et pression — en utilisant le symbole pipe (|) comme délimiteur. Ces valeurs sont ensuite affichées sur le moniteur série dans un format lisible, avec le RSSI (Received Signal Strength Indicator), qui indique la force du signal reçu.

float temp, hum, pres;
sscanf(data, "%f|%f|%f", &amp;temp, &amp;hum, &amp;pres);

Serial.printf("%.1fC  %.0f%%  %.0fhPa  (%d)\n",
              temp, hum, pres, LoRa.packetRssi());

setup

La fonction setup() est courte et simple. Elle initialise l’interface série à 115200 bauds pour le débogage et appelle initLoRa() pour préparer la radio.

void setup() {
  Serial.begin(115200);
  initLoRa();
}

loop

Enfin, la fonction loop() vérifie en continu la présence de paquets LoRa entrants. Lorsqu’elle détecte un paquet avec LoRa.parsePacket(), elle appelle readLoRaData() pour traiter les informations.

void loop() {
  if (LoRa.parsePacket()) {
    readLoRaData();
  }
}

Au lieu d’afficher sur le moniteur série, vous pourriez afficher les données environnementales sur un écran OLED ou e-Paper, les enregistrer sur une carte SD, ou les envoyer vers le cloud.

Code pour l’émetteur LoRa

Cette section contient le code pour l’émetteur. Ce code complète celui du récepteur décrit ci-dessus. L’émetteur mesure les données environnementales telles que la température, l’humidité et la pression atmosphérique, transmet les données toutes les minutes via LoRa et met l’ESP32 en mode deep-sleep entre les transmissions pour économiser la batterie :

#include <Wire.h>
#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_BME280.h>

// WEMOS LOLIN32 Lite
// MOSI ->  23
// MISO ->  19
// SCK  ->  18
#define SS 5
#define RST 17
#define DIO0 4

Adafruit_BME280 bme;

void initBMESensor() {
  Wire.begin(33, 25);  // Software I2C for BME280
  bme.begin(0x76, &Wire);
  bme.setSampling(Adafruit_BME280::MODE_FORCED,
                  Adafruit_BME280::SAMPLING_X1,  // temperature
                  Adafruit_BME280::SAMPLING_X1,  // pressure
                  Adafruit_BME280::SAMPLING_X1,  // humidity
                  Adafruit_BME280::FILTER_OFF);
}

void initLoRa() {
  LoRa.setPins(SS, RST, DIO0);
  // 433E6: Asia, 868E6: Europe, 915E6: North America
  while (!LoRa.begin(868E6)) {
    Serial.println(".");
    delay(500);
  }
  LoRa.setSyncWord(0xF3);          // 0-0xFF sync word to match the receiver
  LoRa.setSpreadingFactor(12);     // (6-12) higher value increases range but decreases data rate
  LoRa.setSignalBandwidth(125E3);  // lower value increases range but decreases data rate
  LoRa.setCodingRate4(8);          // higher value increases range but decreases data rate
  LoRa.enableCrc();
}

void sendLoRaData() {
  static char data[128];

  bme.takeForcedMeasurement();
  float temp = bme.readTemperature();
  float hum = bme.readHumidity();
  float pres = bme.readPressure() / 100.0;

  sprintf(data, "%.2f|%.2f|%.2f", temp, hum, pres);
  Serial.print(data);

  LoRa.beginPacket();
  LoRa.print(data);
  LoRa.endPacket();
}

void shutdownPeripherals() {
  LoRa.sleep();

  Wire.end();
  pinMode(33, INPUT);
  pinMode(25, INPUT);

  SPI.end();
  pinMode(23, INPUT); // MOSI
  pinMode(19, INPUT); // MISO
  pinMode(18, INPUT); // SCK
  pinMode(SS, INPUT);  // SS
  pinMode(RST, INPUT); // RST
  pinMode(DIO0, INPUT);  // DIO0
}

void setup() {
  Serial.begin(115200);
  initBMESensor();
  initLoRa();
  sendLoRaData();
  shutdownPeripherals();
  esp_sleep_enable_timer_wakeup(60 * 1000 * 1000);  // 1 min
  esp_deep_sleep_start();
}

void loop() {
}

Bibliothèques

D’abord, le code inclut les bibliothèques pour la communication LoRa et l’accès au capteur BME280. Bien que nous ayons déjà parlé de SPI.h et LoRa.h, ce sketch utilise aussi Wire.h pour la communication I2C et Adafruit_BME280.h, qui fournit une interface de haut niveau pour le capteur.

#include <Wire.h>
#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_BME280.h>

Vous pouvez installer la bibliothèque Adafruit_BME280 via le gestionnaire de bibliothèques et après une installation réussie, elle devrait apparaître ainsi :

Adafruit_BME280 library in Library Manager
Bibliothèque Adafruit_BME280 dans le gestionnaire de bibliothèques

Objets

Le capteur BME280 est instancié avec le pilote d’Adafruit. Cet objet, bme, gérera toutes les lectures.

Adafruit_BME280 bme;

initBMESensor

La fonction initBMESensor() initialise le BME280 en utilisant un I2C logiciel. Au lieu des broches I2C par défaut de l’ESP32, elle spécifie GPIO 33 pour SDA et GPIO 25 pour SCL, ce qui peut être utile si le bus I2C par défaut est utilisé ailleurs.

Wire.begin(33, 25);  // Software I2C for BME280
bme.begin(0x76, &Wire);

Notez que j’utilise l’adresse I2C 0x76 lors de la configuration du capteur via bme.begin(0x76, &Wire). Votre capteur peut avoir une adresse I2C différente. Par exemple, 0x77 est aussi courante pour le BME280.

Le capteur est configuré en mode forcé, ce qui signifie qu’il ne mesure que lorsqu’on lui demande explicitement. Cette méthode économise de l’énergie. L’échantillonnage est réglé au minimum (1x) pour la température, la pression et l’humidité, et le filtre embarqué est désactivé.

bme.setSampling(Adafruit_BME280::MODE_FORCED,
                Adafruit_BME280::SAMPLING_X1,
                Adafruit_BME280::SAMPLING_X1,
                Adafruit_BME280::SAMPLING_X1,
                Adafruit_BME280::FILTER_OFF);

initLora

La fonction initLoRa() est identique à celle du sketch récepteur et configure le module LoRa pour une communication longue portée à faible débit. Si vous avez besoin d’un rappel sur son fonctionnement, remontez à l’explication précédente.

sendLoRaData

Voici le cœur du sketch : sendLoRaData(). Cette fonction lit les dernières valeurs environnementales du BME280 et les envoie via LoRa. D’abord, elle force le capteur à prendre une nouvelle mesure.

bme.takeForcedMeasurement();

Elle lit ensuite la température, l’humidité et la pression. La pression est divisée par 100 pour convertir de Pascals en hPa, correspondant au format attendu par le récepteur.

float temp = bme.readTemperature();
float hum = bme.readHumidity();
float pres = bme.readPressure() / 100.0;

Les données du capteur sont ensuite formatées en une seule chaîne, utilisant le caractère | comme délimiteur. Cela correspond au format attendu côté récepteur :

sprintf(data, "%.2f|%.2f|%.2f", temp, hum, pres);
Serial.print(data);

Une chaîne typique ressemble à ceci : 25.59|54.93|1001.23. Au lieu d’envoyer une chaîne, nous pourrions aussi envoyer les données en octets. Chaque float fait 4 octets, donc envoyer 3×4 = 12 octets réduirait la quantité de données à transmettre. En revanche, ajouter plus de données et décompresser côté récepteur serait plus complexe.

Ensuite, le code commence un paquet LoRa, écrit les données, puis ferme le paquet pour le transmettre.

LoRa.beginPacket();
LoRa.print(data);
LoRa.endPacket();

shutdownPeripherals

Une fois les données envoyées, la fonction shutdownPeripherals() éteint tout ce qui n’est pas nécessaire. Elle met le module LoRa en veille, termine les bus I2C et SPI, et reconfigure toutes les broches GPIO associées en entrées pour éviter une consommation inutile.

LoRa.sleep();

Wire.end();
pinMode(33, INPUT);
pinMode(25, INPUT);

SPI.end();
pinMode(23, INPUT);
pinMode(19, INPUT);
pinMode(18, INPUT);
pinMode(SS, INPUT);
pinMode(RST, INPUT);
pinMode(DIO0, INPUT);

setup

La fonction setup() rassemble tout. Elle initialise l’interface série, le capteur BME280 et le module LoRa. Puis elle envoie les données et éteint tout. Enfin, elle configure l’ESP32 pour se réveiller du deep sleep après 60 secondes via un réveil par minuterie, et entre immédiatement en mode deep sleep.

esp_sleep_enable_timer_wakeup(60 * 1000 * 1000);  // 1 min
esp_deep_sleep_start();

loop

La fonction loop() reste vide car l’ESP32 ne l’atteint jamais. Après l’envoi des données, le microcontrôleur dort jusqu’à ce qu’il se réveille pour répéter le cycle.

void loop() {
}

Et voilà. Avec le code pour l’émetteur et le récepteur, vous avez un système pour mesurer des données environnementales avec un capteur situé à plusieurs kilomètres et pouvant fonctionner longtemps sur batterie.

Conclusions

Dans ce tutoriel, vous avez appris comment mesurer des données environnementales telles que la température, l’humidité et la pression atmosphérique avec un capteur BME280, et comment transmettre ces données sur de longues distances en utilisant LoRa et le module transceiver SX1276.

Contrairement au WiFi ou au Bluetooth, LoRa vous permet d’envoyer des données depuis des capteurs situés à plusieurs kilomètres et qui doivent fonctionner longtemps sur batterie. Je n’ai pas passé beaucoup de temps à minimiser la consommation de la batterie et la vidéo suivante (BME280 Sleep Mode) peut contenir des informations supplémentaires utiles.

Si vous transmettez des données seulement entre quelques capteurs, LoRa brut suffit. Mais si vous avez beaucoup de capteurs à gérer et souhaitez envoyer les mesures sur Internet, LoRaWAN est un meilleur choix. Consultez le LoRaWAN with Thinknode G1 Gateway tutoriel pour plus d’informations à ce sujet.

Nous avons affiché les mesures sur le moniteur série, mais vous pouvez facilement étendre le code pour afficher les données sur un écran. Jetez un œil aux tutoriels Weather Station on e-Paper Display et How to configure TFT_eSPI Library for TFT display.

Si vous souhaitez aussi afficher les données météo d’Internet ou l’heure actuelle, je vous recommande les tutoriels Simple ESP32 Internet Weather Station et Automatic Daylight Savings Time Clock.

Si vous avez des questions, n’hésitez pas à les laisser dans la section commentaires.

Bon bricolage ; )