Índice:

Comunicação sem fio LoRa de 3 km a 8 km com dispositivo E32 (sx1278 / sx1276) de baixo custo para Arduino, Esp8266 ou Esp32: 15 etapas
Comunicação sem fio LoRa de 3 km a 8 km com dispositivo E32 (sx1278 / sx1276) de baixo custo para Arduino, Esp8266 ou Esp32: 15 etapas

Vídeo: Comunicação sem fio LoRa de 3 km a 8 km com dispositivo E32 (sx1278 / sx1276) de baixo custo para Arduino, Esp8266 ou Esp32: 15 etapas

Vídeo: Comunicação sem fio LoRa de 3 km a 8 km com dispositivo E32 (sx1278 / sx1276) de baixo custo para Arduino, Esp8266 ou Esp32: 15 etapas
Vídeo: Módulo LoRa TX e RX - RF Wireless de 433MHz SX1278 - Longo Alcance para Arduino e Esp32 (AULA1) 2024, Julho
Anonim
Comunicação sem fio LoRa de 3 km a 8 km com dispositivo E32 (sx1278 / sx1276) de baixo custo para Arduino, Esp8266 ou Esp32
Comunicação sem fio LoRa de 3 km a 8 km com dispositivo E32 (sx1278 / sx1276) de baixo custo para Arduino, Esp8266 ou Esp32

Eu crio uma biblioteca para gerenciar EBYTE E32 baseada na série Semtech de dispositivo LoRa, dispositivo muito poderoso, simples e barato.

Você pode encontrar a versão de 3Km aqui, a versão de 8Km aqui

Eles podem trabalhar a uma distância de 3.000m a 8.000m e têm muitos recursos e parâmetros. Então, eu crio esta biblioteca para simplificar o uso.

É uma solução para recuperar dados de sensores metropolitanos ou para controlar drones.

Suprimentos

Arduino UNO

Wemos D1 mini

LoRa E32 TTL 100 versão de 3 km

Versão LoRa E32 TTL 1W 8Km

Etapa 1: Biblioteca

Biblioteca
Biblioteca

Você pode encontrar minha biblioteca aqui.

Baixar.

Clique no botão DOWNLOADS no canto superior direito, renomeie a pasta descompactada LoRa_E32.

Verifique se a pasta LoRa_E32 contém LoRa_E32.cpp e LoRa_E32.h.

Coloque a pasta de biblioteca LoRa_E32 em sua pasta / libraries /. Você pode precisar criar a subpasta de bibliotecas se for sua primeira biblioteca.

Reinicie o IDE.

Etapa 2: Pinagem

Pinagem
Pinagem
Pinagem
Pinagem
Pinagem
Pinagem

Como você pode ver, você pode definir vários modos por meio dos pinos M0 e M1.

Existem alguns pinos que podem ser usados de forma estática, mas se você conectá-lo ao microcontrolador e configurá-los na biblioteca você ganha em desempenho e pode controlar todos os modos via software, mas explicaremos melhor a seguir.

Etapa 3: Pin AUX

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

Como eu já disse, não é importante conectar todos os pinos na saída do microcontrolador, você pode colocar os pinos M0 e M1 em HIGH ou LOW para obter a configuração desejada, e se você não conectar AUX a biblioteca definir um atraso razoável para ter certeza que a operação foi concluída.

Pino AUX

Ao transmitir dados, pode ser usado para despertar o MCU externo e retornar ALTO no término da transferência de dados.

Ao receber AUX indo para BAIXO e retornando ALTO quando o buffer está vazio.

Também é usado para autoverificação para restaurar a operação normal (na inicialização e modo de suspensão / programa).

Etapa 4: Esquema totalmente conectado Esp8266

Esquema Totalmente Conectado Esp8266
Esquema Totalmente Conectado Esp8266
Esquema Totalmente Conectado Esp8266
Esquema Totalmente Conectado Esp8266

O esquema de conexão esp8266 é mais simples porque funciona na mesma voltagem das comunicações lógicas (3.3v).

É importante adicionar um resistor pull-up (4, 7Kohm) para obter uma boa estabilidade.

Etapa 5: Esquema Arduino totalmente conectado

Esquema Arduino totalmente conectado
Esquema Arduino totalmente conectado
Esquema Arduino totalmente conectado
Esquema Arduino totalmente conectado

A tensão de trabalho do Arduino é 5v, então precisamos adicionar um divisor de tensão no pino RX M0 e M1 do módulo LoRa para evitar danos, você pode obter mais informações aqui Divisor de tensão: calculadora e aplicativo.

Você pode usar um resistor de 2Kohm para GND e 1Kohm de sinal do que colocar juntos em RX.

Etapa 6: Biblioteca: Construtor

Fiz um conjunto de construtores bastante numerosos, porque podemos ter mais opções e situações para gerir.

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);

O primeiro conjunto de construtores é criado para delegar o gerenciamento de pinos seriais e outros à biblioteca.

rxPin e txPin é o pino para conectar ao UART e eles são obrigatórios.

auxPin é um pino que verifica o estado de operação, transmissão e recebimento (explicaremos melhor a seguir), esse pino não é obrigatório, se você não configurá-lo, aplico um retardo para permitir que a operação se complete (com latência).

m0pin e m1Pin são os pinos para mudar o MODO de operação (veja a tabela acima), eu acho que esses pinos em “produção” vão se conectar diretamente ALTO ou BAIXO, mas para teste eles são úteis para serem gerenciados pela biblioteca.

bpsRate é a taxa de transmissão de SoftwareSerial normalmente é 9600 (a única taxa de transmissão no modo programmin / sleep)

Um exemplo simples é

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

Podemos usar diretamente um SoftwareSerial com outro construtor

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);

O exemplo superior com este construtor pode ser feito assim.

#include #include "LoRa_E32.h"

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

LoRa_E32 e32ttl100 (& mySerial);

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

O último conjunto de construtor é permitir o uso de HardwareSerial em vez 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);

Etapa 7: começar

O comando begin é usado para inicializar serial e pinos no modo de entrada e saída.

void begin ();

em execução está

// Iniciar todos os pinos e UART

e32ttl100.begin ();

Etapa 8: Configuração e Método de Informação

Existe um conjunto de métodos para gerenciar a configuração e obter informações do dispositivo.

ResponseStructContainer getConfiguration ();

ResponseStatus setConfiguration (configuração de configuração, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

ResponseStructContainer getModuleInformation ();

void printParameters (configuração da configuração da estrutura);

ResponseStatus resetModule ();

Etapa 9: recipiente de resposta

Para simplificar o gerenciamento de resposta eu crio um conjunto de container, para mim muito útil para gerenciar erros e retornar dados genéricos.

ResponseStatus

Este é um contêiner de status e tem 2 pontos de entrada simples, com isso você pode obter o código de status e a descrição do código de status

Serial.println (c.getResponseDescription ()); // Descrição do código

Serial.println (c.code); // 1 se tiver sucesso

O código é

SUCESSO = 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

ResponseContainer

Este contêiner é criado para gerenciar a resposta da String e tem 2 pontos de entrada.

dados com a string retornada da mensagem e status uma instância de RepsonseStatus.

ResponseContainer rs = e32ttl.receiveMessage ();

String message = rs.data;

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

Serial.println (mensagem);

ResponseStructContainer

Este é o contêiner mais “complexo”, eu o uso para gerenciar a estrutura. Ele tem o mesmo ponto de entrada do ResponseContainer, mas os dados são um ponteiro vazio para gerenciar a estrutura complexa.

ResponseStructContainer c;

c = e32ttl100.getConfiguration (); // É importante obter o ponteiro de configuração antes de todas as outras operações

Configuração de configuração = * (Configuração *) c.data;

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

Serial.println (c.status.code);

getConfiguration e setConfiguration

O primeiro método é getConfiguration, você pode usá-lo para recuperar todos os dados armazenados no dispositivo.

ResponseStructContainer getConfiguration ();

Aqui está um exemplo de uso.

ResponseStructContainer c;

c = e32ttl100.getConfiguration (); // É importante obter o ponteiro de configuração antes de todas as outras operações

Configuração de configuração = * (Configuração *) c.data;

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

Serial.println (c.status.code);

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

Estrutura de configuração tem todos os dados de configurações, e eu adiciono uma série de funções para obter todas as descrições de dados individuais.

configuração. ADDL = 0x0; // Primeira parte de addressconfiguration. ADDH = 0x1; // Segunda parte da configuração do endereço. CHAN = 0x19; // Configuração do canal. OPTION.fec = FEC_0_OFF; // Configuração da chave de correção de erro de encaminhamento. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Configuração do modo de transmissão. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; // Configuração de gerenciamento de pull-up. OPTION.transmissionPower = POWER_17; // configuração da potência de transmissão dBm. OPTION.wirelessWakeupTime = WAKE_UP_1250; // Tempo de espera para configuração de ativação. SPED.airDataRate = AIR_DATA_RATE_011_48; // Air data rate configuration. SPED.uartBaudRate = UART_BPS_115200; // Configuração da taxa de transmissão de comunicação. SPED.uartParity = MODE_00_8N1; // bit de paridade

Você tem a função equivalente para todos os atributos para obter todas as descrições:

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

Da mesma forma, setConfiguration deseja uma estrutura de configuração, então acho que a melhor maneira de gerenciar a configuração é recuperar a atual, aplicar a única alteração necessária e defini-la novamente.

ResponseStatus setConfiguration (configuração de configuração, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

configuração é a estrutura anterior mostrada, saveType permite que você escolha se a mudança se torna permanente apenas para a sessão atual.

ResponseStructContainer c; c = e32ttl100.getConfiguration (); // É importante obter o ponteiro de configuração antes de todas as outras operações Configuration configuration = * (Configuration *) c.data; Serial.println (c.status.getResponseDescription ()); Serial.println (c.status.code); printParameters (configuração); configuração. ADDL = 0x0; configuração. ADDH = 0x1; configuração. CHAN = 0x19; configuração. OPÇÃO.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; configuração. SPED.uartBaudRate = UART_BPS_115200; configuração. SPED.uartParity = MODE_00_8N1; // Definir configuração alterada e definir para não manter a configuração ResponseStatus rs = e32ttl100.setConfiguration (configuração, WRITE_CFG_PWR_DWN_LOSE); Serial.println (rs.getResponseDescription ()); Serial.println (rs.code); printParameters (configuração);

Os parâmetros são todos gerenciados como constantes:

Etapa 10: opção de configuração básica

Opção de configuração básica
Opção de configuração básica

Etapa 11: enviar receber mensagem

Primeiro, devemos apresentar um método simples, mas útil para verificar se algo está no buffer de recebimento

disponível int ();

É simplesmente retornar quantos bytes você tem no stream atual.

Etapa 12: Modo de transmissão normal

Modo de transmissão normal
Modo de transmissão normal

O modo de transmissão normal / transparente é usado para enviar mensagens a todos os dispositivos com o mesmo endereço e canal.

Existem vários métodos para enviar / receber mensagens, vamos explicar em detalhes:

ResponseStatus sendMessage (const String mensagem);

ResponseContainer receiveMessage ();

O primeiro método é sendMessage e é usado para enviar uma String a um dispositivo no modo normal.

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

O outro dispositivo simplesmente faz no loop

if (e32ttl.available ()> 1) {ResponseContainer rs = e32ttl.receiveMessage (); String message = rs.data; // Obtenha primeiro os dados Serial.println (rs.status.getResponseDescription ()); Serial.println (mensagem); }

Etapa 13: Gerenciar Estrutura

Se você quiser enviar uma estrutura complexa, você pode usar este método

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

É usado para enviar estrutura, por exemplo:

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

e do outro lado você pode receber a mensagem para

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

Leia a estrutura parcial

Se você quiser ler a primeira parte da mensagem para gerenciar mais tipos de estrutura, pode usar este método.

ResponseContainer receiveInitialMessage (const uint8_t size);

Eu crio para receber um string com tipo ou outro para identificar a estrutura a carregar.

struct Messaggione {// estrutura parcial sem mensagem de tipo de letra [8]; bool mitico; }; tipo char [5]; // primeira parte da estrutura ResponseContainer rs = e32ttl.receiveInitialMessage (sizeof (type)); // Coloca string em um array de char (não necessário) memcpy (type, rs.data.c_str (), sizeof (type)); Serial.println ("TIPO DE LEITURA:"); Serial.println (rs.status.getResponseDescription ()); Serial.println (tipo); // Lê o resto da estrutura ResponseStructContainer rsc = e32ttl.receiveMessage (sizeof (Messaggione)); struct Messaggione messaggione = * (Messaggione *) rsc.data;

Etapa 14: modo fixo em vez do modo normal

Da mesma maneira, crio um conjunto de métodos para usar com transmissão fixa

Transmissão fixa

Você precisa alterar apenas o método de envio, pois o dispositivo de destino não recebe o preâmbulo com Endereço e Canal quando define o modo fixo.

Então, para mensagem String você tem

ResponseStatus sendFixedMessage (byte ADDL, byte ADDH, byte CHAN, const String mensagem); ResponseStatus sendBroadcastFixedMessage (byte CHAN, const String mensagem);

e para estrutura você tem

ResponseStatus sendFixedMessage (byte ADDL, byte ADDH, byte CHAN, const void * mensagem, const uint8_t size); ResponseStatus sendBroadcastFixedMessage (byte CHAN, const void * mensagem, const uint8_t tamanho);

Aqui está um exemplo simples

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

A transmissão fixa tem mais cenários

Se você enviar para um dispositivo específico (segundos cenários de transmissão fixa), você deve adicionar ADDL, ADDH e CHAN para identificá-lo diretamente.

ResponseStatus rs = e32ttl.sendFixedMessage (2, 2, 0x17, "Mensagem para um dispositivo");

Se você quiser enviar uma mensagem para todos os dispositivos em um canal especificado, você pode usar este método.

ResponseStatus rs = e32ttl.sendBroadcastFixedMessage (0x17, "Mensagem para dispositivos de um canal");

Se você deseja receber todas as mensagens de transmissão na rede, você deve definir seu ADDH e ADDL com BROADCAST_ADDRESS.

ResponseStructContainer c; c = e32ttl100.getConfiguration (); // É importante obter o ponteiro de configuração antes de todas as outras operações Configuration configuration = * (Configuration *) c.data; Serial.println (c.status.getResponseDescription ()); Serial.println (c.status.code); printParameters (configuração); configuração. ADDL = BROADCAST_ADDRESS; configuração. ADDH = BROADCAST_ADDRESS; // Definir configuração alterada e definir para não manter a configuração ResponseStatus rs = e32ttl100.setConfiguration (configuração, WRITE_CFG_PWR_DWN_LOSE); Serial.println (rs.getResponseDescription ()); Serial.println (rs.code); printParameters (configuração);

Etapa 15: Obrigado

Agora você tem todas as informações para fazer seu trabalho, mas acho importante mostrar alguns exemplos realistas para entender e melhor todas as possibilidades.

  1. Dispositivo LoRa E32 para Arduino, esp32 ou esp8266: configurações e uso básico
  2. Dispositivo LoRa E32 para Arduino, esp32 ou esp8266: biblioteca
  3. Dispositivo LoRa E32 para Arduino, esp32 ou esp8266: configuração
  4. Dispositivo LoRa E32 para Arduino, esp32 ou esp8266: transmissão fixa
  5. Dispositivo LoRa E32 para Arduino, esp32 ou esp8266: economia de energia e envio de dados estruturados

Recomendado: