Bluetooth Low Energy com ESP32 e DHT11 Deixe um comentário

Você já deve ter ouvido falar de Bluetooth Low Energy, Bluetooth Smart ou BLE. Tem sido uma tecnologia bastante aplicada a dispositivos como sensores de batimento cardíaco, pedômetros, sensores para bicicleta entre outros. E se você já é nosso cliente também viu que temos em nossa loja alguns módulos disponíveis para quem quer começar a trabalhar com BLE como é o caso do módulo BLE Keyes HM-10 e a placa de desenvolvimento ESP32 WiFi+Bluetooth, e nesse post vamos abordar o uso do Bluetooth Low Energy com ESP32.

Bluetooth Low Energy com ESP32

Veremos alguns conceitos básicos sobre BLE, desenvolvendo um programa que utiliza os recursos de BLE do ESP32, para enviar a um aplicativo de celular, dados de temperatura e umidade, coletados de um DHT11. O aplicativo de celular será desenvolvido no Thunkable (uma plataforma parecida com MIT App Inventor).

Conceitos básicos sobre Bluetooth Low Energy

O Bluetooth Low Energy, ou BLE, é um subconjunto do clássico Bluetooth e foi introduzido juntamente com as especificações do Bluetooth 4.0. Em contraste com o BLuetooth clássico, o BLE tem um baixo consumo de energia mesmo mantendo um alcance similar.

Logo Bluetooth Low Energy 4.0

Os dispositivos que trabalham com BLE podem ter duas funções diferentes em uma conexão, Dispositivo Central ou Dispositivo Periférico (Central Device or Peripheral Device). Geralmente os dispositivos centrais são telefones celulares, tablets, computadores, etc. São dispositivos centrais que recebem dados. Já os dispositivos periféricos são sensores e dispositivos low power que se conectam ao dispositivo central. Podemos pensar também como uma estrutura cliente/servidor, onde um celular é o cliente e o sensor é o servidor que “serve” seus dados para o cliente.

GATT (Generic Attribute Profile), é a forma com que os dados são organizados para comunicação entre os dispositivos. GATT é composto por um ou mais serviços que por sua vez são compostos de características. Existem especificações padrão de GATT para os tipos de aplicação mais comuns encontradas no mercado. Várias dessas especificações podem ser encontradas no site oficial do Bluetooth. As características por sua vez são basicamente os valores em si.

Os serviços e características são identificados por um UUID. Por exemplo “0x180F” ou “6E400001-B5A3-F393-E0A9-E50E24DCCA9E”. O legal é que podemos criar nossas próprias características customizadas ou até mesmo utilizar as características já existentes como por exemplo Sensoriamento de Ambiente.

Para sermos um pouco mais práticos, vamos analisar, por exemplo, o serviço oficial de nível de bateria Battery Service. Esse serviço tem um UUID 0x180F e uma característica chamada Battery Level de UUID 0x2A19. Imagine que existe um sensor BLE que mede nível de bateria(serviço) e que envia dados indicando o nível da bateria(característica). Caso um celular se conecte a esse sensor, o celular já irá saber que aquele sensor mede nível de bateria e seus dados enviados são o nível da bateria em si. Pensando em um ESP32, se ele tiver programado essas características, ele “seria um sensor” de nível de bateria e seria reconhecido como tal por qualquer aplicativo BLE de celular (fica a dica para colocar sua criatividade em ação criando um dispositivo BLE, pode ser qualquer um destes).

Bluetooth Clássico vs BLE

Além da diferença do consumo de energia, que no caso do BLE é mais baixo se comparado ao Bluetooth clássico, a forma com que os dispositivos se comunicam e organizam seus dados também é diferente.

Com os módulos tipo HC-05 usávamos o bluetooth clássico. Eles basicamente faziam uma comunicação UART sem fio, bastando apenas parear os dispositivos como visto no Tutorial Módulo Bluetooth com Arduino. Mas se tentarmos parear um dispositivo BLE da mesma forma, veremos que a comunicação não é tão simples assim pois como vimos acima o BLE usa uma organização diferente de dados.

Para simular uma comunicação UART usando BLE, o fabricante Nordic Semiconductor criou um serviço proprietário chamado Nordic UART Service. É um serviço que tem duas características sendo elas TX para transmissão de dados e RX para recepção de dados. Esses serviços e suas características tem os seguintes UUIDs:

Nordic UART Service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
RX Characteristic: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
TX Characteristic: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E

Montagem do Circuito

O circuito do nosso teste usando Bluetooth Low Energy com ESP32 é bem simples e utilizaremos um sensor de umidade e temperatura DHT11. O pino de dados do DHT11 deve ser ligado ao pino 23 do ESP32.

Programa Bluetooth Low Energy com ESP32

Para programar o ESP32 utilizando a IDE Arduino, siga as instruções de instalação de acordo com seu sistema operacional. Certifique-se de conseguir compilar e carregar qualquer programa para o ESP32, por exemplo um Blink LED.

Carregue então o programa abaixo na IDE Arduino. Certifique-se também de ter a biblioteca para sensor DHT instalada em sua IDE.

O programa basicamente define os UUID do serviço de comunicação UART, faz a leitura de umidade e temperatura do sensor DHT e transmite esses dados para o aplicativo no celular. Os dados são enviados em uma única variável, mas num formato tipo CSV, com temperatura e umidade separados por vírgula.

/* 
 *  Programa baseado no programa original desenvolvido por Timothy Woo 
 *  Tutorial do projeto original; https://www.hackster.io/botletics/esp32-ble-android-arduino-ide-awesome-81c67d
 *  Modificado para ler dados do sensor DHT11 - Bluetooth Low Energy com ESP32
 */  
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#include <DHT.h>

#include <iostream>
#include <string>

BLECharacteristic *pCharacteristic;

bool deviceConnected = false;
const int LED = 2; // Could be different depending on the dev board. I used the DOIT ESP32 dev board.

/*
 * Definição do DHT11
 */
#define DHTPIN 23 // pino de dados do DHT11
#define DHTTYPE DHT11 // define o tipo de sensor, no caso DHT11

DHT dht(DHTPIN, DHTTYPE);

int humidity;
int temperature;

// Veja o link seguinte se quiser gerar seus próprios UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define DHTDATA_CHAR_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" 


class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();
      Serial.println(rxValue[0]);

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");

        for (int i = 0; i < rxValue.length(); i++) {
          Serial.print(rxValue[i]);
        }
        Serial.println();
        Serial.println("*********");
      }

      // Processa o caracter recebido do aplicativo. Se for A acende o LED. B apaga o LED
      if (rxValue.find("A") != -1) { 
        Serial.println("Turning ON!");
        digitalWrite(LED, HIGH);
      }
      else if (rxValue.find("B") != -1) {
        Serial.println("Turning OFF!");
        digitalWrite(LED, LOW);
      }
    }
};

void setup() {
  Serial.begin(115200);

  pinMode(LED, OUTPUT);

  // Create the BLE Device
  BLEDevice::init("ESP32 DHT11"); // Give it a name

  // Configura o dispositivo como Servidor BLE
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Cria o servico UART
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Cria uma Característica BLE para envio dos dados
  pCharacteristic = pService->createCharacteristic(
                      DHTDATA_CHAR_UUID,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
                      
  pCharacteristic->addDescriptor(new BLE2902());

  // cria uma característica BLE para recebimento dos dados
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());

  // Inicia o serviço
  pService->start();

  // Inicia a descoberta do ESP32
  pServer->getAdvertising()->start();
  Serial.println("Esperando um cliente se conectar...");
}

void loop() {
  if (deviceConnected) {

    humidity = dht.readHumidity();
    temperature = dht.readTemperature();
    // testa se retorno é valido, caso contrário algo está errado.
    if (isnan(temperature) || isnan(humidity)) 
    {
      Serial.println("Failed to read from DHT");
    }
    else 
    {
      Serial.print("Umidade: ");
      Serial.print(humidity);
      Serial.print(" %\t");
      Serial.print("Temperatura: ");
      Serial.print(temperature);
      Serial.println(" *C");
    }
    
    char humidityString[2];
    char temperatureString[2];
    dtostrf(humidity, 1, 2, humidityString);
    dtostrf(temperature, 1, 2, temperatureString);

    char dhtDataString[16];
    sprintf(dhtDataString, "%d,%d", temperature, humidity);
    
    pCharacteristic->setValue(dhtDataString);
    
    pCharacteristic->notify(); // Envia o valor para o aplicativo!
    Serial.print("*** Dado enviado: ");
    Serial.print(dhtDataString);
    Serial.println(" ***");
  }
  delay(1000);
}

Aplicativo de celular com Thunkable

Para que possamos visualizar no celular os dados enviados pelo ESP32, desenvolvemos um aplicativo utilizando a plataforma Thunkable. Pra quem já utilizou o MIT App Inventor já estará familiarizado com o Thunkable e irá achar super legal o Material Design.

O Thunkable contém uma extensão que nos possibilita a comunicação com dispositivos BLE. Iremos utilizar o Bluetooth Client:

Componente Bluetooth Client

O design da aplicação ficou como a seguir, mas você pode usar sua criatividade e mudar a “cara” da aplicação. Existem dois botões para gerenciar a conexão com o ESP32 e um botão mais abaixo para ligar e desligar o led built-in do ESP32. Em dois labels mostramos a temperatura e umidade do DHT11.

Design da tela do aplicativo

É na seção de blocos onde é feita a programação do aplicativo. Veja na foto a seguir a estrutura geral do aplicativo:

Blocos do aplicativo completo

Primeiramente declaramos os UUIDs utilizados pelo ESP32.

Blocos do aplicativo

Então gerenciamos o escaneamento e conexão de dispositivos:

Blocos do aplicativo

O botão disconnect fica responsável por desconectar o ESP32.

Blocos do aplicativo

Um Timer verifica se o dispositivo ainda está conectado e se foi recebido algum dado do ESP32. Assim que um dado é recebido, o evento StringsReceived é disparado, exibindo os dados de temperatura e umidade nos respectivos labels. Nesse bloco fazemos a separação dos dados de temperatura e umidade que foram recebidos separados por uma vírgula.

Blocos do aplicativo

Quando o botão LED é clicado, o bloco a seguir envia um caractere A ou B para o ESP32, que por sua vez liga o LED se receber A ou desliga se receber B.

Blocos do aplicativo

Caso queira modificar a aplicação você pode baixar o arquivo do projeto(.aia) aqui. Ou se preferir, pode instalar o .apk direto no seu celular. 

Funcionamento do Projeto

Veja no vídeo abaixo o funcionamento do projeto Bluetooth Low Energy com ESP32. Basta clicar no botão connect, escolher o ESP32 na lista de dispositivos e os dados já começam a aparecer. Acenda e apague o LED clicando no botão LED.

Esse projeto de Bluetooth Low Energy com ESP32 foi baseado no projeto original de Timothy Woo e pode ser encontrado no Hackster.io. Agradecemos também ao Timothy por ter nos ajudado com algumas questões técnicas, sobre como enviar mais de um dado ao aplicativo usando apenas uma característica.

Gostou de aprender sobre Bluetooth Low Energy com ESP32? Ajude-nos a melhorar o blog comentando abaixo sobre este tutorial. Não se esqueça de visitar nosso Fórum!

Faça seu comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *