O projeto Gardenino permite a automação da irrigação de plantações de pequeno porte, tais como hortas domésticas. Baseado em horários pré-definidos e na presença de água em um reservatório, realiza-se o acionamento do relé, que por sua vez liga a bomba para a irrigação da horta. Uma mensagem pelo twitter é enviada automaticamente com uma mensagem programada para informar ao produtor que a irrigação está ocorrendo.
O sistema consiste na utilização de uma bomba de aquário para irrigar, um relé para o seu acionamento periódico, um sensor ultra-sônico para verificação do nível da água para evitar o mau funcionamento da bomba e a utilização da placa NodeMCU para o processamento dos dados da periodicidade, verificação do nível da água, acionamento do relé da bomba e envio de mensagem acerca do estado da planta.
Projeto pelos alunos José Pereira e Diego Queiroz
Componentes
- Protoboard
É uma placa com furos e conexões condutoras para montagem de circuitos elétricos experimentais. A grande vantagem da placa de ensaio na montagem de circuitos eletrônicos é a facilidade de inserção de componentes, uma vez que não necessita soldagem. As placas variam de 800 furos até 6000 furos, tendo conexões verticais e horizontais.
- Fios
- NodeMCU
O NodeMCU é um kit de desenvolvimento que permite a programação de protótipos para a Internet das Coisas (IoT). Ele integra interfaces GPIO, 1-Wire, I2C, SPI, PWM, ADC, entre outros.
- Relé( srd-05vdc-sl-c )
O funcionamento do relé consiste quando uma corrente circula pela bobina, esta cria um campo magnético que atrai um ou uma série de contatos fechando ou abrindo circuitos. Ao cessar a corrente da bobina o campo magnético também cessa, fazendo com que os contatos voltem para a posição original.
- Sensor ultra-sônico HC-SR04
O sensor é capaz de medir distâncias de 2cm a 4m com ótima precisão. Este módulo possui um circuito pronto com emissor e receptor acoplados e 4 pinos (VCC, Trigger, ECHO, GND) para medição. Para realizar a medição é necessário alimentar o módulo e colocar o pino Trigger em nível alto por mais de 10us. Assim o sensor emitirá uma onda sonora que ao encontrar um obstáculo rebaterá de volta em direção ao módulo, sendo que o neste tempo de emissão e recebimento do sinal o pino ECHO ficará em nível alto. Logo o cálculo da distância pode ser feito de acordo com o tempo em que o pino ECHO permaneceu em nível alto após o pino Trigger ter sido colocado em nível alto.
- Bomba Submersa A-100 Vigo Ar
Bomba essencial para se obter um ambiente propício aos peixes dentro de tanques ou aquários, tendo como fatores preponderantes a economia de energia e o alto rendimento de vazão e oxigenação, sendo este fator importante na vida aquática. Melhora a qualidade da água de seu aquário. Bomba com vazão para até 100 litros por hora, recomendada para aquários até 30 litros. Pode ser usada dentro ou fora do aquário.
Montagem
Passo 1: Fixar a placa NodeMCU na protoboard.
Passo 2: Conectar o sensor ultra-sônico ao NodeMCU com a pinagem do Trigger no D1, do ECHO no D2, do GND no GND da placa e o VCC do ultra-sônico no VIN da placa, tudo de acordo com a imagem a baixo
Passo 3: Conectar o relé ao NodeMCU de acordo com a imagem a baixo.
Passo 4: Conectar a bomba ao relé (para simular usaremos um motor que tem o mesmo tipo de montagem para o seu funcionamento).
Imagem Real:
Máquina de Estados
A máquina de estado descreve a implementação do projeto Gardenino.O projeto Gardenino inicia pelo estado S0, onde ele se mantém quando se encontra fora da hora de irrigar e o nível do reservatório estiver bom (T0, S1). Se estiver fora da hora de irrigar e o nível do reservatório estiver baixo (T0,S0) ele irá para o estado S1 onde o sistema postará a seguinte mensagem no twitter: “Reservatório vazio!”.
Se der a hora de irrigar e o nível do reservatório estiver baixo (T1,S0) ele irá para o estado S2 onde enviará a seguinte mensagem no twitter: “Estou com sede e não tem água =(“, e se der a hora de irrigar e o nível do reservatório estiver bom (T1,S1) ele irá para o S3 onde o sistema postará uma outra mensagem ao twitter: “Oba! Água! *–*”, acionará a bomba de água pelo tempo delimitado em S3 e retornará para S0.
Estando no estado S1 ele poderá manter-se lá caso a situação (T0,S0) continue ou ir para o estado S2, caso der a hora de irrigar e continue o reservatório com nível de água baixo (T1,S0) onde o sistema postará uma mensagem no twitter: “Reservatório vazio!”, ou irá para o estado S3. Se der à hora de irrigar e já o reservatório estiver cheio deixando em um nível bom (T1,S1) o sistema irá postar uma mensagem no twitter: “Oba! Água! *–*”, acionará a bomba de água pelo tempo delimitado em S3 e retornará para S0.
Estando no estado S2 ele poderá manter-se lá caso a situação (T1,S0) continue ou ir para o estado S3. Se der a hora de irrigar e já tiverem enchido o reservatório deixando num nível bom (T1,S1), o sistema irá postar a seguinte mensagem no twitter: “Oba! Água! *–*”, acionará a bomba de água pelo tempo delimitado em S3 e retornará para S0.
Código
//Inclusão de bibliotecas utilizadas no projeto #include #include //definição das entradas e saídas utilizadas #define TRIGGER 5 #define ECHO 4 #define RELAY 15 //declaração das variáveis unsigned long tempocontrole=0; int s=1; // indica a situacao do sensor int t=0; int count=0; typedef enum{ S0, S1, S2, S3, DELAY } STATES; STATES estado = S0; char ssid[] = "JuniorBrowser"; // SSID da rede char pass[] = "junior29"; // Senha da rede // Variáveis usadas no recebimento e manipulação de pacotes NTP unsigned int localPort = 2390; IPAddress timeServerIP; const char* ntpServerName = "a.st1.ntp.br"; const int NTP_PACKET_SIZE = 48; byte packetBuffer[ NTP_PACKET_SIZE]; WiFiUDP udp; void setup() { //iniciando o Serial e as entradas/saidas Serial.begin(9600); pinMode(TRIGGER, OUTPUT); pinMode(ECHO, INPUT); pinMode(RELAY, OUTPUT); //Metodo de conexão a uma rede Wifi Serial.println("Conectando a "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi conectado"); Serial.println("IP: "); Serial.println(WiFi.localIP()); udp.begin(localPort); } //Metodo que recebe e trata os pacotes NTP unsigned long sendNTPpacket(IPAddress& address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; udp.beginPacket(address, 123); //NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); } //Função que consulta o tempo atual unsigned long gettempo(){ WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); delay(1000); int cb = udp.parsePacket(); while (!cb) { Serial.println("no packet yet"); } udp.read(packetBuffer, NTP_PACKET_SIZE); unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); unsigned long secsSince1900 = highWord <=tempocontrole){ tempocontrole = gettempo()+14400;// Aqui é definido o intervalo de tempo entre regagens em segundos(14400s = 4h) return 1; } else{ return 0; } } //Função que calcula a distancia captada pelo sensor long sensor(){ long duration, distance; digitalWrite(TRIGGER, LOW); delayMicroseconds(2); digitalWrite(TRIGGER, HIGH); delayMicroseconds(10); digitalWrite(TRIGGER, LOW); duration = pulseIn(ECHO, HIGH); distance = (duration/2) / 29.1; Serial.print("Centimeter: "); Serial.println(distance); return distance; } void loop() { //Definição do estado inicial do automato e do tempo controle // importante observar que a maquina irá começar a contar o tempo do intervalo a partir do momento em que for ativada Serial.print("Estado: S"); Serial.println(estado); unsigned long secsSince1900 = gettempo(); if (tempocontrole==0){ tempocontrole= gettempo(); } t =comparatempo(secsSince1900, tempocontrole); if(t==1){ tempocontrole=tempocontrole+14400; //define o tempo de intervalo em segundos } long distance = sensor(); if(distance < 10) { //distancia em centimetros que indica o limite do reservatório. count++; if(count==2){// validação que evita leituras erradas do sensor digitalWrite(RELAY, HIGH); delay(4000); //Tempo em ms que a bomba deve bombear a agua. count=0; s=1; } } else{ count=0; digitalWrite(RELAY, LOW); s=0; } // Definição da maquina de estados e de sua função de transição Serial.print("T: "); Serial.println(t); Serial.print("S: "); Serial.println(s); switch(estado){ case S0: if((t==0)&&(s==1)){ estado=S0; break; } else if((t==0)&&(s==0)){ estado=S2; break; } else if((t==1)&&(s==0)){ estado=S1; break; } else if((t==1)&&(s==1)){ estado=S3; break; } else{estado=S0; } break; case S1: Serial.println("Reservatorio vazio! "); if(s==1){ estado=S3; break; } else{ estado=S1; } break; case S2: Serial.println("Estou com sede e nao tem agua =( "); if((t==0)&&(s==1)){ estado=S0; break; } else if((t==0)&&(s==0)){ break; } else if((t==1)&&(s==0)){ estado=S1; break; } else if((t==1)&&(s==1)){ estado=S3; break; } else{estado=S0; } break; case S3: Serial.println("Oba! Agua! *--* "); //regar //resetar estado=S0; break; case DELAY: //delay(3000); estado=S0; break; default: break; delay(30); } Serial.println("Estado final: "); Serial.println(estado); }