Bichanos são, frequentemente, vistos como pets independentes. E não faltam motivos para isso! Eles cuidam da própria higiene, enterram suas necessidades e não precisam fazer caminhadas diárias. Entretanto, em algumas questões, os felinos precisam de ajuda. Uma delas é a hidratação.
Afinal, como fazer o gato beber água?
Nesse projeto, criamos um bebedouro que cria um fluxo de água corrente, evitando deixar água parada, o que é muito mais atrativo para os felinos, além de evitar que acumule lodo ou sujeira. E, como pode funcionar de maneira automática, é muito fácil de utilizar! Basta colocar a água e esperar o bichano se refrescar!
Esse projeto serve, também, para bebedouro de cachorro, mas será necessário fazer algumas modificações.
O objetivo do projeto é chamar a atenção do gato para ele se hidratar. Para isso, o bebedouro pode operar de 4 formas diferentes:
Você pode alternar entre os modos de operação. Mostrarei como fazer isso a seguir.
Após acionar a bomba de uma das formas citadas acima, o ESP8266 fecha o relé que aciona o circuito da bomba e faz a água jorrar.
Todos os materiais, com exceção das cases, podem ser comprados em nossa loja.
O circuito deve ser alimentado com uma fonte de 5V e 1A.
As partes foram impressas em PLA, mas podem ser impressas em ABS ou PETG. Os respectivos arquivos podem ser baixados por este link, que contém os arquivos editáveis (.ipt) e os arquivos para impressão (.stl). Imprima com as configurações da impressora que deseja.
Para compilar o código do bebedouro, são necessárias as seguintes bibliotecas:
Bebedouro.ino
/** * @file Bebedouro.ino * Criado por: Saulo Aislan * @brief Firmware para controlar o motor bomba do bebedouro para gato. * @version 0.1 * * @copyright Copyright (c) 2022 * */ #include <Arduino.h> #include <ESP8266WiFi.h> #include <ESPAsyncTCP.h> #include <ESPAsyncWebServer.h> #define PIN_MOTOR 4 // Pino D2 do Wemos const char* ssid = "Bebedouro"; // Nome da rede const char* password = "123456789"; // Senha da rede // AsyncWebServer objeto na porta 80 AsyncWebServer server(80); bool buttonStatus = false; // Habilitando ou não o botão na página bool motorStatus = false; // Status do motor bomba uint8_t paramMotorStatus = 0; uint8_t controlMode = 0; uint16_t interval = 60; // Intervalo de acionamento do motor no modo automático (timeControl) em minutos /* Prototipo da funcao */ void withOutControl(void); void controlManual(void); void timeControl(int interval); String processor(const String& var); /** * @brief Função que aciona a bomba, sem controle de tempo ou manual, acionamento constante */ void withOutControl(void){ digitalWrite(PIN_MOTOR, HIGH); buttonStatus = false; } /** * @brief Função para o controle manual da bomba, habilitando o botão na página */ void controlManual(void) { Serial.println("Controle Manual"); buttonStatus = true; } /** * @brief Função de acionamento por tempo do motor bomba * @param int Intervalo em minutos de desligada para ligada */ void timeControl(int i_interval){ i_interval = i_interval*60*1000; digitalWrite(PIN_MOTOR, LOW); delay(i_interval); digitalWrite(PIN_MOTOR, HIGH); delay(15000); // Tempo que vai permanecer ligada 15s } /** * @brief Função para o controle manual da bomba, * recebe o status recebido e aciona o motor bomba * @param AsyncWebServerRequest ponteiro para o request HTTP_GET */ void manualControl(AsyncWebServerRequest* request) { bool st; if (request->hasParam("st")) st = request->getParam("st")->value().toInt(); else st = 0; if(st){ digitalWrite(PIN_MOTOR, HIGH); Serial.println("Motor: ON"); request->send(200, "text/html", SendHTML()); } else { digitalWrite(PIN_MOTOR, LOW); Serial.println("Motor: OFF"); request->send(200, "text/html", SendHTML()); } } /** * @brief Função que cria a página (HTML) de configuração * @return String com o HTML da página */ String SendHTML(){ String ptr = "<!DOCTYPE html><html>"; ptr.concat(F("<head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">")); ptr.concat(F("<title>Bebedouro para Gato</title>")); ptr.concat(F("<style>html {font-family: Arial, Helvetica, sans-serif; display: inline-block; margin: 0px auto; text-align: center;}")); ptr.concat(F("body{margin: 0;font-size: 1rem; color: #1e4659;background-color: #f2f2f2;} h3 {color: #444444;margin-bottom: 50px;}")); ptr.concat(F(".topnav{overflow: hidden; background-color: #04448c; text-align: center; color: white;}")); ptr.concat(F("form{border-radius: 5px;border-radius: 5px;padding: 20px;}")); ptr.concat(F("input {width: 100%;padding: 12px 20px;margin: 8px 0;display: inline-block;border: 1px solid #ccc;border-radius: 4px;box-sizing: border-box;}")); ptr.concat(F(".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}")); ptr.concat(F(".button-on {background-color: #4caf50;}")); ptr.concat(F(".button-off {background-color: #f44336;}")); ptr.concat(F("table{border-collapse: collapse;} td{border: 1px solid #ffc107;padding:8px;}")); ptr.concat(F("</style></head>")); ptr.concat(F("<body><div class=\"topnav\"><h1>Bebedouro para Gato</h1></div>")); ptr.concat(F("<div><form name=\"formMode\"><div style=\"border: 1px solid #ffc107;\"><div style=\"background-color: #ffc107; padding: 10px; font-weight: bold;\"><label for=\"mode\">Modos de operação</label></div>")); ptr.concat(F("<table style=\"width: 100%;\"><tr><td style='width: 50%'><b>Modo atual:</b></td>")); if(paramMotorStatus == 0) { ptr.concat(F("<td>-</td></tr>")); } else if(paramMotorStatus == 1) { ptr.concat(F("<td>Ligada direto</td></tr>")); buttonStatus = false; } else if(paramMotorStatus == 2) { ptr.concat(F("<td>Acionamento por intervalo de tempo</td></tr>")); buttonStatus = false; } else if(paramMotorStatus == 3) { ptr.concat(F("<td>Acionamento manual</td></tr>")); buttonStatus = true; } else if(paramMotorStatus == 4) { ptr.concat(F("<td>Acionamento manual ou por intervalo de tempo</td></tr>")); buttonStatus = true; } ptr.concat(F("<tr><td colspan=\"2\"><b>Escolha o Modo de operação:</b></td></tr>")); ptr.concat(F("<tr><td colspan=\"2\"><select onchange=\"setmode()\" name=\"opMode\" id=\"mode\">")); ptr.concat(F("<option value=\"-\">-</option>")); ptr.concat(F("<option value=\"/mode?op=1\">Ligada</option>")); ptr.concat(F("<option value=\"/mode?op=2\">Por tempo</option>")); ptr.concat(F("<option value=\"/mode?op=3\">Manualmente</option>")); ptr.concat(F("<option value=\"/mode?op=4\">Por tempo e manualmente</option></select></td></tr></table></form></div>")); if(buttonStatus) { if(digitalRead(PIN_MOTOR) == LOW) { ptr.concat(F("<div><div style='background-color:#ffc107;padding: 10px;font-weight: bold;margin: auto;margin-bottom: 2%;width: 50%;'>Bebedouro: <span style='color: #f44336;'>Desligado</span></div><a class='button button-on' href=\"/bomba?st=1\">Ligar</a></div>")); } else { ptr.concat(F("<div><div style='background-color:#ffc107;padding: 10px;font-weight: bold;margin: auto;margin-bottom: 2%;width: 50%;'>Bebedouro: <span style='color: #4caf50;'>Ligado</span></div><a class='button button-off' href='/bomba?st=0'>Desligar</a></div>")); } } else { ptr.concat(F("<div><a class='button button-on' style='background-color:#c3c3c3;'> - </a></div>")); } ptr.concat(F("<script type=\"text/javascript\">function setmode(){")); ptr.concat(F("location=document.formMode.opMode.options[document.formMode.opMode.selectedIndex].value")); ptr.concat(F("}</script>")); ptr.concat(F("</body></html>")); return ptr; } /******************* Função em setup (setup) *********************/ void setup(){ Serial.begin(115200); pinMode(PIN_MOTOR, OUTPUT); Serial.print("Access Point…"); WiFi.softAP(ssid, password); IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); Serial.println(WiFi.localIP()); server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(200, "text/html", SendHTML()); }); server.on("/mode", HTTP_GET, [](AsyncWebServerRequest *request){ if (request->hasParam("op")) { paramMotorStatus = request->getParam("op")->value().toInt(); controlMode = paramMotorStatus; } else { paramMotorStatus = 0; } Serial.print("Modo: "); Serial.println(paramMotorStatus); request->send(200, "text/html", SendHTML()); }); server.on("/bomba", HTTP_GET, manualControl); // Start server server.begin(); } /******************* Função em loop (loop) *********************/ /** * @brief Máquina de estados para os modos de acionamento do motor bomba */ void loop(){ switch(controlMode){ case 1: withOutControl(); // Acionamento direto, motor ligado todo o tempo break; case 2: timeControl(interval); // Acionamento por tempo (minutos) break; case 3: controlManual(); // Acionamento manual break; case 4: // Caso 4 o motor poderá ser acionado manualmente e pelo tempo controlManual(); // Acionamento manual timeControl(interval); // Acionamento direto, motor ligado todo o tempo break; default: timeControl(30); // Acionamento por tempo (30 minutos) } }
Monte todo o circuito e bomba nas respectivas cases junto com o tubo como nas figuras abaixo, use cola quente para fixar melhor os componentes:
Coloque a bomba dentro do recipiente (algo como um pote de sorvete, por exemplo) e fixe, de alguma forma, a bomba no fundo do recipiente e o circuito na lateral de fora do recipiente para evitar contato com a água.
Ao ligar o bebedouro, ele irá criar uma rede como Access-Point com o nome de “Bebedouro”. Com um celular ou computador, acesse a rede criada e insira a senha que está no código na linha “const char* password“. Em seguida, clique em conectar.
Uma vez conectado à rede, acesse o IP: 192.168.4.1 para abrir a página de configuração. Ao acessa-lo, será aberta uma página como essa:
Os modos de operação podem ser selecionados através da página web de configuração na caixa de seleção “Escolha o Modo de operação”. Se o modo escolhido for o 3 ou o 4, o botão Ligar/Desligar irá aparecer para o acionamento manual.
Nesse tutorial, aprendemos a montar um bebedouro para ajudar seu amigo de pelos tomar água. Esse projeto é totalmente Open-source e você pode modificar o que quiser, adicionar ou remover componentes, conectar o bebedouro direto na sua rede local. Deixe sua imaginação fluir. Para mais material como este, continue acompanhando as postagens semanais do blog e não deixe de visitar nossa loja. Lá, você encontra todos os componentes necessários para desenvolver esse e muitos outros projetos!
Que a força estejam com vocês e até mais!
Referências utilizadas no artigo:
Tenha a Metodologia Eletrogate na sua Escola! Conheça nosso Programa de Robótica Educacional.
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!