Tabla de contenido:

LoRa 3Km a 8Km Comunicación Inalámbrica con Dispositivo de Bajo Costo E32 (sx1278 / sx1276) para Arduino, Esp8266 o Esp32: 15 Pasos
LoRa 3Km a 8Km Comunicación Inalámbrica con Dispositivo de Bajo Costo E32 (sx1278 / sx1276) para Arduino, Esp8266 o Esp32: 15 Pasos

Video: LoRa 3Km a 8Km Comunicación Inalámbrica con Dispositivo de Bajo Costo E32 (sx1278 / sx1276) para Arduino, Esp8266 o Esp32: 15 Pasos

Video: LoRa 3Km a 8Km Comunicación Inalámbrica con Dispositivo de Bajo Costo E32 (sx1278 / sx1276) para Arduino, Esp8266 o Esp32: 15 Pasos
Video: Comunicación Inalámbrica de 7 a 8 kilómetros😱con LoRa RYLR998 y ESP32-(Arduino) 2024, Noviembre
Anonim
LoRa 3Km a 8Km Comunicación Inalámbrica con Dispositivo de Bajo Costo E32 (sx1278 / sx1276) para Arduino, Esp8266 o Esp32
LoRa 3Km a 8Km Comunicación Inalámbrica con Dispositivo de Bajo Costo E32 (sx1278 / sx1276) para Arduino, Esp8266 o Esp32

Creo una biblioteca para administrar EBYTE E32 basada en la serie Semtech de dispositivo LoRa, dispositivo muy potente, simple y económico.

Puede encontrar la versión de 3Km aquí, la versión de 8Km aquí

Pueden trabajar a una distancia de 3000 ma 8000 my tienen muchas características y parámetros. Entonces creo esta biblioteca para simplificar el uso.

Es una solución para recuperar datos de sensores metropolitanos o para controlar drones.

Suministros

Arduino UNO

Wemos D1 mini

Versión LoRa E32 TTL 100 3Km

Versión LoRa E32 TTL 1W 8Km

Paso 1: biblioteca

Biblioteca
Biblioteca

Puedes encontrar mi biblioteca aquí.

Descargar.

Haga clic en el botón DESCARGAS en la esquina superior derecha, cambie el nombre de la carpeta sin comprimir LoRa_E32.

Verifique que la carpeta LoRa_E32 contenga LoRa_E32.cpp y LoRa_E32.h.

Coloque la carpeta de la biblioteca LoRa_E32 en su carpeta / libraries /. Es posible que deba crear la subcarpeta de bibliotecas si es su primera biblioteca.

Reinicie el IDE.

Paso 2: Pinout

Pinout
Pinout
Pinout
Pinout
Pinout
Pinout

Como puede ver, puede configurar varios modos a través de los pines M0 y M1.

Hay algunos pines que se pueden usar de forma estática, pero si lo conectas al microcontrolador y los configuras en la librería ganas en rendimiento y puedes controlar todos los modos vía software, pero te lo vamos a explicar mejor a continuación.

Paso 3: Pin AUX

Pin AUX
Pin AUX
Pin AUX
Pin AUX
Pin AUX
Pin AUX

Como ya digo, no es importante conectar todos los pines a la salida del microcontrolador, puede poner los pines M0 y M1 en ALTO o BAJO para obtener la configuración deseada, y si no conecta AUX, la biblioteca establece un retraso razonable para estar seguro que la operación está completa.

Pin AUX

Cuando se transmiten datos, se puede utilizar para activar la MCU externa y devolver ALTO al finalizar la transferencia de datos.

Cuando recibe AUX, va a BAJO y vuelve a ALTO cuando el búfer está vacío.

También se utiliza para la autocomprobación para restablecer el funcionamiento normal (en el modo de encendido y de suspensión / programa).

Paso 4: Esquema completamente conectado Esp8266

Esquema completamente conectado Esp8266
Esquema completamente conectado Esp8266
Esquema completamente conectado Esp8266
Esquema completamente conectado Esp8266

El esquema de conexión esp8266 es más simple porque funciona al mismo voltaje de las comunicaciones lógicas (3.3v).

Es importante agregar una resistencia pull-up (4, 7Kohm) para obtener una buena estabilidad.

