Recents in Beach


Receba o meu conteúdo GRATUITAMENTE


Super WiFi Longa Distância do ESP32 LoRa com Arduino IDE



Bastante útil por depurar e testar o seu programa, em função do display que já o acompanha, hoje vamos tratar novamente do ESP32 LoRa, desta vez em um projeto utilizando o sensor BME280. Vocês já sabem que gosto muito deste chip, inclusive pela possibilidade de seu uso em campo. Vamos, então, enviar solicitações utilizando LoRa, executar a leitura da temperatura, pressão e umidade utilizando o sensor BME280, além de enviar resposta à solicitação com os dados lidos.


No nosso projeto, o Master envia uma solicitação ao Slave. O Slave utilza o sensor BME280 para fazer a leitura dos dados, sendo que este mesmo Slave envia para o Master os dados lidos. O Master, então, calcula o tempo da operação e mostra os dados. Tudo isso, faço usando o radio LoRa, que vai longe, como comprovado em um teste que fizemos que chegamos ao alcance de 6,5 km.


  Onde encontrar este ESP32 LoRa: https://bit.ly/2JpAi7u


Comunicação


1 - O Master envia um pacote indicando que deseja receber os dados do Slave
2 - O Slave recebe e verifica este pacote
3 - O Slave envia de volta um pacote com os dados lidos do sensor BME280
4 - O Master recebe, verifica o pacote e exibe os dados


Heltec WiFi LoRa 32 Pinout



BME280

Sensor de temperatura, pressão e umidade.



Montagem



Biblioteca BME280

Na IDE do Arduino vá em Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Procure por BME280 e instale Adafruit BME280 Library



Biblioteca Adafruit Unified Sensor

Na IDE do Arduino vá em Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Procure por adafruit sensor based libraries e instale Adafruit Unified Sensor



Modificar pinagem I2C do WiFi LoRa 32

Preciso contar para vocês que, na primeira vez que compilei o BME280 no ESP32, não deu certo. Então, veja só essa dica: você tem que modificar um .h de dentro do compilador do arduino. Essa é uma questão que não se descobre rapidamente, então quero te explicar aqui o que você deve fazer.
Em C:\Users\<SEU_USUARIO>\Documents\Arduino\hardware\heltec\esp32\variants\wifi_lora_32\pins_arduino.h a Heltec colocou o SAD e o SCL, no pinos 21 e 22, respectivamente. Porém, a lib da Adafruit não aceita esses pinos. Qual a biblioteca aceita: o 4 e o 15. Essa alteração, portanto, é muito importante.

Portanto:
Abra o arquivo:
C:\Users\<SEU_USUARIO>\Documents\Arduino\hardware\heltec\esp32\variants\wifi_lora_32\pins_arduino.h
Altere os pinos SDA para 4, e o pino SCL para 15.




Código fonte

Esse código fonte é o mesmo que utilizei no vídeo: ESP32 LoRa comArduino IDE Send e Receive TX RX. Eu apenas o modifiquei para o BME280.


LoRaSendReceiveBME280.ino

De início, vamos incluir as bibliotecas e definir os destinos dos GPIOs, além da frequência do rádio. Ainda, vamos criar constantes para informar ao Slave sobre os trabalhos com os dados, bem como o retorno destes para o Master. Estruturamos ainda os dados do sensor e apontamos a variável para controlar o display.

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

//Deixe esta linha descomentada para compilar o Master
//Comente ou remova para compilar o Slave
#define MASTER

#define RST 14  // GPIO14 RESET
#define DI00 26 // GPIO26 IRQ(Interrupt Request)

#define BAND 433E6 //Frequência do radio - exemplo : 433E6, 868E6, 915E6

//Constante para informar ao Slave que queremos os dados
const String GETDATA = "getdata";
//Constante que o Slave retorna junto com os dados para o Master
const String SETDATA = "setdata=";

//Estrutura com os dados do sensor
typedef struct {
  double temperature;
  double pressure;
  double humidity;
}Data;

//Variável para controlar o display
SSD1306 display(0x3c, SDA, SCL);



LoRaSendReceiveBME280.ino – setupDisplay

Neste primeiro Setup, vamos atuar na configuração do display.

void setupDisplay(){
  //O estado do GPIO16 é utilizado para controlar o display OLED
  pinMode(16, OUTPUT);
  //Reseta as configurações do display OLED
  digitalWrite(16, LOW);
  //Para o OLED permanecer ligado, o GPIO16 deve permanecer HIGH
  //Deve estar em HIGH antes de chamar o display.init() e fazer as demais configurações,
  //não inverta a ordem
  digitalWrite(16, HIGH);

  //Configurações do display
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_16);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
}


LoRaSendReceiveBME280.ino – setupLoRa

Aqui, vamos tratar das configurações iniciais do LoRa.

//Configurações iniciais do LoRa
void setupLoRa(){ 
  //Inicializa a comunicação
  SPI.begin(SCK, MISO, MOSI, SS);
  LoRa.setPins(SS, RST, DI00);

  //Inicializa o LoRa
  if (!LoRa.begin(BAND, true)){
    //Se não conseguiu inicializar, mostra uma mensagem no display
    display.clear();
    display.drawString(0, 0, "Erro ao inicializar o LoRa!");
    display.display();
    while (1);
  }

  //Ativa o crc
  LoRa.enableCrc();
  //Ativa o recebimento de pacotes
  LoRa.receive();
}


