Dans cet article, je vais vous montrer comment envoyer des données en utilisant LoRaWAN avec le Thinknode G1 Gateway. LoRa (Long Range) est une méthode sans fil pour envoyer de petites quantités de données sur des distances beaucoup plus longues (plusieurs kilomètres) que ce que peuvent atteindre le WiFi ou le Bluetooth, par exemple.
LoRaWAN est un protocole de transmission qui utilise LoRa. Il permet de construire des systèmes IoT complexes avec une communication sécurisée entre les appareils et les applications cloud. Si vous souhaitez surveiller des capteurs via Internet, LoRaWAN est ce qu’il vous faut.
Les End Devices (capteurs) envoient leurs données à une passerelle (Gateway), qui les transmet à un serveur réseau (Network Server). Un serveur d’application (Application Server) peut alors accéder au serveur réseau pour traiter les données, par exemple afficher un graphique avec les données de température.

Notez que les capteurs transmettent les données à la passerelle via LoRa, tandis que la passerelle communique avec le serveur réseau via une connexion Wi-Fi, Ethernet ou cellulaire. La passerelle est essentiellement un pont entre LoRa et Internet.
Dans les sections suivantes, nous utiliserons un ESP32 avec un module LoRa SX1276 pour transmettre des données environnementales telles que la température et l’humidité mesurées par un BME280 via LoRaWAN sur une passerelle Thinknode G1.
Nous connecterons cette passerelle à un serveur réseau sur le The Things Network, où vous pourrez ensuite surveiller les données environnementales ou y accéder depuis une application Internet pour un traitement ultérieur.
Commençons !
Pièces requises
J’ai utilisé un ESP32 Lite comme microprocesseur pour le nœud LoRa, mais tout autre ESP32 fonctionnera très bien aussi. Si vous souhaitez utiliser un Arduino ou un autre microprocesseur, vous aurez besoin d’une carte fonctionnant en 3,3 V.
Pour le module émetteur-récepteur LoRa SX1276, faites attention à la version que vous achetez ! Depending on the country les fréquences autorisées sont différentes. 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.
De même, assurez-vous que la passerelle LoRaWAN que vous utilisez peut fonctionner dans la bande de fréquence requise. La passerelle ThinkNode G1 listée ci-dessous supporte les fréquences 868 MHz et 915 MHz.
Pour le capteur environnemental, j’ai choisi le BME280, qui peut mesurer la température, l’humidité, la pression atmosphérique et l’altitude. Assurez-vous d’acheter la version 3,3 V, car nous allons le connecter à l’ESP32.

Passerelle ThinkNode G1 LoRaWAN

Module LoRa 868/915M SX1276

ESP32 lite

Câble USB de données

Capteur BME280

Jeu de fils Dupont

Plaque d’essai (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.
Qu’est-ce que LoRaWAN ?
LoRaWAN signifie Long Range Wide Area Network. C’est un protocole sans fil conçu spécifiquement pour l’Internet des objets (IoT), permettant aux appareils de communiquer sur de longues distances — plusieurs kilomètres, même en zones urbaines — en consommant très peu d’énergie.
Contrairement au WiFi ou Bluetooth, qui sont excellents pour des communications à courte portée et à haut débit, LoRaWAN mise sur la portée et l’efficacité. Un capteur envoie généralement de petits paquets de données toutes les quelques minutes ou heures, mais peut fonctionner sur une petite batterie pendant des années.
Il est idéal pour les appareils alimentés par batterie qui envoient peu d’informations, comme les capteurs de température, les traceurs GPS ou les moniteurs d’humidité du sol, sur des distances inaccessibles au Wi-Fi ou Bluetooth. En revanche, on ne peut pas envoyer d’images ou de vidéos via LoRa.
Supposons que vous ayez un capteur de température dans un endroit isolé. Il n’y a pas de WiFi, mais vous voulez quand même surveiller la température toutes les 15 minutes. Que faites-vous ?
Vous connectez un capteur de température à un ESP32 relié à un module LoRa (comme le SX1276). Il envoie les données sans fil via LoRa à une passerelle LoRaWAN, dans notre cas une Thinknode G1. Cette passerelle peut écouter les signaux de plusieurs capteurs situés à plusieurs kilomètres et transmet leurs données au serveur réseau. La passerelle est essentiellement un pont vers le web.
Vous pouvez exécuter votre propre serveur réseau ou utiliser un serveur public. Ici, nous utiliserons le The Things Network (TTN), une infrastructure LoRaWAN gratuite et open-source. Depuis TTN, les données peuvent être visualisées dans un tableau de bord, envoyées vers un service cloud ou utilisées pour déclencher d’autres actions — comme envoyer des alertes ou allumer un ventilateur. Et puisque le serveur réseau fonctionne dans le cloud, vos données peuvent être traitées, visualisées ou exploitées depuis n’importe où dans le monde.
Dans les sections suivantes, nous configurons la passerelle, la connectons à The Things Network et construisons le nœud LoRa avec un ESP32 comme microcontrôleur, le SX1276 comme émetteur-récepteur LoRa et le BME280 comme capteur environnemental.
La passerelle ThinkNode G1
ThinkNode G1 d’Elecrow est une passerelle LoRaWAN d’intérieur conçue pour se connecter à divers serveurs réseau. Cette passerelle supporte plusieurs méthodes de connexion pour la configuration telles que WiFi, Bluetooth et Ethernet. Elle supporte la transmission sur 8 canaux et utilise la technologie sans fil LoRa pour réaliser une transmission de données longue distance.

La passerelle est équipée d’un concentrateur LoRa SX1302 et de deux puces SX1250, offrant 10 voies de démodulation parallèles programmables. Elle supporte les bandes de fréquences ISM mondiales, avec une plage de fréquences de 815 MHz à 960 MHz.
Spécifications techniques
Le tableau suivant extrait de la page produit Elecrow liste les détails techniques de la passerelle Thinknode G1 :
| Processeur | CPU/SoC | MT7628N (MIPS24KEc@580MHz CPU) |
| Mémoire système | 128 Mo DDR2 | |
| Stockage | 32 Mo Nor Flash | |
| Logiciel de configuration | WEB | |
| Communication | ||
| Wi-Fi | Supporte les standards sans fil IEEE 802.11 b/g/n, antenne intégrée | |
| Câblé | Supporte les standards câblés IEEE 802.3, IEEE 802.3u, RJ45 (10M / 100M) | |
| Compatible Bluetooth | Bluetooth dual-mode compatible (BR/EDR+BLE) 5.0 BLE, antenne céramique intégrée | |
| LoRaWAN | Puces baseband | SX1302, utilisant le module baseband LR1302 |
| Canaux | 8 canaux | |
| Protocole nœud | Supporte Class A/Class B/Class C | |
| Bande de fréquence | EU868/US915 | |
| Sensibilité | -125 dBm @125KHz/SF7 -139 dBm @125KHz/SF12 | |
| Puissance d’émission | Maximum 26 dBm | |
| Antenne | 1. Antenne bâton en caoutchouc (accordée), gain 3 dBi, impédance 50 ohms; 2. Antenne externe avec base (optionnelle), gain 3 dBi, impédance 50 ohms; | |
| Interface réservée | Prise DC | Entrée d’alimentation, DC 12V – 2A |
| Ethernet | RJ45 (10M / 100 M) | |
| Prise antenne LoRa | Prise femelle RP-SMA | |
| Prise antenne GPS | Prise femelle RP-SMA | |
| Interface Type-C | Utilisée pour le contrôle en arrière-plan, la connexion au panneau de configuration ou la gravure du firmware, débogage | |
| Slot carte Micro SD | OUI | |
| Slot carte Nano SIM | OUI | |
| Voyant réservé | Voyant d’état de l’appareil | OUI |
| 4G | OUI (personnalisable) | |
| WLAN | OUI | |
| LoRa | OUI | |
| PWR | OUI | |
| Bouton | Bouton Reset | |
| Dimensions | 140*140*38 mm | |
| Matériau du boîtier | ABS+PC (boîtier), PC givré (guide de lumière) | |
| Alimentation | 12V-2A | |
| Température de fonctionnement | -20℃~55℃ | |
| Température de stockage | -30℃~70℃ | |
Pour plus d’informations, voir le ThinkNode G1 Datasheet.
Voyants lumineux
Le Thinknode G1 possède cinq voyants lumineux. Les quatre à l’avant indiquent si la passerelle est sous tension, et si elle est connectée à LoRa, WLAN ou LTE. La photo ci-dessous montre le dessus du G1 avec les quatre voyants à l’avant du boîtier :

Le grand voyant LED en forme de Y en haut peut s’allumer en différentes couleurs et clignoter à différentes vitesses. Le tableau ci-dessous décrit la signification des différents signaux :

Connecteurs
À l’arrière du Thinknode G1, vous trouverez les connecteurs pour l’alimentation, Ethernet (ETH), USB-C, l’antenne LoRa, les emplacements pour une carte Micro SD et une carte Nano SIM :

À l’arrière se trouve également un bouton pour redémarrer ou entrer en mode configuration. Le tableau suivant décrit comment basculer entre les modes :

Installation du matériel
Connectez d’abord l’antenne puis l’alimentation. Le voyant d’alimentation doit devenir vert et le voyant supérieur sera rouge jusqu’à ce que la passerelle soit correctement configurée.

Pour la configuration, vous pouvez connecter la passerelle via un câble Ethernet (ETH) ou WIFI. Le User Manual du ThinkNode G1 décrit les deux méthodes. Dans la section suivante, je vous montre comment j’ai configuré le logiciel du ThinkNode G1 en utilisant la connexion WIFI.
Configuration logicielle
Pour configurer via Wi-Fi, appuyez et maintenez le bouton à l’arrière du ThinkNode G1 jusqu’à ce que le voyant LED en haut devienne bleu (cela prend environ 5 secondes) :

Connexion à l’interface utilisateur
Puis scannez votre réseau Wi-Fi pour un nouveau point d’accès nommé ThinkNode-G1_XXXXXX et connectez-vous :

Ensuite, ouvrez votre navigateur et allez à l’adresse IP 192.168.1.1. Vous devriez voir un écran de connexion où vous entrez « root » comme nom d’utilisateur et aussi comme mot de passe :

Connexion au Wi-Fi
Pour connecter la passerelle à votre réseau Wi-Fi, allez à Network -> Wireless

et cliquez sur Scan pour rechercher votre réseau Wi-Fi :

Dans la liste, cliquez sur votre réseau Wi-Fi et dans la boîte de dialogue suivante, entrez le mot de passe pour y accéder.

Configurer LoRaWAN
Ensuite, nous devons configurer l’interface LoRa et la fréquence. Allez à LoRaWAN -> LoRa Gateway

Dans la boîte de dialogue suivante, sélectionnez WIFI comme interface LoRa, et EU868 comme plan de fréquence pour l’Europe. En Amérique du Nord, vous devez sélectionner US915. Réglez le mode LoRa sur Packet Forwarder :

(Alternativement, si vous souhaitez configurer la passerelle comme station de base, consultez le Webtutorial).
Laissez les autres paramètres tels quels mais assurez-vous que l’adresse du serveur est définie sur eu1.cloud.thethings.network (si vous êtes en Europe). Nous en aurons besoin pour connecter la passerelle à The Things Network.
Enfin, appuyez sur Save & Apply, ce qui redémarrera la passerelle et, si vous avez de la chance, ce sera tout.

Cependant, j’ai rencontré des problèmes et j’ai dû aussi entrer le serveur DNS, sinon mon G1 ne se connectait pas à The Things Network.
Serveur DNS
Pour ajouter ou modifier le serveur DNS, allez à Network -> Interfaces et appuyez sur le bouton Edit pour le LAN :

Dans la boîte de dialogue, cliquez sur l’onglet Advanced Settings et modifiez les champs Use custom DNS servers :

J’ai ajouté 8.8.8.8 (Google) et 1.1.1.1 (Cloudflare) comme serveurs DNS et finalement ma passerelle s’est connectée à The Things Network.
Connexion de la passerelle à The Things Network
The Things Network (TTN) vous offre un serveur réseau public qui permet d’envoyer des données de capteurs depuis un appareil LoRa, par exemple la température, vers un site web où vous pouvez consulter les données ou les traiter avec une application web.
La première étape est de connecter notre passerelle ThinkNode G1 à TTN. Allez à l’URL suivante : https://eu1.cloud.thethings.network/console/, cliquez sur le bouton bleu Add et sélectionnez Add new gateway :

Entrez votre Gateway EUI, qui est imprimé à l’arrière de la passerelle ThinkNode G1 ou peut être trouvé sur la page Status de l’interface de configuration de la passerelle. Après avoir entré l’EUI, appuyez sur Confirm :

Cela étendra la boîte de dialogue et vous pourrez alors entrer un ID unique pour la passerelle, par exemple l’EUI de la passerelle avec le préfixe ‘eui’ et un nom de passerelle, j’ai choisi Maet-ThinkNode-G1 pour ce test. Vous devez aussi sélectionner un plan de fréquence qui correspond à la fréquence de votre passerelle (Europe 863-870 MHz) pour l’Europe, par exemple :

Laissez tout le reste tel quel et appuyez sur Register gateway. Si tout fonctionne correctement, vous verrez une page de statut affichant un statut vert Gateway indiquant que la passerelle est connectée :

Si vous en êtes là, félicitations. Le plus dur est passé ; )
Créer une application
The Things Network (TTN) organise les End Devices (capteurs, actionneurs) en « Applications ». Leur rôle est de décoder les données et éventuellement de les transférer vers des serveurs externes via Webhooks ou MQTT.
Les Applications, Passerelles et End Devices interagissent ainsi : l’End Device envoie des données (uplink) via LoRa. Ensuite, la passerelle reçoit les données et les transmet à TTN. Enfin, le serveur réseau TTN route les données vers une application spécifique en utilisant le DevEUI de l’appareil.
[End Device] ←→ [Gateway] ←→ [TTN Network Server] ←→ [Application]
Donc, avant de pouvoir recevoir et surveiller les données des capteurs sur TTN, nous devons créer une application. Pour cela, allez à https://eu1.cloud.thethings.network/console/applications/add, ce qui ouvrira la boîte de dialogue suivante :

Entrez un ID d’application, par exemple env-sensor-network et un nom d’application, par exemple Environmental Sensors comme montré ci-dessus.
Enregistrer un End Device
Ensuite, nous allons ajouter et enregistrer notre End Device. Sur la page de votre application (https://eu1.cloud.thethings.network/console/applications/env-sensor-network), vous devriez voir une boîte avec un bouton bleu intitulé « + Register end device » :

Appuyez sur ce bouton et vous obtiendrez la boîte de dialogue suivante :

Entrez les données pour votre End Device, surtout le plan de fréquence, la version LoRaWAN et le JoinEUI. Le JoinEUI (anciennement AppEUI) est un numéro au format suivant : 70B3D57EDxxxxxxx. Remplacez ‘xxxxxxx’ par un nombre hexadécimal pour créer un JoinEUI unique pour votre End Device, par exemple 70B3D57ED0000001.
Une fois fait, cliquez sur le bouton Confirm à droite, ce qui étendra la boîte de dialogue et vous permettra de générer un DevEUI et une AppKey. Enfin, vous devez donner un ID unique à votre End Device :

Appuyez sur Register end device puis vous devriez voir les informations pour l’appareil que vous avez créé :

Les informations les plus importantes sont l’AppEUI, le DevEUI et l’AppKey. Vous aurez besoin de ces identifiants dans le code de l’End Device. Ils permettent à l’End Device de s’authentifier auprès de The Things Network.
Construire un End Device LoRaWAN avec SX1276 et ESP32
Vous pouvez acheter de nombreux appareils LoRaWAN préfabriqués avec toutes sortes de capteurs et fonctions, mais ils sont chers. Pour un aperçu, voyez le Device Repository for LoRaWAN de The Things Network. Dans ce tutoriel, nous allons construire notre propre End Device, ce qui n’est pas difficile et beaucoup moins cher ; )
Nous utiliserons un ESP32 comme microcontrôleur et un module émetteur-récepteur SX1276 pour transmettre les données via LoRa. Si vous avez besoin de plus d’informations sur le SX1276, voyez le Long range communication with LoRa SX1276 and ESP32 tutoriel. Ci-dessous, je vais faire court et vous montrer comment connecter le SX1276 à l’ESP32. Voici le tableau de connexion :
| SX1276 | ESP32 |
|---|---|
| MOSI | 23 |
| MSIO | 19 |
| SCK | 18 |
| RST | 17 |
| NSS | 5 |
| DIO0 | 4 |
| DIO1 | 16 |
| GND | GND |
| VCC | 3.3V |
Assurez-vous de connecter VCC à la broche 3,3 V de votre ESP32. En plus de l’interface SPI (MOSI, MISO, SCK, RST, NSS), les connexions numériques IO sur les broches DIO0 et DIO1 sont également essentielles. L’image ci-dessous montre le schéma de câblage complet :

Comme mentionné précédemment, vous devez utiliser un module émetteur-récepteur SX1276 qui fonctionne sur la LoRa frequency that is permitted in your country. Dans le schéma de câblage ci-dessus, vous pouvez voir que le SX1276 est marqué 868M, ce qui signifie qu’il utilise la bande 868 MHz pour l’Europe. Pour l’Amérique du Nord, vous aurez besoin d’un module 915 MHz.
La fréquence du SX1276, de la passerelle et les réglages sur The Things Network doivent tous correspondre ! Dans mon cas, ils sont tous réglés sur 868 MHz.
Envoyer des données de test via LoRaWAN
Passons maintenant à l’écriture du code pour envoyer des données de test depuis notre End Device (ESP32 + SX1276) via LoRaWAN vers TTN.
Mais d’abord, vous devrez installer une bibliothèque pour LoRaWAN et nous allons utiliser la MCCI LoRaWAN LMIC library. Ouvrez simplement le LIBRARY MANAGER, cherchez « mcci lorawan lmic library » et appuyez sur INSTALL. L’image ci-dessous montre une installation réussie :

Notez que LoRaWAN définit trois classes d’appareils : Classe A, Classe B et Classe C, chacune offrant différents compromis entre consommation d’énergie et disponibilité du downlink. La Classe A est le mode par défaut et le plus économe en énergie, où un appareil ne peut recevoir des messages downlink que dans deux courtes fenêtres après avoir transmis un uplink. Cette classe est idéale pour les capteurs alimentés par batterie et est entièrement supportée par la bibliothèque LMIC.
La Classe B ajoute des fenêtres de réception programmées utilisant des balises périodiques envoyées par la passerelle, permettant un accès downlink plus prévisible au prix d’une consommation d’énergie plus élevée. Les appareils de Classe C gardent leurs fenêtres de réception ouvertes presque tout le temps, permettant une communication downlink à faible latence mais nécessitant une alimentation constante (par exemple, appareils sur secteur). Cependant, la bibliothèque LMIC ne supporte que la Classe A.
Configuration de la bibliothèque
Ensuite, nous devons configurer la bibliothèque LMIC pour la fréquence LoRa, la version et la puce que nous utilisons. La bibliothèque LMIC contient un fichier lmic_project_config.h que vous trouverez généralement sous le chemin Windows suivant :
...\OneDrive\Documents\Arduino\libraries\MCCI_LoRaWAN_LMIC_library\project_config
Ouvrez ce fichier et modifiez son contenu comme indiqué ci-dessous :
#define CFG_eu868 1 //#define CFG_us915 1 //#define CFG_au915 1 //#define CFG_as923 1 //#define CFG_kr920 1 //#define CFG_in866 1 #define CFG_sx1276_radio 1 //#define CFG_sx1261_radio 1 //#define CFG_sx1262_radio 1 //#define ARDUINO_heltec_wifi_lora_32_V3 //#define LMIC_USE_INTERRUPTS #define LMIC_LORAWAN_SPEC_VERSION LMIC_LORAWAN_SPEC_VERSION_1_0_3
Encore une fois, si vous ne vivez pas en Europe, vous devrez choisir la fréquence LoRa pour votre pays (Europe -> CFG_eu868, Amérique du Nord -> CFG_us915, …). Assurez-vous de commenter toutes les autres fréquences.
Nous utilisons la puce SX1276, donc nous définissons aussi CFG_sx1276_radio 1. Si vous utilisez une puce LoRa différente, vous devrez aussi la changer ici.
Code pour envoyer des données avec LoRaWAN
Le code suivant envoie toutes les minutes une valeur de compteur sous forme de chaîne, par exemple « Counter = 5 » depuis notre End Device (ESP32 + SX1276) via la passerelle ThinkNode vers TTN, où nous pouvons l’inspecter. Plus d’informations à ce sujet plus tard. Pour l’instant, jetez un coup d’œil rapide au code avant que nous en discutions les détails :
#include <lmic.h>
#include <hal/hal.h>
static const u1_t PROGMEM APPEUI[8] = { 0x01, 0x00, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
void os_getArtEui(u1_t* buf) {
memcpy_P(buf, APPEUI, 8);
}
static const u1_t PROGMEM DEVEUI[8] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28};
void os_getDevEui(u1_t* buf) {
memcpy_P(buf, DEVEUI, 8);
}
static const u1_t PROGMEM APPKEY[16] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 };
void os_getDevKey(u1_t* buf) {
memcpy_P(buf, APPKEY, 16);
}
static osjob_t sendjob;
const unsigned TX_INTERVAL = 60; // Send every minute
const lmic_pinmap lmic_pins = {
.nss = 5,
.rxtx = LMIC_UNUSED_PIN,
.rst = 17,
.dio = { 4, 16, LMIC_UNUSED_PIN }
};
void onEvent(ev_t ev) {
Serial.printf("%d: ", os_getTime());
switch (ev) {
case EV_JOINING:
Serial.println("EV_JOINING");
break;
case EV_JOINED:
Serial.println("EV_JOINED");
LMIC_setLinkCheckMode(0);
break;
case EV_JOIN_FAILED:
Serial.println("EV_JOIN_FAILED");
break;
case EV_TXCOMPLETE:
Serial.println("EV_TXCOMPLETE");
if (LMIC.dataLen) {
Serial.printf("> Downlink %d bytes\n", LMIC.dataLen);
Serial.print("> Data: ");
for (int i = 0; i < LMIC.dataLen; i++) {
Serial.printf("%02X ", LMIC.frame[LMIC.dataBeg + i]);
}
Serial.println();
}
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println("EV_TXCANCELED");
break;
case EV_JOIN_TXCOMPLETE:
Serial.println("EV_JOIN_TXCOMPLETE: no JoinAccept");
break;
default:
Serial.print("Unknown event: ");
Serial.println((unsigned)ev);
break;
}
}
void do_send(osjob_t* j) {
static uint16_t counter = 0;
static char mydata[25];
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
snprintf(mydata, sizeof(mydata), "Counter = %u", counter);
LMIC_setTxData2(1, (uint8_t*)mydata, strlen(mydata), 0);
Serial.printf("> Data: %s\n", mydata);
counter++;
}
}
void setup() {
Serial.begin(115200);
os_init_ex(&lmic_pins);
LMIC_reset();
do_send(&sendjob);
}
void loop() {
os_runloop_once();
}
Bibliothèques
Le code commence par inclure les bibliothèques LMIC requises :
#include <lmic.h> #include <hal/hal.h>
Ces bibliothèques nous fournissent tout ce dont nous avons besoin pour communiquer avec la puce SX1276 et gérer la fonctionnalité LoRaWAN. Le fichier d’en-tête lmic.h gère la logique du protocole, tandis que hal/hal.h connecte LMIC au matériel (dans ce cas, notre ESP32 et SX1276).
Authentification
L’authentification LoRaWAN commence avec trois clés critiques : APPEUI, DEVEUI, et APPKEY. Ce sont les identifiants de l’appareil utilisés pour rejoindre un réseau LoRaWAN via OTAA (Over-The-Air Activation). Vous avez entré/généré ces clés lors de la création de l’End Device dans TTN et vous pouvez les voir dans les informations de l’appareil :

Cependant, la bibliothèque LMIC attend les octets pour APPEUI et DEVEUI dans l’ordre LSB-first (octet de poids faible en premier), ce qui signifie que vous devez inverser les octets pour APPEUI et DEVEUI dans le code. Par exemple, si l’AppEUI dans les infos de l’appareil sur TTN est 70 B3 D5 7E D0 00 00 01 comme montré ci-dessus, dans le code cela devient :
APPEUI[8] = { 0x01, 0x00, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
La même règle s’applique pour DEVUI mais pas pour APPKEY – elle reste dans le même ordre d’octets !
Constantes clés
Le code crée des tableaux constants pour ces clés d’authentification dans le bon ordre d’octets, puis appelle une fonction qui copie la clé dans un tampon utilisé par LMIC pendant le processus de jonction. Ces fonctions garantissent que votre ESP32 peut s’authentifier en toute sécurité auprès de votre serveur réseau LoRaWAN, comme The Things Network.
Ci-dessous la constante pour l’APPEUI avec la fonction « copy » os_getArtEui() :
static const u1_t PROGMEM APPEUI[8] = { 0x01, 0x00, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
void os_getArtEui(u1_t* buf) {
memcpy_P(buf, APPEUI, 8);
}
La directive PROGMEM stocke les données en mémoire flash pour économiser la RAM. La même logique s’applique pour le DEVEUI et la clé d’application. Rappelez-vous simplement que APPEUI et DEVEUI sont en ordre d’octets inversé mais pas APPKEY :
static const u1_t PROGMEM DEVEUI[8] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28};
void os_getDevEui(u1_t* buf) {
memcpy_P(buf, DEVEUI, 8);
}
static const u1_t PROGMEM APPKEY[16] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 };
void os_getDevKey(u1_t* buf) {
memcpy_P(buf, APPKEY, 16);
}
Évidemment, vous devrez utiliser les valeurs APPEUI, DEVEUI et APPKEY de votre application TTN et End Device !
Constantes
Ensuite, le code définit un objet global de tâche et un intervalle de transmission.
static osjob_t sendjob; const unsigned TX_INTERVAL = 60; // Send every minute
L’objet sendjob contient la tâche programmée pour une exécution ultérieure, tandis que TX_INTERVAL définit la fréquence d’envoi des données — ici, une fois toutes les 60 secondes.
Mappage des broches
Nous définissons maintenant le mappage des broches entre l’ESP32 et le module LoRa SX1276 :
const lmic_pinmap lmic_pins = {
.nss = 5,
.rxtx = LMIC_UNUSED_PIN,
.rst = 17,
.dio = { 4, 16, LMIC_UNUSED_PIN }
};
Cette structure indique à LMIC quelles broches GPIO sont connectées aux lignes de contrôle du SX1276. Par exemple, nss est la broche chip-select SPI, rst est Reset, et dio correspond aux broches d’interruption utilisées par la radio.
onEvent
La fonction onEvent() gère divers événements LoRaWAN — tout, des requêtes de jonction aux transmissions terminées.
void onEvent(ev_t ev) {
Serial.printf("%d: ", os_getTime());
switch (ev) {
case EV_JOINING:
Serial.println("EV_JOINING");
break;
case EV_JOINED:
Serial.println("EV_JOINED");
LMIC_setLinkCheckMode(0);
break;
...
}
}
Cette fonction vous aide à surveiller ce que fait votre appareil. Par exemple, EV_JOINED signifie que l’appareil s’est connecté avec succès au réseau, et nous désactivons le mode de vérification de lien avec LMIC_setLinkCheckMode(0) pour économiser du temps d’air. Quand EV_TXCOMPLETE se déclenche, l’appareil a fini d’envoyer des données, et nous programmons la prochaine transmission :
case EV_TXCOMPLETE:
Serial.println("EV_TXCOMPLETE");
if (LMIC.dataLen) {
Serial.printf("> Downlink %d bytes\n", LMIC.dataLen);
Serial.print("> Data: ");
for (int i = 0; i < LMIC.dataLen; i++) {
Serial.printf("%02X ", LMIC.frame[LMIC.dataBeg + i]);
}
Serial.println();
}
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
Le cas EV_TXCOMPLETE vérifie aussi si le module LoRa a reçu des données (downlink). S’il y a un downlink (LMIC.dataLen > 0), le code affiche les octets des données en nombres hexadécimaux.
Vous pouvez envoyer des données depuis TTN en cliquant sur l’onglet Messaging de votre End Device :

do_send
La logique principale de transmission se trouve dans la fonction do_send().
void do_send(osjob_t* j) {
static uint16_t counter = 0;
static char mydata[25];
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
snprintf(mydata, sizeof(mydata), "Counter = %u", counter);
LMIC_setTxData2(1, (uint8_t*)mydata, strlen(mydata), 0);
Serial.printf("> Data: %s\n", mydata);
counter++;
}
}
Cette fonction construit une chaîne comme "Counter = 23" et la met en file d’attente pour la transmission. Elle vérifie d’abord si une autre transmission est en attente — LoRaWAN est strict sur le timing. Si c’est libre, elle envoie le paquet sur le port 1 sans confirmation (le dernier argument 0 signifie uplink non confirmé).
setup
La fonction setup() lance tout :
void setup() {
Serial.begin(115200);
os_init_ex(&lmic_pins);
LMIC_reset();
do_send(&sendjob);
}
Elle initialise le port série pour le débogage, configure la pile LMIC avec le bon mappage des broches, réinitialise l’état interne de LMIC, et programme la première transmission.
loop
Enfin, la fonction loop() maintient le runtime LMIC actif.
void loop() {
os_runloop_once();
}
Contrairement aux boucles Arduino traditionnelles, LMIC nécessite cet appel dans loop() pour que le planificateur de tâches et le système d’événements fonctionnent correctement.
Moniteur série
Si vous téléversez le code et ouvrez le moniteur série, vous devriez voir les messages suivants apparaître :

Messages uplink
Avec cette configuration, votre ESP32 et SX1276 enverront une chaîne compteur via LoRaWAN chaque minute. Si vous allez sur TTN, vous pouvez choisir de voir les messages de données uplink envoyés par notre End Device. Sélectionnez Applications et cliquez sur Live data :

Sur la droite, vous verrez alors le message horodaté envoyé par notre ESP32 :

Formatteur de charge utile
Cependant, il ne montre pas les données réelles du message, notre valeur compteur. C’est parce que TTN ne sait pas comment décoder les données dans le message. Vous devrez spécifier ou implémenter un Payload Formatter pour pouvoir voir les données.
Ouvrez la barre latérale, sélectionnez Application, cliquez sur Payload formatters et choisissez Uplink :

Vous pouvez alors sélectionner un Payload Formatter existant ou en implémenter un vous-même. Nous allons en implémenter un, donc sélectionnez « Custom Javascript formatter » comme Type de formateur :

Pour « Formatter code », entrez le code suivant, qui convertit simplement les octets envoyés en caractères :
function decodeUplink(input) {
let str = "";
for (let i = 0; i < input.bytes.length; i++) {
str += String.fromCharCode(input.bytes[i]);
}
return { data: { message: str } };
}
Si vous regardez maintenant les messages uplink à nouveau, vous trouverez un champ Payload à la fin, qui montre la chaîne avec la valeur compteur envoyée par l’End Device :

Dans la section suivante, nous ajoutons un capteur environnemental à l’ESP32 et modifions le code pour envoyer la température, l’humidité et la pression atmosphérique via LoRaWAN à TTN.
Envoyer des données environnementales via LoRaWAN
Une application classique de LoRaWAN est d’envoyer des données environnementales telles que température, humidité et pression atmosphérique d’un End Device LoRa vers TTN. Dans cette section, nous allons ajouter le capteur BME280 à notre circuit et étendre le code pour envoyer les données mesurées par le capteur.
Si vous voulez plus d’informations sur le BME280, voyez le How To Use BME280 Pressure Sensor ou les Temperature Plotter on e-Paper Display tutoriels.
Connexion du BME280 à l’ESP32
Le capteur BME280 possède une interface I2C et est facile à ajouter au circuit. Le tableau suivant montre toutes les connexions à réaliser, y compris celles existantes pour le SX1276 :
| SX1276 | BME280 | ESP32 |
|---|---|---|
| MOSI | – | 23 |
| MSIO | – | 19 |
| SCK | – | 18 |
| RST | – | 17 |
| NSS | – | 5 |
| DIO0 | – | 4 |
| DIO1 | – | 16 |
| – | SCL | 25 |
| – | SDA | 33 |
| GND | GND | GND |
| VCC | VCC | 3.3V |
Et voici le câblage complet entre le BME280, le SX1276 et l’ESP32 :

Code pour envoyer des données environnementales via LoRaWAN
Ensuite, nous allons installer deux bibliothèques : La Adafruit_BME280 pour lire les données du BME280 :

et la CayenneLPP library, qui formate les données des capteurs pour les transmissions LoRaWAN :

Le code suivant est une modification simple et une extension du code précédent. Au lieu d’envoyer un compteur, nous envoyons les mesures de température, humidité et pression atmosphérique du capteur BME280. Jetez un coup d’œil rapide, puis nous discuterons des différences avec le code précédent :
#include <lmic.h>
#include <hal/hal.h>
#include <CayenneLPP.h>
#include <Adafruit_BME280.h>
static const u1_t PROGMEM APPEUI[8] = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 };
void os_getArtEui(u1_t* buf) {
memcpy_P(buf, APPEUI, 8);
}
static const u1_t PROGMEM DEVEUI[8] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28};
void os_getDevEui(u1_t* buf) {
memcpy_P(buf, DEVEUI, 8);
}
static const u1_t PROGMEM APPKEY[16] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 };
void os_getDevKey(u1_t* buf) {
memcpy_P(buf, APPKEY, 16);
}
static osjob_t sendjob;
const unsigned TX_INTERVAL = 60; // Send every minute
const lmic_pinmap lmic_pins = {
.nss = 5,
.rxtx = LMIC_UNUSED_PIN,
.rst = 17,
.dio = { 4, 16, LMIC_UNUSED_PIN }
};
CayenneLPP lpp(16);
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 onEvent(ev_t ev) {
Serial.printf("%d: ", os_getTime());
switch (ev) {
case EV_JOINING:
Serial.println("EV_JOINING");
break;
case EV_JOINED:
Serial.println("EV_JOINED");
LMIC_setLinkCheckMode(0);
break;
case EV_JOIN_FAILED:
Serial.println("EV_JOIN_FAILED");
break;
case EV_TXCOMPLETE:
Serial.println("EV_TXCOMPLETE");
if (LMIC.dataLen) {
Serial.printf("> Downlink %d bytes\n", LMIC.dataLen);
Serial.print("> Data: ");
for (int i = 0; i < LMIC.dataLen; i++) {
Serial.printf("%02X ", LMIC.frame[LMIC.dataBeg + i]);
}
Serial.println();
}
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println("EV_TXCANCELED");
break;
case EV_JOIN_TXCOMPLETE:
Serial.println("EV_JOIN_TXCOMPLETE: no JoinAccept");
break;
default:
Serial.print("Unknown event: ");
Serial.println((unsigned)ev);
break;
}
}
void do_send(osjob_t* j) {
bme.takeForcedMeasurement();
float temp = bme.readTemperature();
float hum = bme.readHumidity();
float pres = bme.readPressure() / 100.0;
lpp.reset();
lpp.addTemperature(1, temp); // channel 1
lpp.addRelativeHumidity(2, hum); // channel 2
lpp.addBarometricPressure(3, pres); // channel 3
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
Serial.printf("> Temperature: %.2f\n", temp);
Serial.printf("> Humidity: %.2f\n", hum);
Serial.printf("> Pressure: %.2f\n", pres);
}
}
void setup() {
Serial.begin(115200);
initBMESensor();
os_init_ex(&lmic_pins);
LMIC_reset();
do_send(&sendjob);
}
void loop() {
os_runloop_once();
}
Le code utilise les mêmes clés APPEUI, DEVEUI et APPKEY qu’avant. L’extension principale est une fonction qui initialise le capteur BME280 et une modification de la fonction qui envoie les données.
initBMESensor
La fonction initBMESensor() initialise le BME280 en utilisant l’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 :
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);
}
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 approche é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é.
do_send
La fonction do_send() récupère d’abord les mesures de température, humidité et pression atmosphérique du capteur BME280.
void do_send(osjob_t* j) {
bme.takeForcedMeasurement();
float temp = bme.readTemperature();
float hum = bme.readHumidity();
float pres = bme.readPressure() / 100.0;
Elle formate ensuite les données pour la transmission LoRaWAN en ajoutant la température, l’humidité et la pression atmosphérique comme différents canaux dans le paquet de données :
lpp.reset(); lpp.addTemperature(1, temp); // channel 1 lpp.addRelativeHumidity(2, hum); // channel 2 lpp.addBarometricPressure(3, pres); // channel 3
Enfin, les données sont envoyées comme le paquet habituel d’octets. De plus, le code affiche les données dans le moniteur série :
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
Serial.printf("> Temperature: %.2f\n", temp);
Serial.printf("> Humidity: %.2f\n", hum);
Serial.printf("> Pressure: %.2f\n", pres);
}
}
Pour plus d’informations, consultez le Send Environmental Data with LoRa tutoriel qui fait quelque chose de similaire mais utilise LoRa brut au lieu de LoRaWAN.
Moniteur série
Si vous téléversez et exécutez le code, vous devriez voir la sortie suivante dans votre moniteur série :

Formatteur de charge utile
Si vous voulez inspecter les données sur TTN, vous devrez spécifier un Payload Formatter comme avant. Cependant, dans ce cas, c’est plus simple. Nous n’avons pas besoin d’écrire notre propre formateur Javascript personnalisé, mais pouvons utiliser le formateur CayenneLPP :

Dans l’aperçu de l’appareil, vous pouvez alors voir les données environnementales bien formatées envoyées dans les trois canaux :

Et voilà. Maintenant vous savez comment construire votre propre End Device LoRaWAN pour envoyer des données environnementales via la passerelle ThinkNode G1 vers TTN.
Conclusions
Cet article a présenté la passerelle Thinknode G1. Une passerelle LoRaWAN vous permet essentiellement d’envoyer des données de capteurs LoRa vers Internet. Nous avons construit notre propre capteur LoRa avec un ESP32, un SX1276 et un capteur BME280, et l’avons utilisé pour envoyer température, humidité et pression à The Things Network.
Nous n’avons fait qu’effleurer la surface de LoRaWAN et je vous encourage à parcourir les informations sur www.thethingsnetwork.org/docs/lorawan pour en apprendre davantage. Pour plus d’aide sur la configuration du ThinkNode G1, voyez le Manual et le Webtutorial.
Si vous voulez juste transmettre des données entre deux appareils LoRa, LoRaWAN est probablement excessif et vous feriez mieux d’utiliser LoRa brut. Jetez un œil au Long range communication with LoRa SX1276 and ESP32 et au Send Environmental Data with LoRa.
Enfin, si vous préférez un Arduino à l’ESP32, vous devez soit utiliser un convertisseur de niveau logique, soit un Arduino fonctionnant en 3,3 volts, car le module SX1276 ne fonctionne pas en 5 V ! Consultez le Interface Arduino Uno with ST7735 TFT using Level Shifter tutoriel pour plus d’informations.
Si vous avez des questions, n’hésitez pas à les laisser dans la section commentaires.
Bon bricolage ; )
Liens
Voici quelques liens que j’ai trouvés utiles lors de la rédaction de cet article :
- ThinkNode G1 Gateway Setup
- ThinkNode G1 LoRaWAN gateway setup and testing
- Maximizing LoRaWAN coverage with an indoor gateway – ThinkNode G1 setup and review
- 5 Things You Need to Know about LoRaWAN-based Gateways
- Set Up the LoRa Module Network to Communicate with the ThinkNode Gateway
- How to use ESP32 for LoRa communication with the Things Network
- MCCI LoRaWAN LMIC Library
- CayenneLPP Library