Paso 5: Esquema Arduino completamente conectado

Esquema Arduino completamente conectado
Esquema Arduino completamente conectado
Esquema Arduino completamente conectado
Esquema Arduino completamente conectado

El voltaje de trabajo de Arduino es de 5v, por lo que necesitamos agregar un divisor de voltaje en el pin RX M0 y M1 del módulo LoRa para evitar daños, puede obtener más información aquí Divisor de voltaje: calculadora y aplicación.

Puede usar una resistencia de 2Kohm a GND y 1Kohm de la señal que armar en RX.

Paso 6: Biblioteca: Constructor

Hice un conjunto de constructores bastante numerosos, porque podemos tener más opciones y situaciones que gestionar.

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

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

El primer conjunto de constructores se crea para delegar la administración de Serial y otros pines a la biblioteca.

rxPin y txPin es el pin para conectarse a UART y son obligatorios.

auxPin es un pin que verifica el estado de operación, transmisión y recepción (lo explicaremos mejor a continuación), ese pin no es obligatorio, si no lo configura, aplico un retraso para permitir que la operación se complete por sí sola (con latencia).

m0pin y m1Pin son los pines para cambiar el MODO de operación (vea la tabla superior), creo que estos pines en "producción" se van a conectar directamente HIGH o LOW, pero para la prueba son útiles para ser administrados por la biblioteca.

bpsRate es el boudrate de SoftwareSerial que normalmente es 9600 (la única velocidad en baudios en modo programmin / sleep)

Un ejemplo simple es

#include "LoRa_E32.h" LoRa_E32 e32ttl100 (2, 3); // RX, TX // LoRa_E32 e32ttl100 (2, 3, 5, 6, 7); // RX, TX

Podemos usar directamente un SoftwareSerial con otro constructor

LoRa_E32 (HardwareSerial * serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (HardwareSerial * serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (HardwareSerial * serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

El ejemplo superior con este constructor puede ser así.

#include #include "LoRa_E32.h"

SoftwareSerial mySerial (2, 3); // RX, TX

LoRa_E32 e32ttl100 (& mySerial);

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

El último conjunto de constructores es permitir el uso de HardwareSerial en lugar de SoftwareSerial.

LoRa_E32 (SoftwareSerial * serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (SoftwareSerial * serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (SoftwareSerial * serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Paso 7: Comience

El comando begin se usa para iniciar Serial y pines en modo de entrada y salida.

comienzo vacío ();

en ejecución es

// Arranque todos los pines y UART

e32ttl100.begin ();

Paso 8: Método de configuración e información

Existe un conjunto de métodos para administrar la configuración y obtener información del dispositivo.

ResponseStructContainer getConfiguration ();

ResponseStatus setConfiguration (Configuración de configuración, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

ResponseStructContainer getModuleInformation ();

printParameters void (configuración de configuración de estructura);

ResponseStatus resetModule ();

Paso 9: Contenedor de respuesta

Para simplificar la gestión de la respuesta creo un conjunto de contenedores, para mí muy útil para gestionar errores y devolver datos genéricos.

ResponseStatus

Este es un contenedor de estado y tiene 2 puntos de entrada simples, con esto puede obtener el código de estado y la descripción del código de estado.

Serial.println (c.getResponseDescription ()); // Descripción del código

Serial.println (c.code); // 1 si tiene éxito

El código es

ÉXITO = 1, ERR_UNKNOWN, ERR_NOT_SUPPORT, ERR_NOT_IMPLEMENT, ERR_NOT_INITIAL, ERR_INVALID_PARAM, ERR_DATA_SIZE_NOT_MATCH, ERR_BUF_TOO_SMALL, ERR_TIMEOUT, ERR_HARDWARE, ERR_HEAD_NOT_RECOGNIZED

Contenedor de respuesta

Este contenedor se crea para administrar la respuesta de cadena y tiene 2 puntos de entrada.

datos con la cadena devuelta del mensaje y el estado de una instancia de RepsonseStatus.

ResponseContainer rs = e32ttl.receiveMessage ();

Mensaje de cadena = rs.data;

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

Serial.println (mensaje);

ResponseStructContainer

Este es el contenedor más "complejo", lo uso para administrar la estructura. Tiene el mismo punto de entrada de ResponseContainer, pero los datos son un puntero vacío para administrar la estructura compleja.

ResponseStructContainer c;

c = e32ttl100.getConfiguration (); // Es importante obtener el puntero de configuración antes de cualquier otra operación

Configuración configuración = * (Configuración *) c.data;

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

Serial.println (c.status.code);

getConfiguration y setConfiguration

El primer método es getConfiguration, puede usarlo para recuperar todos los datos almacenados en el dispositivo.

ResponseStructContainer getConfiguration ();

Aquí un ejemplo de uso.

ResponseStructContainer c;

c = e32ttl100.getConfiguration (); // Es importante obtener el puntero de configuración antes de cualquier otra operación

Configuración configuración = * (Configuración *) c.data;

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

Serial.println (c.status.code);

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

La estructura de la configuración tiene todos los datos de la configuración y agrego una serie de funciones para obtener toda la descripción de los datos individuales.

configuración. ADDL = 0x0; // Primera parte de la configuración de direcciones. ADDH = 0x1; // Segunda parte de la configuración de la dirección. CHAN = 0x19; // Configuración del canal. OPTION.fec = FEC_0_OFF; // Configuración del conmutador de corrección de errores hacia adelante. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Configuración del modo de transmisión. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; // Configuración de gestión de pull-up. OPTION.transmissionPower = POWER_17; // Configuración de potencia de transmisión en dBm. OPTION.wirelessWakeupTime = WAKE_UP_1250; // Tiempo de espera para la configuración de activación. SPED.airDataRate = AIR_DATA_RATE_011_48; // Configuración de la velocidad de datos del aire. SPED.uartBaudRate = UART_BPS_115200; // Configuración de la velocidad de comunicación en baudios. SPED.uartParity = MODE_00_8N1; // Bit de paridad

Tiene la función equivalente para todos los atributos para obtener toda la descripción:

Serial.print (F ("Chan:")); Serial.print (configuración. 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 misma manera, setConfiguration quiere una estructura de configuración, por lo que creo que la mejor manera de administrar la configuración es recuperar la actual, aplicar el único cambio que necesita y configurarlo nuevamente.

ResponseStatus setConfiguration (Configuración de configuración, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

La configuración es la estructura que se muestra previamente, saveType le permite elegir si el cambio se vuelve permanente sólo para la sesión actual.

ResponseStructContainer c; c = e32ttl100.getConfiguration (); // Es importante obtener el puntero de configuración antes de todas las demás operaciones Configuración de configuración = * (Configuración *) c.data; Serial.println (c.status.getResponseDescription ()); Serial.println (c.status.code); printParameters (configuración); configuración. ADDL = 0x0; configuración. ADDH = 0x1; configuración. 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; // Se cambió la configuración y se estableció para que no mantenga la configuración ResponseStatus rs = e32ttl100.setConfiguration (configuración, WRITE_CFG_PWR_DWN_LOSE); Serial.println (rs.getResponseDescription ()); Serial.println (código rs); printParameters (configuración);

Todos los parámetros se gestionan como constantes:

Paso 10: Opción de configuración básica

Opción de configuración básica
Opción de configuración básica

Paso 11: Enviar mensaje de recepción

Primero debemos introducir un método simple pero útil para verificar si hay algo en el búfer de recepción

int disponible ();

Simplemente devuelve la cantidad de bytes que tiene en la transmisión actual.

Paso 12: Modo de transmisión normal

Modo de transmisión normal
Modo de transmisión normal

El modo de transmisión normal / transparente se utiliza para enviar mensajes a todos los dispositivos con la misma dirección y canal.

Hay muchos métodos para enviar / recibir mensajes, los explicaremos en detalle:

ResponseStatus sendMessage (mensaje de cadena constante);

ResponseContainer receiveMessage ();

El primer método es sendMessage y se utiliza para enviar una cadena a un dispositivo en modo Normal.

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

El otro dispositivo simplemente hazlo en el bucle

if (e32ttl.available ()> 1) {ResponseContainer rs = e32ttl.receiveMessage (); Mensaje de cadena = rs.data; // Primero obtenga los datos Serial.println (rs.status.getResponseDescription ()); Serial.println (mensaje); }

Paso 13: administrar la estructura

Si desea enviar una estructura compleja, puede utilizar este método.

ResponseStatus sendMessage (const void * mensaje, const uint8_t tamaño); ResponseStructContainer receiveMessage (const uint8_t tamaño);

Se usa para enviar estructuras, por ejemplo:

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

y del otro lado puedes recibir el mensaje así

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

Leer estructura parcial

Si desea leer la primera parte del mensaje para administrar más tipos de estructuras, puede usar este método.

ResponseContainer receiveInitialMessage (const uint8_t tamaño);

Lo creo para recibir una cadena con tipo u otro para identificar la estructura a cargar.

struct Messaggione {// Estructura parcial sin mensaje typechar [8]; bool mitico; }; tipo char [5]; // primera parte de la estructura ResponseContainer rs = e32ttl.receiveInitialMessage (sizeof (type)); // Ponga una cadena en una matriz de caracteres (no es necesario) memcpy (type, rs.data.c_str (), sizeof (type)); Serial.println ("LEER TIPO:"); Serial.println (rs.status.getResponseDescription ()); Serial.println (tipo); // Leer el resto de la estructura ResponseStructContainer rsc = e32ttl.receiveMessage (sizeof (Messaggione)); struct Messaggione messaggione = * (Messaggione *) rsc.data;

Paso 14: modo fijo en lugar del modo normal

De la misma manera creo un conjunto de métodos para usar con transmisión fija

Transmisión fija

Necesita cambiar solo el método de envío, porque el dispositivo de destino no recibe el preámbulo con la dirección y el canal en el modo fijo.

Entonces, para el mensaje de cadena, tienes

ResponseStatus sendFixedMessage (byte ADDL, byte ADDH, byte CHAN, mensaje de cadena const); ResponseStatus sendBroadcastFixedMessage (byte CHAN, mensaje de cadena const);

y por estructura tienes

ResponseStatus sendFixedMessage (byte ADDL, byte ADDH, byte CHAN, const void * mensaje, const uint8_t tamaño); ResponseStatus sendBroadcastFixedMessage (byte CHAN, const void * mensaje, const uint8_t tamaño);

Aqui un simple ejemplo

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

La transmisión fija tiene más escenarios

Si envías a un dispositivo específico (segundos escenarios de transmisión fija) debes agregar ADDL, ADDH y CHAN para identificarlo directamente.

ResponseStatus rs = e32ttl.sendFixedMessage (2, 2, 0x17, "Mensaje a un dispositivo");

Si desea enviar un mensaje a todos los dispositivos en un canal específico, puede utilizar este método.

ResponseStatus rs = e32ttl.sendBroadcastFixedMessage (0x17, "Mensaje a un dispositivo de un canal");

Si desea recibir todos los mensajes de difusión en la red, debe configurar su ADDH y ADDL con BROADCAST_ADDRESS.

ResponseStructContainer c; c = e32ttl100.getConfiguration (); // Es importante obtener el puntero de configuración antes de todas las demás operaciones Configuración de configuración = * (Configuración *) c.data; Serial.println (c.status.getResponseDescription ()); Serial.println (c.status.code); printParameters (configuración); configuration. ADDL = BROADCAST_ADDRESS; configuration. ADDH = BROADCAST_ADDRESS; // Establecer la configuración cambiada y establecida para que no mantenga la configuración ResponseStatus rs = e32ttl100.setConfiguration (configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println (rs.getResponseDescription ()); Serial.println (código rs); printParameters (configuración);

Paso 15: Gracias

Ahora tienes toda la información para hacer tu trabajo, pero creo que es importante mostrar algunos ejemplos realistas para entender mejor todas las posibilidades.

  1. Dispositivo LoRa E32 para Arduino, esp32 o esp8266: configuración y uso básico
  2. Dispositivo LoRa E32 para Arduino, esp32 o esp8266: biblioteca
  3. Dispositivo LoRa E32 para Arduino, esp32 o esp8266: configuración
  4. Dispositivo LoRa E32 para Arduino, esp32 o esp8266: transmisión fija
  5. Dispositivo LoRa E32 para Arduino, esp32 o esp8266: ahorro de energía y envío de datos estructurados

Recomendado: