Table des matières:

Communication sans fil LoRa 3Km à 8Km avec dispositif E32 (sx1278/sx1276) à faible coût pour Arduino, Esp8266 ou Esp32 : 15 étapes
Communication sans fil LoRa 3Km à 8Km avec dispositif E32 (sx1278/sx1276) à faible coût pour Arduino, Esp8266 ou Esp32 : 15 étapes

Vidéo: Communication sans fil LoRa 3Km à 8Km avec dispositif E32 (sx1278/sx1276) à faible coût pour Arduino, Esp8266 ou Esp32 : 15 étapes

Vidéo: Communication sans fil LoRa 3Km à 8Km avec dispositif E32 (sx1278/sx1276) à faible coût pour Arduino, Esp8266 ou Esp32 : 15 étapes
Vidéo: A la casse ou aux enchères : la fin de vie de nos voitures 2024, Novembre
Anonim
Communication sans fil LoRa 3Km à 8Km avec dispositif E32 (sx1278/sx1276) à faible coût pour Arduino, Esp8266 ou Esp32
Communication sans fil LoRa 3Km à 8Km avec dispositif E32 (sx1278/sx1276) à faible coût pour Arduino, Esp8266 ou Esp32

Je crée une bibliothèque pour gérer EBYTE E32 basée sur la série Semtech d'appareil LoRa, appareil très puissant, simple et bon marché.

Vous pouvez trouver la version 3Km ici, la version 8Km ici

Ils peuvent fonctionner sur une distance de 3000m à 8000m, et ils ont beaucoup de fonctionnalités et de paramètres. Je crée donc cette bibliothèque pour simplifier l'utilisation.

C'est une solution pour récupérer des données de capteurs métropolitains ou pour contrôler un drone.

Fournitures

Arduino UNO

Wemos D1 mini

LoRa E32 TTL 100 version 3Km

LoRa E32 TTL 1W version 8Km

Étape 1: Bibliothèque

Une bibliothèque
Une bibliothèque

Vous pouvez trouver ma bibliothèque ici.

Télécharger.

Cliquez sur le bouton TÉLÉCHARGEMENTS dans le coin supérieur droit, renommez le dossier non compressé LoRa_E32.

Vérifiez que le dossier LoRa_E32 contient LoRa_E32.cpp et LoRa_E32.h.

Placez le dossier de la bibliothèque LoRa_E32 dans votre dossier /libraries/. Vous devrez peut-être créer le sous-dossier des bibliothèques s'il s'agit de votre première bibliothèque.

Redémarrez l'IDE.

Étape 2: brochage

Brochage
Brochage
Brochage
Brochage
Brochage
Brochage

Comme vous pouvez le voir, vous pouvez définir différents modes via les broches M0 et M1.

Certaines broches peuvent être utilisées de manière statique, mais si vous le connectez au microcontrôleur et que vous les configurez dans la bibliothèque, vous gagnez en performances et vous pouvez contrôler tous les modes via un logiciel, mais nous allons mieux expliquer ensuite.

Étape 3: broche AUX

Broche AUX
Broche AUX
Broche AUX
Broche AUX
Broche AUX
Broche AUX

Comme je l'ai déjà dit, il n'est pas important de connecter toutes les broches à la sortie du microcontrôleur, vous pouvez mettre les broches M0 et M1 sur HIGH ou LOW pour obtenir la configuration souhaitée, et si vous ne connectez pas AUX, la bibliothèque définit un délai raisonnable pour être sûr que l'opération est terminée.

Broche AUX

Lors de la transmission de données, il peut être utilisé pour réveiller le MCU externe et renvoyer HIGH à la fin du transfert de données.

Lors de la réception AUX va LOW et retourne HIGH lorsque le tampon est vide.

Il est également utilisé pour l'auto-vérification afin de rétablir le fonctionnement normal (à la mise sous tension et en mode veille/programme).

Étape 4: Schéma entièrement connecté Esp8266

Schéma entièrement connecté Esp8266
Schéma entièrement connecté Esp8266
Schéma entièrement connecté Esp8266
Schéma entièrement connecté Esp8266

Le schéma de connexion esp8266 est plus simple car il fonctionne à la même tension que les communications logiques (3.3v).

Il est important d'ajouter une résistance de rappel (4, 7Kohm) pour obtenir une bonne stabilité.

Étape 5: schéma entièrement connecté Arduino

Arduino de schéma entièrement connecté
Arduino de schéma entièrement connecté
Arduino de schéma entièrement connecté
Arduino de schéma entièrement connecté

La tension de fonctionnement Arduino est de 5v, nous devons donc ajouter un diviseur de tension sur les broches RX M0 et M1 du module LoRa pour éviter tout dommage, vous pouvez obtenir plus d'informations ici Diviseur de tension: calculatrice et application.

Vous pouvez utiliser une résistance de 2Kohm à GND et 1Kohm à partir du signal que mis ensemble sur RX.

Étape 6: Bibliothèque: Constructeur

J'ai fait un ensemble de constructeurs assez nombreux, car on peut avoir plus d'options et de situations à gérer.

LoRa_E32(octet rxPin, octet txPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32(octet rxPin, octet txPin, octet auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); LoRa_E32(octet rxPin, octet txPin, octet auxPin, octet m0Pin, octet m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Le premier ensemble de constructeurs est créé pour déléguer la gestion de Serial et d'autres broches à la bibliothèque.

rxPin et txPin sont les broches pour se connecter à UART et elles sont obligatoires.

auxPin est une broche qui vérifie l'état de fonctionnement, de transmission et de réception (nous allons mieux expliquer ensuite), cette broche Ce n'est pas obligatoire, si vous ne la définissez pas, j'applique un délai pour permettre à l'opération de se terminer (avec latence).

m0pin et m1Pin sont les broches pour changer de MODE de fonctionnement (voir le tableau ci-dessus), je pense que ces broches en "production" vont se connecter directement en HAUT ou en BAS, mais pour test elles sont utilement gérées par la librairie.

bpsRate est le boudrate de SoftwareSerial est normalement 9600 (le seul débit en bauds en mode programmin/sleep)

Un exemple simple est

#include "LoRa_E32.h"LoRa_E32 e32ttl100(2, 3); // RX, TX // LoRa_E32 e32ttl100(2, 3, 5, 6, 7); // Réception, Émission

On peut utiliser directement un SoftwareSerial avec un autre constructeur

LoRa_E32(HardwareSerial* série, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32(HardwareSerial* série, octet auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32(HardwareSerial* série, octet auxPin, octet m0Pin, octet m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

L'exemple supérieur avec ce constructeur peut être fait comme ça.

#include #include "LoRa_E32.h"

SoftwareSerial mySerial(2, 3); // Réception, Émission

LoRa_E32 e32ttl100(&mySerial);

// LoRa_E32 e32ttl100(&mySerial, 5, 7, 6);

Le dernier ensemble de constructeurs permet d'utiliser un HardwareSerial au lieu de SoftwareSerial.

LoRa_E32(SoftwareSerial* série, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32(SoftwareSerial* série, octet auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32(SoftwareSerial* série, octet auxPin, octet m0Pin, octet m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Étape 7: Commencer

La commande begin est utilisée pour démarrer Serial et les broches en mode d'entrée et de sortie.

void commencer();

en exécution est

// Démarrage de toutes les broches et UART

e32ttl100.begin();

Étape 8: Méthode de configuration et d'information

Il existe un ensemble de méthodes pour gérer la configuration et obtenir des informations sur l'appareil.

ResponseStructContainer getConfiguration();

ResponseStatus setConfiguration(Configuration de configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

ResponseStructContainer getModuleInformation();

void printParameters(struct Configuration configuration);

ResponseStatus resetModule();

Étape 9: Conteneur de réponse

Pour simplifier la gestion de réponse je crée un ensemble de conteneur, pour moi très utile pour gérer les erreurs et renvoyer des données génériques.

État de la réponse

Ceci est un conteneur d'état et a 2 points d'entrée simples, avec cela vous pouvez obtenir le code d'état et la description du code d'état

Serial.println(c.getResponseDescription()); // Description du code

Serial.println(c.code); // 1 si Réussite

Les codes sont

SUCCÈS = 1, ERR_INCONNU, ERR_NOT_SUPPORT, ERR_NOT_IMPLEMENT, ERR_NOT_INITIAL, ERR_INVALID_PARAM, ERR_DATA_SIZE_NOT_MATCH, ERR_BUF_TOO_SMALL, ERR_TIMEOUT, ERR_MATÉRIEL, ERR_HEAD_NOT_RECOGNIZED

Conteneur de réponse

Ce conteneur est créé pour gérer la réponse String et possède 2 points d'entrée.

data avec la chaîne renvoyée par message et status une instance de RepsonseStatus.

ResponseContainer rs = e32ttl.receiveMessage();

Message de chaîne = rs.data;

Serial.println(rs.status.getResponseDescription());

Serial.println(message);

ResponseStructContainer

C'est le conteneur le plus "complexe", je l'utilise pour gérer la structure, il a le même point d'entrée que ResponseContainer mais les données sont un pointeur vide pour gérer la structure complexe.

ResponseStructContainer c;

c = e32ttl100.getConfiguration (); // Il est important d'obtenir le pointeur de configuration avant toute autre opération

Configuration configuration = *(Configuration*) c.data;

Serial.println(c.status.getResponseDescription());

Serial.println(c.status.code);

getConfiguration et setConfiguration

La première méthode est getConfiguration, vous pouvez l'utiliser pour récupérer toutes les données stockées sur l'appareil.

ResponseStructContainer getConfiguration();

Voici un exemple d'utilisation.

ResponseStructContainer c;

c = e32ttl100.getConfiguration (); // Il est important d'obtenir le pointeur de configuration avant toute autre opération

Configuration configuration = *(Configuration*) c.data;

Serial.println(c.status.getResponseDescription());

Serial.println(c.status.code);

Serial.println(configuration. SPED.getUARTBaudRate());

La structure de configuration contient toutes les données de paramètres et j'ajoute une série de fonctions pour obtenir toute la description des données individuelles.

configuration. ADDL = 0x0; // Première partie de addressconfiguration. ADDH = 0x1; // Deuxième partie de la configuration de l'adresse. CHAN = 0x19;// Configuration du canal. OPTION.fec = FEC_0_OFF; // Configuration du commutateur de correction d'erreur en avant. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Configuration du mode de transmission. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; // Configuration de la gestion des pull-up. OPTION.transmissionPower = POWER_17; // configuration de la puissance de transmission en dBm. OPTION.wirelessWakeupTime = WAKE_UP_1250; // Temps d'attente pour la configuration de réveil. SPED.airDataRate = AIR_DATA_RATE_011_48; // Configuration du débit de données aériennes. SPED.uartBaudRate = UART_BPS_115200; // Configuration du débit en bauds de la communication. SPED.uartParity = MODE_00_8N1; // Bit de parité

Vous avez la fonction équivalente pour tous les attributs pour obtenir toutes les descriptions:

Serial.print(F("Chan: ")); Serial.print(configuration. CHAN, DEC); Serial.print(" -> "); Serial.println(configuration.getChannelDescription());Serial.println(F(" ")); Serial.print(F("SpeedParityBit: ")); Serial.print(configuration. SPED.uartParity, BIN);Serial.print(" -> "); Serial.println(configuration. SPED.getUARTParityDescription()); Serial.print(F("SpeedUARTDatte: ")); Serial.print(configuration. SPED.uartBaudRate, BIN);Serial.print(" -> "); Serial.println(configuration. SPED.getUARTBaudRate()); Serial.print(F("SpeedAirDataRate: ")); Serial.print(configuration. SPED.airDataRate, BIN);Serial.print(" -> "); Serial.println(configuration. SPED.getAirDataRate()); Serial.print(F("OptionTrans: ")); Serial.print(configuration. OPTION.fixedTransmission, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getFixedTransmissionDescription()); Serial.print(F("OptionPullup: ")); Serial.print(configuration. OPTION.ioDriveMode, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getIODroveModeDescription()); Serial.print(F("OptionWakeup: ")); Serial.print(configuration. OPTION.wirelessWakeupTime, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getWirelessWakeUPTimeDescription()); Serial.print(F("OptionFEC: ")); Serial.print(configuration. OPTION.fec, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getFECDescription()); Serial.print(F("OptionPower: ")); Serial.print(configuration. OPTION.transmissionPower, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getTransmissionPowerDescription());

De la même manière, setConfiguration veut une structure de configuration, donc je pense que la meilleure façon de gérer la configuration est de récupérer la configuration actuelle, d'appliquer la seule modification dont vous avez besoin et de la redéfinir.

ResponseStatus setConfiguration(Configuration de configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

configuration est la structure précédemment affichée, saveType vous permet de choisir si le changement devient définitif uniquement pour la session en cours.

ResponseStructContainer c;c = e32ttl100.getConfiguration(); // Il est important d'obtenir le pointeur de configuration avant toute autre opération Configuration configuration = *(Configuration*) c.data; Serial.println(c.status.getResponseDescription()); Serial.println(c.status.code); printParameters(configuration); configuration. ADDL = 0x0; configuration. ADDH = 0x1; configuration. CHAN = 0x19; configuration. OPTION.fec = FEC_0_OFF; configuration. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; configuration. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; configuration. OPTION.transmissionPower = POWER_17; configuration. OPTION.wirelessWakeupTime = WAKE_UP_1250; configuration. SPED.airDataRate = AIR_DATA_RATE_011_48; configuration. SPED.uartBaudRate = UART_BPS_115200; configuration. SPED.uartParity = MODE_00_8N1; // Définir la configuration modifiée et définie pour ne pas conserver la configuration ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println(rs.getResponseDescription()); Serial.println(rs.code); printParameters(configuration);

Les paramètres sont tous gérés comme constants:

Étape 10: Option de configuration de base

Option de configuration de base
Option de configuration de base

Étape 11: envoyer un message de réception

Nous devons d'abord introduire une méthode simple mais utile pour vérifier si quelque chose est dans le tampon de réception

int disponible();

Il renvoie simplement le nombre d'octets que vous avez dans le flux actuel.

Étape 12: Mode de transmission normal

Mode de transmission normal
Mode de transmission normal

Le mode de transmission Normal/Transparent est utilisé pour envoyer des messages à tous les appareils avec la même adresse et le même canal.

Il y a beaucoup de méthode pour envoyer/recevoir un message, nous allons expliquer en détail:

ResponseStatus sendMessage(const String message);

ResponseContainer receiveMessage();

La première méthode est sendMessage et est utilisée pour envoyer une chaîne à un appareil en mode normal.

ResponseStatus rs = e32ttl.sendMessage("Prova");Serial.println(rs.getResponseDescription());

L'autre appareil fait simplement sur la boucle

if (e32ttl.available() > 1){ResponseContainer rs = e32ttl.receiveMessage(); Message de chaîne = rs.data; // Récupérez d'abord les données Serial.println(rs.status.getResponseDescription()); Serial.println(message); }

Étape 13: Gérer la structure

Si vous souhaitez envoyer une structure complexe, vous pouvez utiliser cette méthode

ResponseStatus sendMessage(const void *message, const uint8_t size);ResponseStructContainer receiveMessage(const uint8_t size);

Il est utilisé pour envoyer des structures, par exemple:

struct Messaggione {char type[5]; message char[8]; bool mitico; }; struct Messaggione messaggione = {"TEMP", "Peple", true}; ResponseStatus rs = e32ttl.sendMessage(&messaggione, sizeof(Messaggione)); Serial.println(rs.getResponseDescription());

et de l'autre côté tu peux recevoir le message donc

ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione));struct Messaggione messaggione = *(Messaggione*) rsc.data; Serial.println(messaggione.message); Serial.println(messaggione.mitico);

Lire la structure partielle

Si vous souhaitez lire la première partie du message pour gérer plus de type de structure, vous pouvez utiliser cette méthode.

ResponseContainer receiveInitialMessage (taille const uint8_t);

Je le crée pour recevoir une chaîne de type ou autre pour identifier la structure à charger.

struct Messaggione { // Structure partielle sans typechar message[8]; bool mitico; }; type de caractère[5]; // première partie de la structure ResponseContainer rs = e32ttl.receiveInitialMessage(sizeof(type)); // Mettre la chaîne dans un tableau de caractères (pas nécessaire) memcpy (type, rs.data.c_str(), sizeof(type)); Serial.println("READ TYPE: "); Serial.println(rs.status.getResponseDescription()); Serial.println(type); // Lire le reste de la structure ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione)); struct Messaggione messaggione = *(Messaggione*) rsc.data;

Étape 14: Mode fixe au lieu du mode normal

De la même manière je crée un ensemble de méthode à utiliser avec une transmission fixe

Transmission fixe

Vous devez uniquement modifier la méthode d'envoi, car l'appareil de destination ne reçoit pas le préambule avec l'adresse et le canal quando settato il fixed mode.

Donc, pour le message String, vous avez

ResponseStatus sendFixedMessage(octet ADDL, octet ADDH, octet CHAN, message de chaîne const);ResponseStatus sendBroadcastFixedMessage(octet CHAN, message de chaîne const);

et pour la structure tu as

ResponseStatus sendFixedMessage (octet ADDL, octet ADDH, octet CHAN, const void *message, const uint8_t taille);

Voici un exemple simple

ResponseStatus rs = e32ttl.sendFixedMessage(0, 0, 0x17, &messaggione, sizeof(Messaggione));// ResponseStatus rs = e32ttl.sendFixedMessage(0, 0, 0x17, "Ciao");

La transmission fixe a plus de scénarios

Si vous envoyez à un appareil spécifique (deuxièmes scénarios Transmission fixe) vous devez ajouter ADDL, ADDH et CHAN pour l'identifier directement.

ResponseStatus rs = e32ttl.sendFixedMessage(2, 2, 0x17, "Message à un appareil");

Si vous souhaitez envoyer un message à tous les appareils d'un canal spécifié, vous pouvez utiliser cette méthode.

ResponseStatus rs = e32ttl.sendBroadcastFixedMessage(0x17, "Message à un appareil d'un canal");

Si vous souhaitez recevoir tous les messages diffusés sur le réseau, vous devez définir votre ADDH et ADDL avec BROADCAST_ADDRESS.

ResponseStructContainer c;c = e32ttl100.getConfiguration(); // Il est important d'obtenir le pointeur de configuration avant toute autre opération Configuration configuration = *(Configuration*) c.data; Serial.println(c.status.getResponseDescription()); Serial.println(c.status.code); printParameters(configuration); configuration. ADDL = BROADCAST_ADDRESS; configuration. ADDH = BROADCAST_ADDRESS; // Définir la configuration modifiée et définie pour ne pas conserver la configuration ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println(rs.getResponseDescription()); Serial.println(rs.code); printParameters(configuration);

Étape 15: Merci

Maintenant, vous avez toutes les informations pour faire votre travail, mais je pense qu'il est important de montrer des exemples réalistes pour mieux comprendre toutes les possibilités.

  1. Appareil LoRa E32 pour Arduino, esp32 ou esp8266: paramètres et utilisation de base
  2. Périphérique LoRa E32 pour Arduino, esp32 ou esp8266: bibliothèque
  3. Périphérique LoRa E32 pour Arduino, esp32 ou esp8266: configuration
  4. Périphérique LoRa E32 pour Arduino, esp32 ou esp8266: transmission fixe
  5. Appareil LoRa E32 pour Arduino, esp32 ou esp8266: économie d'énergie et envoi de données structurées

Conseillé: