Hoje vamos dar continuidade a série de posts sobre a Planta IoT com ESP8266 NodeMCU, uma planta conectada à internet que avisa no seu celular quando precisa ser regada. Nesta continuação, a planta não vai somente avisar quando precisa ser regada, mas sim vai se regar sozinha! Ou seja, através de conceitos IoT, a planta irá reportar a situação da umidade de solo e, sem você precisar tomar ação alguma, ela irá se regar se necessário. Portanto, trata-se de uma solução ideal para você que precisa se ausentar de sua casa com frequência e quer que suas plantas fiquem bem cuidadas.
Se você perdeu os “episódios anteriores” do projeto Planta IoT com ESP8266 NodeMCU, acesse os links abaixo:
- Planta IoT com ESP8266 NodeMCU – Parte 1 (Monitoramento da planta IoT com ThingSpeak)
- Planta IoT com ESP8266 NodeMCU – Parte 2 (Envio de avisos pelo Twitter)
- Planta IoT com ESP8266 NodeMCU – Parte 3 (Integração com MQTT)
Como a planta IoT vai se auto regar?
Para a planta IoT se auto regar, iremos utilizar um hardware adicional ao projeto: a Válvula de Vazão Solenóide Água 12VDC. Esta válvula permite, através de um sinal de controle de 12V, liberar ou restringir o fluxo de água por ela. Em outras palavras, é como uma “torneira acionada eletricamente”. Portanto, em termos de hardware, iremos precisar utilizar tal válvula e um circuito para permitir o acionamento da mesma sem danificar o NodeMCU (para mais informações sobre os limites elétricos do NodeMCU, leia este nosso post).
A regra para a planta se auto regar é simples: de trinta em trinta segundos (período de envio da umidade do solo ao ThingSpeak) é verificada se a umidade do solo é menor ou igual que o limite para regar (valor configurável no código, mas com default 30%). Em caso positivo, a válvula de vazão solenóide de água é acionada no tempo configurado (default de dois segundos).
Lista de componentes e circuito esquemático
O circuito completo do projeto utilizará os seguintes componentes:
- NodeMCU
- Válvula de vazão solenóide água 12VDC
- Fonte DC chaveada 12V 2A (metálica)
- Sensor de umidade do solo higrômetro
- Resistor 1K 1/4W
- Resistor 2K 1/4W
- Protoboard (preferencialmente de 830 pontos)
- Transistor BC337
- Diodo 1N4007
- Jumpers diversos
- Fios e plug para tomada
- Mangueiras e conexões hidráulicas (para ligação da válvula à uma torneira)
O circuito esquemático pode ser visto abaixo:
Atenção: fazer as ligações da fonte 12V conforme ilustra a imagem a seguir. Observar que a ligação deve ser feita em rede 110V e que em L deve ser ligada a fase e em N o neutro (do ponto de energia / tomada que você estiver ligando a fonte).
Código-fonte
O código fonte do projeto planta IoT com ESP8266 NodeMCU pode ser visto a seguir. Observe com atenção os defines LIMITE_UMIDADE_PARA_REGAR (este valor determina qual será o limite percentual inferior da umidade do solo para a planta se regar) e TEMPO_PARA_REGAR (aqui é determinado por quanto tempo a válvula de vazão solenóide de água será acionada). Altere-os conforme seu gosto e necessidade.
//Programa: Planta IoT com ESP8266 NodeMCU e MQTT #include <ESP8266WiFi.h> //essa biblioteca já vem com a IDE. Portanto, não é preciso baixar nenhuma biblioteca adicional #include <PubSubClient.h> // Importa a Biblioteca PubSubClient //defines - mapeamento de pinos do NodeMCU #define D0 16 #define D1 5 #define D2 4 #define D3 0 #define D4 2 #define D5 14 #define D6 12 #define D7 13 #define D8 15 #define D9 3 #define D10 1 //defines #define SSID_REDE " " //coloque aqui o nome da rede que se deseja conectar #define SENHA_REDE " " //coloque aqui a senha da rede que se deseja conectar #define INTERVALO_ENVIO_THINGSPEAK 30000 //intervalo entre envios de dados ao ThingSpeak (em ms) #define INTERVALO_ENVIO_MQTT 10000 //intervalo entre envios de dados via MQTT (em ms) #define LIMITE_UMIDADE_PARA_REGAR 30 //limite percentual inferior para a planta se auto regar #define TEMPO_PARA_REGAR 2000 //tempo (em ms) ao qual a válvula de vazão solenóide de água será acionada quando for necessário regar a planta #define SAIDA_COMANDO_VALVULA D0 //saída do NodeMCU que acionará a válvula de vazão solenóide de água //defines de id mqtt e tópicos para publicação e subscribe #define TOPICO_SUBSCRIBE "MQTTFFPlantaIoTEnvia" //tópico MQTT de escuta #define TOPICO_PUBLISH "MQTTFFPlantaIoTRecebe" //tópico MQTT de envio de informações para Broker //IMPORTANTE: recomendamos fortemente alterar os nomes // desses tópicos. Caso contrário, há grandes // chances de você controlar e monitorar o NodeMCU // de outra pessoa. #define ID_MQTT "PlantaIotParte3" //id mqtt (para identificação de sessão) //IMPORTANTE: este deve ser único no broker (ou seja, // se um client MQTT tentar entrar com o mesmo // id de outro já conectado ao broker, o broker // irá fechar a conexão de um deles). //constantes e variáveis globais const char* BROKER_MQTT = "iot.eclipse.org"; //URL do broker MQTT que se deseja utilizar int BROKER_PORT = 1883; // Porta do Broker MQTT char EnderecoAPIThingSpeak[] = "api.thingspeak.com"; String ChaveEscritaThingSpeak = " "; //coloque aqui sua chave de escrita do seu canal no ThingSpeak long lastConnectionTime; long lastMQTTSendTime; WiFiClient client; WiFiClient clientMQTT; PubSubClient MQTT(clientMQTT); // Instancia o Cliente MQTT passando o objeto clientMQTT //prototypes void EnviaInformacoesThingspeak(String StringDados); float FazLeituraUmidade(void); void initWiFi(void); void initMQTT(void); void reconectWiFi(void); void mqtt_callback(char* topic, byte* payload, unsigned int length); void VerificaConexoesWiFIEMQTT(void); /* * Implementações */ //Função: envia informações ao ThingSpeak //Parâmetros: String com a informação a ser enviada //Retorno: nenhum void EnviaInformacoesThingspeak(String StringDados) { if (client.connect(EnderecoAPIThingSpeak, 80)) { //faz a requisição HTTP ao ThingSpeak client.print("POST /update HTTP/1.1n"); client.print("Host: api.thingspeak.comn"); client.print("Connection: closen"); client.print("X-THINGSPEAKAPIKEY: "+ChaveEscritaThingSpeak+"n"); client.print("Content-Type: application/x-www-form-urlencodedn"); client.print("Content-Length: "); client.print(StringDados.length()); client.print("nn"); client.print(StringDados); lastConnectionTime = millis(); Serial.println("- Informações enviadas ao ThingSpeak!"); } } //Função: inicializa e conecta-se na rede WI-FI desejada //Parâmetros: nenhum //Retorno: nenhum void initWiFi() { delay(10); Serial.println("------Conexao WI-FI------"); Serial.print("Conectando-se na rede: "); Serial.println(SSID_REDE); Serial.println("Aguarde"); reconectWiFi(); } //Função: inicializa parâmetros de conexão MQTT(endereço do // broker, porta e seta função de callback) //Parâmetros: nenhum //Retorno: nenhum void initMQTT() { MQTT.setServer(BROKER_MQTT, BROKER_PORT); //informa qual broker e porta deve ser conectado MQTT.setCallback(mqtt_callback); //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega) } //Função: função de callback // esta função é chamada toda vez que uma informação de // um dos tópicos subescritos chega) //Parâmetros: nenhum //Retorno: nenhum void mqtt_callback(char* topic, byte* payload, unsigned int length) { } //Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) // em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. //Parâmetros: nenhum //Retorno: nenhum void reconnectMQTT() { while (!MQTT.connected()) { Serial.print("* Tentando se conectar ao Broker MQTT: "); Serial.println(BROKER_MQTT); if (MQTT.connect(ID_MQTT)) { Serial.println("Conectado com sucesso ao broker MQTT!"); MQTT.subscribe(TOPICO_SUBSCRIBE); } else { Serial.println("Falha ao reconectar no broker."); Serial.println("Havera nova tentatica de conexao em 2s"); delay(2000); } } } //Função: reconecta-se ao WiFi //Parâmetros: nenhum //Retorno: nenhum void reconectWiFi() { //se já está conectado a rede WI-FI, nada é feito. //Caso contrário, são efetuadas tentativas de conexão if (WiFi.status() == WL_CONNECTED) return; WiFi.begin(SSID_REDE, SENHA_REDE); // Conecta na rede WI-FI while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); } Serial.println(); Serial.print("Conectado com sucesso na rede "); Serial.print(SSID_REDE); Serial.println("IP obtido: "); Serial.println(WiFi.localIP()); } //Função: verifica o estado das conexões WiFI e ao broker MQTT. // Em caso de desconexão (qualquer uma das duas), a conexão // é refeita. //Parâmetros: nenhum //Retorno: nenhum void VerificaConexoesWiFIEMQTT(void) { if (!MQTT.connected()) reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita reconectWiFi(); //se não há conexão com o WiFI, a conexão é refeita } //Função: faz a leitura do nível de umidade //Parâmetros: nenhum //Retorno: umidade percentual (0-100) //Observação: o ADC do NodeMCU permite até, no máximo, 1V. Dessa forma, // para 1V, obtem-se (empiricamente) 418 como leitura de ADC float FazLeituraUmidade(void) { int ValorADC; float UmidadePercentual; ValorADC = analogRead(0); //418 -> 1.0V Serial.print("[Leitura ADC] "); Serial.println(ValorADC); //Quanto maior o numero lido do ADC, menor a umidade. //Sendo assim, calcula-se a porcentagem de umidade por: // // Valor lido Umidade percentual // _ 0 _ 100 // | | // | | // - ValorADC - UmidadePercentual // | | // | | // _|_ 418 _|_ 0 // // (UmidadePercentual-0) / (100-0) = (ValorADC - 418) / (-418) // Logo: // UmidadePercentual = 100 * ((418-ValorADC) / 418) UmidadePercentual = 100 * ((418-(float)ValorADC) / 418); Serial.print("[Umidade Percentual] "); Serial.print(UmidadePercentual); Serial.println("%"); return UmidadePercentual; } void setup() { Serial.begin(9600); lastConnectionTime = 0; lastMQTTSendTime = 0; initWiFi(); initMQTT(); pinMode(SAIDA_COMANDO_VALVULA,OUTPUT); digitalWrite(SAIDA_COMANDO_VALVULA,LOW); //por default, a válvula de vazão solenóide de água começa fechada Serial.println("Planta IoT com ESP8266 NodeMCU"); } //loop principal void loop() { float UmidadePercentualLida; int UmidadePercentualTruncada; char FieldUmidade[11]; char MsgUmidadeMQTT[50]; VerificaConexoesWiFIEMQTT(); //Força desconexão ao ThingSpeak (se ainda estiver desconectado) if (client.connected()) { client.stop(); Serial.println("- Desconectado do ThingSpeak"); Serial.println(); } UmidadePercentualLida = FazLeituraUmidade(); UmidadePercentualTruncada = (int)UmidadePercentualLida; //trunca umidade como número inteiro //verifica se está conectado no WiFi e se é o momento de enviar dados ao ThingSpeak if(!client.connected() && ((millis() - lastConnectionTime) > INTERVALO_ENVIO_THINGSPEAK)) { sprintf(FieldUmidade,"field1=%d",UmidadePercentualTruncada); EnviaInformacoesThingspeak(FieldUmidade); } //verifica se é o momento de enviar informações via MQTT if ((millis() - lastMQTTSendTime) > INTERVALO_ENVIO_MQTT) { sprintf(MsgUmidadeMQTT,"- Umidade do solo: %d porcento.",UmidadePercentualTruncada); MQTT.publish(TOPICO_PUBLISH, MsgUmidadeMQTT); lastMQTTSendTime = millis(); } //verifica se a planta deve ser regada if (UmidadePercentualTruncada <= LIMITE_UMIDADE_PARA_REGAR) { //em caso positivo, a planta é regada no tempo contido no define TEMPO_PARA_REGAR digitalWrite(SAIDA_COMANDO_VALVULA,HIGH); //abre a válvula de vazão solenóide de água delay(TEMPO_PARA_REGAR); digitalWrite(SAIDA_COMANDO_VALVULA,LOW); //fecha a válvula de vazão solenóide de água } delay(1000); }
Abaixo você confere o projeto da Planta IoT em ação!
Gostou? Deixe seu comentário logo abaixo.
a valvula nunca ativa, consegue me ajudar?
Olá Miguel,
A válvula está conectada no pino D0 do ESP? O transistor utilizado é um BC337 ou compatível?
Você pode colocar um LED no pino D0 no lugar da válvula para ver se o comando está sendo enviado corretamente, se o LED acender, quer dizer que o comando está saindo do ESP corretamente.
Abraços!
Vinícius – Equipe MakerHero
#include
uint8_t temperature, humidity, icalor;
ThingSpeak.setField( 1, temperature);
ThingSpeak.setField( 2, indicecalor);
ThingSpeak.setField( 3, humidity);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
consegui utilizar o ThingSpeak por meio desta biblioteca contudo quando uso dela minha função de callback não funciona
void setup() {
// put your setup code here, to run once:
dht.begin();
Serial.begin(115200);
initWiFi();
//iniciando MQTT , adeno client poderia ser substituido por qualquer outra nome pois este é uma classe
MQTT.setServer(BROKER_MQTT, SERVERPORT);
MQTT.setCallback(mqtt_callback);
ThingSpeak.begin(espClient);
}
void loop() {
VerificaConexoesWiFIEMQTT();
LerPubSensor();
MQTT.loop();
// delay (1800);
}
//Funções da WiFi
void VerificaConexoesWiFIEMQTT(void)
{
if (!MQTT.connected())
reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita
reconectWiFi(); //se não há conexão com o WiFI, a conexão é refeita
}
void initWiFi()
{
delay(10);
Serial.println(“——Conexao WI-FI——“);
Serial.print(“Conectando-se na rede: “);
Serial.println(SSID);
Serial.println(“Aguarde”);
reconectWiFi();
}
void reconectWiFi()
{
//se já está conectado a rede WI-FI, nada é feito.
//Caso contrário, são efetuadas tentativas de conexão
if (WiFi.status() == WL_CONNECTED)
return;
WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(“.”);
}
Serial.println();
Serial.print(“[STATUS] Conectado com sucesso na rede “);
Serial.print(SSID);
Serial.println(” IP obtido: “);
Serial.println(WiFi.localIP());
}
void mqtt_callback(char* topic, byte* payload, unsigned int length)
{
String msg;
for (int i = 0; i < length; i++)
{
char c = (char)payload[i];
msg += c;
}
Serial.println(msg);
char carray[msg.length() + 1];
msg.toCharArray(carray, sizeof(carray));
TempIdeal = atof(carray);
Serial.println("—————————————–");
Serial.print("Temperatura Ideal é: ");
Serial.print(TempIdeal);
Serial.println("\n—————————————–");
}
void reconnectMQTT()
{
while (!MQTT.connected())
{
Serial.print("Tentando Conectar ao Broker MQTT: ");
Serial.println(BROKER_MQTT);
if (MQTT.connect(USERNAME, MQTTUSER, MQTTSENHA))
{
Serial.println("[STATUS] Conectado com sucesso ao broker MQTT! ");
Serial.println("[STATUS] Se Inscrevendo no Topico: ");
MQTT.subscribe(TOPICO_SUBSCRIBE);
}
else
{
Serial.print("falhou, rc=");
Serial.print(MQTT.state());
Serial.println("[STATUS] Falha ao reconectar no broker.");
Serial.println("Havera nova tentatica de conexao em 2s");
delay(2000);
}
}
}
void LerPubSensor(void) {
float h = dht.readHumidity(); //ler humidade
float t = dht.readTemperature(); //ler temperatura
float t_f = (t * 9) / 5 + 32;//tranforma em Farenheit
double a = -42.379 + 2.04901523 * t_f + 10.14333127 * h – 0.22475541 * t_f * h
– 0.00683783 * pow(t_f, 2) – 0.05481717 * pow(h, 2) + 0.00122874 *
pow(t_f, 2) *
h + 0.000885282 * t_f * pow(h, 2) – 0.00000199 * pow(t_f, 2) *
pow(h, 2);
double ic = 0.5556 * ( a – 32);
char data1[8];
char data2[5];
// dtostrif converte um float para char
char *IC = dtostrf(ic, 5, 2, data1); //convertendo em para enviar
char *T = dtostrf(t, 4, 2, data2); ////convertendo em para enviar
Serial.println("[STATUS] Publicando no Topico: ");
Serial.println(TOPICO_PUBLISH_IC);
Serial.println("Indice de Calor = ");
Serial.println(IC);
MQTT.publish(TOPICO_PUBLISH_IC, IC);
Serial.println("[STATUS] Publicando no Topico: ");
Serial.println("Temperatura = ");
Serial.println(T);
MQTT.publish(TOPICO_PUBLISH_TEMP, T);
Serial.println("[STATUS] Temperatura enviada!");
Serial.println("—————————————–");
temperature = t;
humidity = h;
icalor = ic;
Serial.println("Umidade = ");
Serial.println(h);
Serial.println("—————————————–");
if (WiFi.status() == WL_CONNECTED)
{
ThingSpeak.setField( 1, temperature);
ThingSpeak.setField( 2, icalor);
ThingSpeak.setField( 3, humidity);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
}
else
{
reconectWiFi();
ThingSpeak.setField( 1, temperature);
ThingSpeak.setField( 2, icalor);
ThingSpeak.setField( 3, humidity);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
}
delay(60000);
Olá meu camarada, tudo bem?
Gostaria de saber como colocar a bomba ou válvula solenóide de 12V no relé de 5V?
Eu até tenho uma placa Arduino, porém, não tenho um Internet Shield. Como a minha mãe já está com 70 anos e nem sempre tem disposição para ir colocar água nas plantinhas dela gostaria de automatizar essa pequena tarefa usando um NodeMCU ESP8266.
Só nisso estou me enrolando.
Desde já agradeço pela sua atenção!
Bom dia, Maurício.
Depende do seu relé. Caso ele aguente uma carga de 12V, basta você jogar uma tensão de 5V na entrada dele, usando uma fonte por exemplo.
Abraços!
Diogo – Equipe MakerHero
Bom dia Pedro.
Pretendo utilizar esta aplicação “Planta IoT” como base para um projeto simples
que conecta alguns sensores na internet, estou usando um PIC para leitura e pretendo
conectar com o modulo ESP8266 12F via UART (RX – TX ).
Como sou novato nesta área, no código acima, a IDE citada, é Arduino?
Posso transferir o código de execução via UART direto do microcontrolador? ,
sem a necessidade do IDE, uma vez já desenvolvido o Firmware ? pretendo usar o modulo sem o conversor USB-RS232…
Tem algum caminho para acelerar meu aprendizado?
Grato.
Carlos.
Olá Carlos,
A IDE utilizada é Arduino. Creio que não seja possível utilizar com PIC.
O código também não servirá para PIC, mas você pode tomar a lógica do programa como base para seu programa em PIC.
A melhor forma é procurar tutoriais para programação de PIC e leitura de sensores com PIC.
Veja como programar PIC no tutorial:
https://www.makerhero.com/blog/como-utilizar-gravador-pic-pickit-3.html
Veja como utilizar ESP8266 com PIC no tutorial:
https://www.dobitaobyte.com.br/esp8266-com-pic/
A ligação seria a mesma caso usasse o arduino uno ?
Na válvula de vazão solenoide Água 12VDC
Rudyer, boa tarde.
Quanto ao acionamento do solenoide (circuito para acioná-lo) com Arduino UNO, você pode usar o mesmo circuito deste artigo sim.
Atenciosamente,
Pedro Bertoleti
Boa tarde!
Estou tentando aplicar esse projeto na minha escola estadual pública, gostaria de saber se vocês tem o fluxograma, desenho ou planta desse projeto, pelo que observei o código fonte está completo, mas fiquei com um pouco de dúvida no desenho, tipo a ligação dos componentes. Muito obrigado
Olá.
O conteúdo seria o que está no post mesmo. O mesmo possui o esquema elétrico.
Caso queira outra opção de planta IOT, nós temos um produto específico para isso: https://www.makerhero.com/produto/kit-plantinha-iot/. Ele acompanha os materiais e curso/tutorial para montar o projeto.
Att.
Vitor Mattos.
Suporte Técnico MakerHero.