Master.ino – setup

Fazemos nesta parte as configurações que envolvem o Master, estas sobre a compilação, o intervalo entre envios, bem como o tempo do último envio. Ainda, chamamos as configurações iniciais do display e do LoRa.

//Compila apenas se MASTER estiver definido no arquivo principal
#ifdef MASTER

//Intervalo entre os envios
#define INTERVAL 500

//Tempo do último envio
long lastSendTime = 0;

void setup(){
  Serial.begin(115200);
  //Chama a configuração inicial do display
  setupDisplay();
  //Chama a configuração inicial do LoRa
  setupLoRa();

  display.clear();
  display.drawString(0, 0, "Master");
  display.display();
}


Master.ino – loop

Neste Loop, definimos o envio do pacote para informar ao Slave o desejo de receber dados e ainda verificamos se existem pacotes a serem recebidos.

void loop(){
  //Se passou o tempo definido em INTERVAL desde o último envio
  if (millis() - lastSendTime > INTERVAL){
    //Marcamos o tempo que ocorreu o último envio
    lastSendTime = millis();
    //Envia o pacote para informar ao Slave que queremos receber os dados
    send();
  }

  //Verificamos se há pacotes para recebermos
  receive();
}


Master.ino – send

Inicializamos o pacote e enviamos o que está contido em “GETDATA”, para posteriormente finalizar e enviar o pacote.

void send(){
  //Inicializa o pacote
  LoRa.beginPacket();
  //Envia o que está contido em "GETDATA"
  LoRa.print(GETDATA);
  //Finaliza e envia o pacote
  LoRa.endPacket();
}


Master.ino – receive

Nesta etapa, verificamos se o pacote tem o tamanho mínimo de caracteres que esperamos e armazenamos uma string. Ainda analisamos se o cabeçalho é o que esperamos, partimos para a leitura dos dados e os exibimos no display.

void receive(){
  //Tentamos ler o pacote
  int packetSize = LoRa.parsePacket();
  
  //Verificamos se o pacote tem o tamanho mínimo de caracteres que esperamos
  if (packetSize > SETDATA.length()){
    String received = "";
    //Armazena os dados do pacote em uma string
    for(int i=0; i<SETDATA.length(); i++){
      received += (char) LoRa.read();
    }

    //Se o cabeçalho é o que esperamos
    if(received.equals(SETDATA)){
      //Fazemos a leitura dos dados
      Data data;
      LoRa.readBytes((uint8_t*)&data, sizeof(data));
      //Mostramos os dados no display
      showData(data);
    }
  }
}


Master.ino – showData

Por fim, mostramos o tempo que o Master levou para criar o pacote, enviar, o Slave receber, fazer a leitura, criar um novo pacote e enviá-lo ao Master, que o recebe e faz a leitura. Este é impresso no display.

void showData(Data data){
  //Tempo que demorou para o Master criar o pacote, enviar o pacote,
  //o Slave receber, fazer a leitura, criar um novo pacote, enviá-lo
  //e o Master receber e ler
  String waiting = String(millis() - lastSendTime);
  //Mostra no display os dados e o tempo que a operação demorou
  display.clear();
  display.drawString(0, 0, String(data.temperature) + " C");
  display.drawString(0, 16, String(data.pressure) + " Pa");
  display.drawString(0, 32, String(data.humidity) + "%");
  display.drawString(0, 48, waiting + " ms");
  display.display();
}

#endif


Slave.ino

Iniciando o código do Slave, compilamos apenas se o Master não estiver definido no arquivo principal.  Incluímos as bibliotecas e apontamos a responsável pela leitura da temperatura, pressão e umidade.

//Compila apenas se MASTER não estiver definido no arquivo principal
#ifndef MASTER

#include <adafruit_sensor.h>
#include <adafruit_bme280.h>


//Responsável pela leitura da temperatura, pressão e umidade
Adafruit_BME280 bme; 


Slave.ino – Setup

No Setup do Slave, chamamos as configurações iniciais do display e do LoRa.

void setup(){
  Serial.begin(115200);
  //Chama a configuração inicial do display
  setupDisplay();
  //Chama a configuração inicial do LoRa
  setupLoRa();

  //0x76 se pino SDO do sensor estiver no GND
  //0x77 se pino SDO do sensor estiver no 3.3v 
  if (!bme.begin(0x76))
  {
    display.clear();
    display.drawString(0, 0, "Sensor não encontrado");
    display.display();
    while(1);
  }

  display.clear();
  display.drawString(0, 0, "Slave esperando...");
  display.display();
}


Slave.ino - Loop

Assim como no Master, nesta parte do Loop do Slave, verificamos se o mesmo tem a quantidade de caracteres esperada e armazenamos os dados em uma String. Ainda, simulamos a leitura dos dados. Criamos o pacote, finalizamos e enviamos. Por fim, exibimos as informações no display.

void loop(){
  //Tenta ler o pacote
  int packetSize = LoRa.parsePacket();

  //Verifica se o pacote possui a quantidade de caracteres que esperamos
  if (packetSize == GETDATA.length())
  {
    String received = "";

    //Armazena os dados do pacote em uma string
    while(LoRa.available())
    {
      received += (char) LoRa.read();
    }

    if(received.equals(GETDATA))
    {
      //Faz a leitura dos dados
      Data data = readData();
      Serial.println("Criando pacote para envio");
      //Cria o pacote para envio
      LoRa.beginPacket();
      LoRa.print(SETDATA);
      LoRa.write((uint8_t*)&data, sizeof(data));
      //Finaliza e envia o pacote
      LoRa.endPacket();
      showSentData(data);
    }
  }
}


Slave.ino – readData

Nesta parte tratamos da função onde se faz a leitura dos dados.

//Função onde se faz a leitura dos dados
Data readData()
{
  Data data;
  data.temperature = bme.readTemperature();
  data.pressure = bme.readPressure();
  data.humidity = bme.readHumidity();
  return data;
}


Slave.ino – showSentData

Enfim, exibidos os dados no display.

void showSentData(Data data)
{
  //Mostra no display
  display.clear();
  display.drawString(0, 0, "Enviou:");
  display.drawString(0, 16,  String(data.temperature) + " C");
  display.drawString(0, 32, String(data.pressure) + " Pa");
  display.drawString(0, 48, String(data.humidity) + "%");
  display.display();
}

#endif


Faça o download dos arquivos:



Onde encontrar este ESP32 LoRa: https://bit.ly/2JpAi7u





Postar um comentário

12 Comentários

  1. Olá Fernando, estou seguindo esta aula, porem está dando este erro ao compilar:

    LoRaSendReceiveBME280:54: error: no matching function for call to 'LoRaClass::begin(double, bool)'

    In file included from C:\Users\Rafael\Google Drive\Indus4\Projetos\Estação Met\Programa ESP\LoRaSendReceiveBME280\LoRaSendReceiveBME280\LoRaSendReceiveBME280.ino:2:0:

    C:\Users\Rafael\Documents\Arduino\libraries\LoRa\src/LoRa.h:31:7: note: candidate: int LoRaClass::begin(long int)

    int begin(long frequency);

    ^

    C:\Users\Rafael\Documents\Arduino\libraries\LoRa\src/LoRa.h:31:7: note: candidate expects 1 argument, 2 provided

    exit status 1
    no matching function for call to 'LoRaClass::begin(double, bool)'

    ResponderExcluir
    Respostas
    1. Olá, boa tarde. Estou com o mesmo problema. Ao compilar apresenta o mesmo erro :


      exit status 1
      no matching function for call to 'LoRaClass::begin(double, bool)'

      Conseguiu resolver? Pode me ajudar com alguma dica? Obrigado

      Excluir
    2. Só tirar o true que ta resolvido

      Excluir
  2. Boa noite… Eu gostaria de fazer um projeto onde usaria um display OLED grande e nele constariam 4 leituras de sensores ultrasonicos diferentes… Você poderia me ajudar?

    ResponderExcluir
  3. Bom dia Fernando
    Muito obrigado por vossos videos que sigo desde Paris. Apprendi bastente com a qualidade das informaçoes. Este video mostra uma imagem do Heltec Wifi Lora 32 que parece que foi feita com Fritzing. Nao consigo encontrar o modelo, seria possivel voce por a disposiçao en descarga no materail para download?
    Obrigado
    Daniel

    ResponderExcluir
  4. Olá,

    Estou tentando utilizar o EPS32 LORA WIFI da HELTEC junto do GPS-NEO6M e não estou conseguindo fazer leitura do GPS. Alguém poderia me ajudar? Já tentei usar Software e HardwareSerial ambas sem sucesso (talvez por falta de conhecimento de como utilizá-las corretamente)...

    ResponderExcluir
  5. Olá boa tarde a todos. Estou tentando reproduzir esse projeto, porém ao compilar apresenta o mesmo erro informado pelo colega acima. Alguma dica? Desde já agradeço.

    exit status 1
    no matching function for call to 'LoRaClass::begin(double, bool)'

    Miguel.

    ResponderExcluir
  6. na linha 54 ---> if (!LoRa.begin(BAND, true)){
    retirar o true
    desta forma funciona ---> if (!LoRa.begin(BAND)){

    ResponderExcluir
    Respostas
    1. Compilo, mais aparece no display MASTER e no outro esp32 aparece slave esperando mais nada

      Excluir
  7. Consigo compilar o MASTER, mas na compilação do Slave aparece um erro "Adafruit_SPIDevice.cpp: In member function 'bool Adafruit_SPIDevice::write(const uint8_t*, size_t, const uint8_t*, size_t)':"

    Acredito que deva ser algo que mudou na atualização de alguma library, tentei compilar em versões anteriores mas também não funcionou...

    ResponderExcluir
    Respostas
    1. Agora funcionou, vi que teve uma atualização na biblioteca Adafruit_BusIO, acredito que foi isso!

      Excluir