Registre dados no banco de dados MySQL usando o NodeMCU Development Board
NodeMCU é uma plataforma IoT de código aberto de baixo custo que inicialmente incluía firmware que roda no ESP8266 Wi-Fi SoC da Espressif Systems, e hardware que era baseado no módulo ESP-12.
Se você está começando com IoT ou microcontroladores em geral, esta placa de desenvolvimento é uma competição feroz para tudo que você vai encontrar, pelo menos inicialmente.
Neste projeto, enfatizaremos como fazer a interface da placa de desenvolvimento NodeMCU com uma cópia local do banco de dados MySQL usando PHP.
Conteudo
Principalmente,
- Estaremos construindo um ponto de acesso NodeMCU que fará uma solicitação POST com os dados do sensor para um script PHP que irá inserir os dados em uma cópia local do banco de dados MySQL.
- Estaremos montando uma página da Web que recuperará a leitura mais recente do banco de dados MySQL e a exibirá.
Observação: a página da web neste contexto não buscará os dados do banco de dados de forma assíncrona para evitar a complexidade óbvia. Teremos que recarregar a página para ver os dados mais recentes, podemos automatizar o processo de recarregamento da página inserindo uma meta tag HTML5:
<meta http-equiv="refresh" content="1">
Onde o atributo content representa o intervalo em segundos de atualização automática da página.
Secundariamente, para apimentar as coisas no lado do hardware,
- Faremos interface com um sensor de temperatura e umidade DHT11, que será armazenado no banco de dados MySQL.
- Faremos interface com um display OLED de 0,96 polegadas (comumente conhecido como SSD1306 OLED) e exibiremos as leituras.
Componentes necessários
- NodeMCU
- Sensor DHT11
- Módulo de exibição OLED de 0,96 polegada I2C/IIC 128×64 4 pinos
- Resistor de 10K 0,5W
- Protoboard
- Fios de jumper macho para macho x10
Diagrama de circuito
Como você pode notar na ilustração do circuito acima, conectar as coisas é bastante simples.
1. Ligação de DHT11 para NodeMCU
- Comece colocando o NodeMCU em sua placa de ensaio, garantindo que cada lado da placa esteja em um lado separado da placa de ensaio.
- Agora, coloque o sensor em sua placa de ensaio ao lado do NodeMCU.
- Conecte o pino VCC no sensor ao pino de 3,3 V no NodeMCU e faça o aterramento.
- Além disso, conecte o pino de dados no sensor ao pino D3 do NodeMCU.
- Finalmente, precisamos colocar um resistor pull-up de 10KΩ entre o VCC e a linha de dados para mantê-lo ALTO para a comunicação adequada entre o sensor e o NodeMCU.
2. Conectando o OLED ao NoceMCU
- As conexões são bastante simples. Comece conectando o pino VCC à saída de 3,3 V no NodeMCU e conecte o GND ao aterramento.
- Em seguida, conecte o pino SCL ao pino D1 do relógio I2C em seu NodeMCU e conecte o pino SDA ao pino D2 de dados I2C em seu NodeMCU.
Dito isso, nosso hardware está instalado, observe que não iremos nos aprofundar nos aspectos de codificação do hardware, mas o código será comentado o suficiente para ser autoexplicativo, pois nossa agenda principal é entender o MySQL e sua interface com NodeMCU.
Configurando o Ambiente de Desenvolvimento Local
Observação: o único motivo pelo qual precisamos configurar manualmente um ambiente de desenvolvimento é que hospedaremos e desenvolveremos o projeto localmente, sem necessidade de internet depois que a configuração for concluída.
1. Baixe o XAMPP -> Ele está sendo anunciado como o ambiente de desenvolvimento de PHP mais popular no momento em que este artigo foi escrito.
Ele está disponível para MacOS, Windows e Linux e o processo de instalação será semelhante em todos os sistemas operacionais.
Link para download: https://www.apachefriends.org/index.html
2. Clique no arquivo de instalação para iniciar o clique em Avançar até que seja solicitado a instalar o aplicativo.
Observação: certifique-se de que todos os componentes estejam instalados, alguns dos quais não são necessários para nosso projeto, mas podem ser internamente necessários para que as coisas funcionem perfeitamente.
3. Após a instalação bem-sucedida, execute o Painel de controle do XAMPP a partir do atalho da área de trabalho.
Você poderá ver algo como abaixo na janela do aplicativo.
4. Execute instâncias do Apache Server e MySQL clicando no botão Iniciar no Painel de Controle do XAMPP.
Acesse o painel phpMyAdmin clicando no botão Admin localizado na linha MySQL do Painel de controle do XAMPP. Que o abrirá em uma guia do navegador.
5. Agora, teremos acesso ao phpMyAdmin que pode ser usado para criar um novo banco de dados MySQL para nosso projeto.
Um resumo sobre phpMyAdmin:
É um dos aplicativos mais populares para gerenciamento de banco de dados MySQL. É uma ferramenta gratuita escrita em PHP. Através deste software, você pode criar, alterar, eliminar, excluir, importar e exportar tabelas de banco de dados MySQL. Você pode executar consultas MySQL, otimizar, reparar e verificar tabelas, alterar agrupamento e executar outros comandos de gerenciamento de banco de dados.
Configurando o banco de dados MySQL usando phpMyAdmin
1. Clique em “Novo” na barra lateral localizada à esquerda do phpMyAdmin para criar um novo banco de dados.
Você será solicitado a preencher dois campos:
1. Nome do banco de dados
2. Collation
Nota: Você pode pesquisar o que é agrupamento na Internet ou apenas seguir em frente, o agrupamento padrão é utfmb4_general_ci que funcionará bem para o projeto, pois oferece suporte a tudo que precisaremos.
Chamamos nosso banco de dados de “nodemcu_datalog” aqui, que pode ser renomeado para qualquer nome válido.
2. O próximo passo será criar uma tabela em nosso banco de dados.
- Vamos nomear nossa tabela como “dht11_sensorlog”.
- Queremos que nossa tabela tenha quatro colunas, a saber, id, temperatura, umidade e tempo de leitura.
Clique na guia “SQL” na barra superior para executar uma consulta SQL que criará uma tabela para nós, cole a consulta como abaixo e clique no botão “GO” no canto inferior direito.
CREATE TABLE dht11_sensorlog ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, temperature FLOAT, humidity FLOAT, reading_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP )
Isso criará uma tabela com campos especificados:
Aqui, o ID é atribuído com “AUTO_INCREMENT”, o que significa que toda vez que novos dados chegam, o ID é incrementado em um em comparação com os dados da linha anterior.
Além disso, o atributo “PRIMARY_KEY” significa que cada valor nesta coluna é único.
Agora você pode ver a tabela vazia com o nome das colunas que serão preenchidas com os dados do sensor.
Ao clicar na guia Estrutura na barra superior, você verá todas as colunas e seus tipos, como pode ser visto abaixo.
Além disso, toda vez que inserirmos alguns dados na tabela, o campo “reading_time” será preenchido automaticamente com o carimbo de data / hora de quando os dados foram inseridos.
3. Para finalizar, criaremos um usuário e uma senha do banco de dados.
1. Clique na guia “Contas de usuário” na barra superior.
2. Clique em “Adicionar conta de usuário” e preencha as informações de login conforme abaixo.
3. Clique em “Ir” no canto inferior esquerdo para criar um usuário com sucesso.
Com isso dito, concluímos a configuração de nosso banco de dados.
Script PHP para inserir dados no banco de dados
Vamos agora começar a escrever nosso script php para inserir dados no banco de dados MySQL.
Para simplificar, criaremos um novo arquivo de texto como “phpwrite.txt”. E mais tarde, quando terminarmos de escrever o código, podemos alterar a extensão do arquivo para “dbwrite.php”
É hora de colocar a mão na massa escrevendo alguns códigos PHP …
Espere um pouco se você nunca foi ao PHP antes, você pode ler os comentários um por um para ter uma ideia.
Esta é a aparência do código:
<?php // host = localhost porque banco de dados hospedado no mesmo servidor onde os arquivos PHP estão hospedados // tudo prefixado com $ é uma variável PHP $host = "localhost"; $dbname = "nodemcu_datalog"; // Nome do Database $username = "admin"; // Usuario do Database $password = "root"; // Senha do Database // Estabeleça conexão com o banco de dados MySQL, usando a biblioteca MySQLi embutida. $conn = new mysqli($host, $username, $password, $dbname); // Verifique se a conexão foi estabelecida com sucesso if ($conn->connect_error) { die("Falha na conexão: " . $conn->connect_error); } else { echo "Conectado ao banco de dados mysql."; } // $_POST é uma Superglobal PHP que nos auxilia na coleta / acesso aos dados, que chegam na forma de um post request feito a este script. // Se os valores enviados por NodeMCU não estiverem vazios, insira na tabela do banco de dados MySQL if(!empty($_POST['sendval']) && !empty($_POST['sendval2']) ){ // "sendval" e "sendval2" são parâmetros de consulta acessados a partir da solicitação HTTP POST feita pelo NodeMCU. $temperature = $_POST['sendval']; $humidity = $_POST['sendval2']; // Atualize seu nome de tabela aqui // Uma consulta SQL para inserir dados na tabela -> INSERT INTO table_name (col1, col2, ..., colN) VALUES (' " .$col1. " ', '".col2."', ..., ' ".colN." ') $sql = "INSERT INTO dht11_sensorlog (temperature, humidity) VALUES ('".$temperature."','".$humidity."')"; if ($conn->query($sql) === TRUE) { // Se a consulta retornar verdadeiro, significa que foi executada com sucesso echo "Valores inseridos na tabela do banco de dados MySQL."; } else { echo "Erro: " . $sql . "<br>" . $conn->error; } } // Fechar conexão MySQL $conn->close(); ?>
Script PHP para exibir as leituras mais recentes
Agora que terminamos de gravar no banco de dados, passaremos para a leitura de nosso banco de dados MySQL e mostraremos a última leitura na tela.
Mas, desta vez, nosso script PHP será executado no servidor e retornará HTML, o que nos permitirá visitar a página da web e ver as últimas leituras.
Observação: conforme discutido anteriormente, nossa página da web não buscará os dados do banco de dados de forma assíncrona para evitar a complexidade óbvia. Teremos que recarregar a página para ver os dados mais recentes, podemos automatizar o processo de recarregamento da página inserindo um HTML5 Meta Marcação:
<meta http-equiv="refresh" content="1">
Onde o atributo content representa o intervalo em segundos de atualização automática da página.
<html> <head> <title>NodeMCU MySQL Datalog</title> <meta http-equiv="refresh" content="1"> <!-- Refreshes the browser every 1 second --> <!-- All the CSS styling for our Web Page, is inside the style tag below --> <style type="text/css"> * { margin: 0; padding: 0; } body { background: url('/bg.jpeg') no-repeat center center; background-attachment: fixed; background-size: cover; display: grid; align-items: center; justify-content: center; height: 100vh; font-family:Haettenschweiler, 'Arial Narrow Bold', sans-serif; } .container { box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .2); border-radius: 1rem; position: relative; z-index: 1; background: inherit; overflow: hidden; text-align:center; padding: 5rem; font-size:40px; color: white; } .container:before { content: ""; position: absolute; background: inherit; z-index: -1; top: 0; left: 0; right: 0; bottom: 0; box-shadow: inset 0 0 2000px rgba(255, 255, 255, .5); filter: blur(10px); margin: -20px; } h1{ font-size: 40px; } p{ margin: 60px 0 0 0; } </style> </head> <body> <?php $host = "localhost"; // host = localhost porque banco de dados hospedado no mesmo servidor onde os arquivos PHP estão hospedados $dbname = "nodemcu_datalog"; // Nome do Database $username = "admin"; // Nome do Usuario $password = "root"; // Senha do Usuario // Estabelece conexão com o banco de dados MySQL $conn = new mysqli($host, $username, $password, $dbname); // Verifique se a conexão foi estabelecida com sucesso if ($conn->connect_error) { die("Conexão falhou: " . $conn->connect_error); } // Consultar a única entrada mais recente do banco de dados. -> SELECT * FROM table_name ORDER BY col_name DESC LIMIT 1 $sql = "SELECT * FROM dht11_sensorlog ORDER BY id DESC LIMIT 1"; $result = $conn->query($sql); if ($result->num_rows > 0) { // Será útil se mais tarde quisermos buscar várias linhas da tabela while($row = $result->fetch_assoc()) { //fetch_assoc busca uma linha do resultado de nossa consulta iterativamente para cada linha em nosso resultado. //Retornando HTML do servidor para mostrar na página da web. echo '<div class="container">'; echo '<h1>NodeMCU Data Logging</h1>'; echo '<p>'; echo ' <span class="dht-labels">Temperature = </span>'; echo ' <span id="temperature">'.$row["temperature"].' ℃</span>'; echo ' </p>'; echo '<p>'; echo ' <span class="hum dht-labels">Humidity = </span>'; echo ' <span id="humidity">'.$row["humidity"].' %</span>'; echo ' </p>'; echo '</div>'; } } else { echo "0 results"; } ?> </body> </html>
Detalhando a consulta SQL que busca os dados mais recentes
“SELECT * FROM dht11_sensorlog ORDER BY id DESC LIMIT 1”
SELECT * -> Usado para selecionar todas as colunas / campos do banco de dados
FROM nome_tabela -> A tabela da qual os dados estão sendo buscados
ORDER BY field_name DESC -> Recupera dados em ordem alfabética ou numérica decrescente.
LIMIT some_number -> O número define quantas linhas queremos recuperar do resultado.
Depois de ter ambos os scripts php prontos, é hora de alterar a extensão de ambos os arquivos para.php, se ainda não estiver.
Em seguida, você terá que movê-los para a pasta htdocs dentro da pasta de instalação principal do xampp, junto com todos os ativos, como imagens, etc.
Código NodeMCU
1. O sketch começa incluindo bibliotecas:
#include "DHT.h" #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Adafruit_Sensor.h> #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h>
Você deve instalar algumas dessas bibliotecas do gerenciador de biblioteca presente no Arduino IDE.
2. Em seguida, todas as variáveis globais, definições de pinos e classes necessárias são instanciadas:
//Inicializações para sensor DHT11 #define DHTPIN 0 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); float Temperature; float Humidity; // Fim das inicializações do sensor DHT11 // Inicializações para sensor SSD1306 #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaração para o display SSD1306 conectado via I2C -> SDA + Pinos SCL Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // "&Wire" Declara o protocolo de comunicação I2C // "-1" informa que o display OLED não possui um pino de RESET, o que é o caso do nosso display OLED. // Fim das inicializações para sensor SSD1306 // Declara variáveis globais que serão uploaded to server String sendval, sendval2, postData;
3. A função setup():
void setup() { dht.begin(); Serial.begin(115200); Serial.println("Comunicação iniciada \n\n"); delay(1000); pinMode(LED_BUILTIN, OUTPUT); //inicializar o led integrado na placa if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } delay(2000); display.clearDisplay(); display.setTextColor(WHITE); WiFi.mode(WIFI_AP); //nome do ponto de acesso e senha de 8 caracteres WiFi.softAP("NodeMCU", "nodemcur"); delay(200); while (WiFi.softAPgetStationNum() !=1){ //faça um loop aqui enquanto nenhum AP estiver conectado a esta estação Serial.print("."); delay(100); } delay(500);
O trecho de código mais importante aqui é configurar o NodeMCU como um ponto de acesso WiFI:
// configure o modo WiFi.mode(WIFI_AP); // nome do ponto de acesso e senha de 8 caracteres WiFi.softAP("NodeMCU", "nodemcur");
Agora, este AP WiFi pode ser acessado usando a senha definida. Uma vez que o cliente está conectado ao AP, precisamos do endereço IPv4 do nodemcu no lado do cliente para permitir fazer solicitações POST.
Nota: Assim que o AP estiver pronto, conecte o dispositivo cliente e extraia o endereço IPv4, que é o endereço IP real no qual uma solicitação POST pode ser feita.
O endereço IPv4 aqui é: 192.168.4.2.
4. A função loop()
void loop(){ // ler temperatura e umidade float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); if(isnan(temperature) || isnan(humidity)){ Serial.println("Falha ao ler DHT11"); } else { Serial.print("Humidity: "); Serial.print(humidity); Serial.print(" %\t"); Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" *C"); delay(450); } // exibição clara display.clearDisplay(); // temperatura do display display.setTextSize(1); display.setCursor(0,0); display.print("Temperature: "); display.setTextSize(2); display.setCursor(0,10); display.print(temperature); display.print(" "); display.setTextSize(1); display.cp437(true); display.write(167); display.setTextSize(2); display.print("C"); // exibir umidade display.setTextSize(1); display.setCursor(0, 35); display.print("Humidity: "); display.setTextSize(2); display.setCursor(0, 45); display.print(humidity); display.print(" %"); display.display(); HTTPClient http; // objeto http de clas HTTPClient // Converter para flutuar sendval = float(temperature); sendval2 = float(humidity); postData = "sendval=" + sendval + "&sendval2=" + sendval2; // Podemos postar valores em arquivos PHP como example.com/dbwrite.php?name1=val1&name2=val2 // Portanto, criamos a variável postData e armazenamos nossas variáveis nela no formato desejado // Atualize o URL do host aqui: - http.begin("http://192.168.4.2/dbwrite.php"); // Conecte-se ao host onde o banco de dados MySQL está hospedado http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Especifique o cabeçalho do tipo de conteúdo int httpCode = http.POST(postData); // Envie a solicitação POST para o arquivo php e armazene o código de resposta do servidor na variável chamada httpCode Serial.println("Os valores são, sendval = " + sendval + " e sendval2 = "+sendval2 ); // se a conexão for estabelecida, faça isso if (httpCode == 200) { Serial.println("Valores enviados com sucesso."); Serial.println(httpCode); String webpage = http.getString(); // Obtenha a saída da página da web em html e armazene-a em uma string Serial.println(webpage + "\n"); } else { // se houver falha na conexão, retorne e reinicie Serial.println(httpCode); Serial.println("Failed to upload values. \n"); http.end(); return; } delay(200); digitalWrite(LED_BUILTIN, LOW); delay(200); digitalWrite(LED_BUILTIN, HIGH); }
Código para fazer uma solicitação POST ao nosso servidor local:
sendval = float(temperature); sendval2 = float(humidity); // Construir a string de dados postData = "sendval=" + sendval + "&sendval2=" + sendval2; // Conecte-se ao host onde o banco de dados MySQL está hospedado, com o endereço IPv4 de nosso NodeMCU http.begin("http://192.168.4.2/dbwrite.php"); // Especifique o cabeçalho do tipo de conteúdo http.addHeader("Content-Type", "application/x-www-form-urlencoded"); // Envie a solicitação POST para o arquivo php e armazene o código de resposta do servidor na variável chamada httpCode int httpCode = http.POST(postData);
Dito isso, agora você pode visitar a página da web:
http://192.168.4.2/dbread.php
Nota: dbread.php era o nome da nossa página conforme salvamos na pasta “htdocs”. O nome do arquivo pode ser atualizado para qualquer nome válido e, portanto, a URL deve variar.
Hardware Images:
Código
#include "DHT.h" #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Adafruit_Sensor.h> #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #define DHTPIN 0 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); float Temperature; float Humidity; #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); String sendval, sendval2, postData; void setup() { dht.begin(); Serial.begin(115200); Serial.println("Communication Started \n\n"); delay(1000); pinMode(LED_BUILTIN, OUTPUT); // inicializa o led integrado na placa if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } delay(2000); display.clearDisplay(); display.setTextColor(WHITE); WiFi.mode(WIFI_AP); WiFi.softAP("NodeMCU", "nodemcur"); delay(200); while (WiFi.softAPgetStationNum() !=1) { // loop aqui enquanto nenhum AP está conectado a esta estação Serial.print("."); delay(100); } delay(500); } void loop(){ //read temperature and humidity float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); if(isnan(temperature) || isnan(humidity)){ Serial.println("Failed to read DHT11"); } else { Serial.print("Humidity: "); Serial.print(humidity); Serial.print(" %\t"); Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" *C"); delay(450); } display.clearDisplay(); display.setTextSize(1); display.setCursor(0,0); display.print("Temperature: "); display.setTextSize(2); display.setCursor(0,10); display.print(temperature); display.print(" "); display.setTextSize(1); display.cp437(true); display.write(167); display.setTextSize(2); display.print("C"); display.setTextSize(1); display.setCursor(0, 35); display.print("Humidity: "); display.setTextSize(2); display.setCursor(0, 45); display.print(humidity); display.print(" %"); display.display(); HTTPClient http; // Converter para float sendval = float(temperature); sendval2 = float(humidity); postData = "sendval=" + sendval + "&sendval2=" + sendval2; // Podemos postar valores em arquivos PHP como example.com/dbwrite.php?name1=val1&name2=val2 // Portanto, criamos a variável postData e armazenamos nossas variáveis nela no formato desejado // Atualize o URL do host aqui: - http.begin("http://192.168.4.2/dbwrite.php"); // Conecte-se ao host onde o banco de dados MySQL está hospedado http.addHeader("Content-Type", "application/x-www-form-urlencoded"); int httpCode = http.POST(postData); // Envie a solicitação POST para o arquivo php e armazene o código de resposta do servidor na variável chamada httpCode Serial.println("Values are, sendval = " + sendval + " and sendval2 = "+sendval2 ); if (httpCode == 200) { Serial.println("Valores carregados com sucesso."); Serial.println(httpCode); String webpage = http.getString(); Serial.println(webpage + "\n"); } else { Serial.println(httpCode); Serial.println("Failed to upload values. \n"); http.end(); return; } delay(200); digitalWrite(LED_BUILTIN, LOW); delay(200); digitalWrite(LED_BUILTIN, HIGH); }