(A versão em inglês desse post pode ser encontrada aqui em meu blog: ArduFamBot ou em sua versão original no site do Instructables.com)
Neste tutorial desenvolveremos um controlador eletrônico (o “ArduFarmBot”) que a partir da captura de dados provenientes de uma plantação de tomates (vulgo tomateiro), tais como temperatura, umidade relativa do ar, luminosidade e umidade do solo, decidirá autonomamente a quantidade certa (e quando) o plantio deve receber calor e irrigação (água + nutrientes). Além disso, o ArduFarmBot permitirá a intervenção manual de um operador (tanto de forma local quanto remotamente via Internet), a fim de controlar o acionamento de uma bomba de água e de uma lâmpada elétrica (esta última para ser usada na geração de calor para as plantas).
Em suma, o ArduFarmBot receberá como entrada:
- Sensores (dados analógicos):
- Temperatura
- Umidade do ar
- Luminosidade
- Umidade do solo
E fornecerá como saídas:
- Atuadores:
- Relé para controle de bomba
- Relé para controlo da lâmpada
- Sinalização (dados digitais):
- Visual e sonoro para indicação de status / erro
- Visual de Estado da bomba
- Visual para o estado da lâmpada
- Display dos dados
- Todos os dados analógicos e digitais devem estar disponíveis para avaliação instantânea
- Armazenamento de dados
- Dados históricos deve ser de armazenamento remotamente na internet e opcionalmente também localmente (via cartão de memória).
O diagrama de blocos abaixo mostra os principais componentes do projeto.
O vídeo abaixo descreve os principais elementos utilizados no primeiro protótipo de laboratório usado para testes:
Neste segundo vídeo, mostramos como os comandos funcionarão em modo local e remotamente via Web page:
PARTE 1 – ESTAÇÃO LOCAL
O projeto será dividido em 3 partes:
- Estação local
- Estação Remota ( ESP8266, Thingspeak, criação da página web em HTML/CSS/JS, etc)
- Uso e Acompanhamento do ArduFarmBot em uma plantação real.
Aqui nesta primeira parte, vamos explorar a estação local, desenvolvendo o HW e o SW para trabalhar com os sensores, atuadores, aprendendo como exibir dados, etc.
Abaixo o diagrama em blocos simplificado da versão 1 da estação local:
1.1: Lista de Materiais

Os principais componentes para o ArduFarmBot são (valores em USD):
Itens gerais (cerca de $ 37,00):
- Arduino Nano – ( $ 7,50)
- Sensor de Temperatura e Umidade DHT22 – ($ 3,66)
- Sensor Luminosidade – AD-018 módulo photo-resistor. , ou equivalente – ($ 0,71)
- Soil Moisture Sensor – ($ 1,99) (Opcionalmente, pode ser do tipo “DIY” vide capítulo 1.5)
- LCD 20X4 I2C ($ 13,99)
- Botões (2X) – ($ 0.90)
- LEDs (3x) ($ 0.20)
- Esp8266 Serial WiFi Transceiver Module Esp-01 – ($ 5,96) – (Para ser usado na parte 2)
- Buzzer (ativo) – Ky-12 ou equivalente ($ 0,60) – (Para ser usado na parte 2)
- 2 X 5v Módulo de Relé ($ 11,60)
- Fios de salto (S1.00)
- 10 Kohm resistor – ($ 0,03)
- 2.2 Kohm resistor – ($ 0,03)
- 1.0 Kohm resistor – ($ 0,03)
- 220 ohm resistor – ($ 0,03)
Opção 1 com Nano Shield (em torno de US $ 15,00):
- Shield Arduino Nano ( “Funduino”) – ($ 7,28)
- Teclado de membrana (4 teclas) – ($ 6,65)
- Placa de ensaio Mini ($ 1,00) (Para ser usado na parte 2)
Opção 2 sem o Shield para o Nano- (cerca de US $ 4,00):
- 3.3V Voltage Regulator LD33V ou equivalente ($ 1.20) (Para ser usado na parte 2)
- Capacitor – electrolítico 10uF (2X) para ser utilizado com LD33V – ($ 0,10)
- Placa de ensaio – Média – (US $ 2,50)
1.2: Instalação, programação e teste dos sensores
O primeiro sensor a ser testado e instalado é o DHT 22, um sensor digital de humidade relativa do ar e temperatura. Ele usa internamente um sensor capacitivo de humidade e um termistor para medir o ar circundante, gerando um sinal digital em sua saída de dados.
De acordo com a sua folha de dados(Datasheet), o sensor deve ser alimentado entre 3.3V e 5V (algumas especificações falam em até 6V max). Ele trabalha a partir de -40 a + 80 graus centígraods (algumas especs falam em + 125 ° C) com uma precisão de +/- 0,5 ° C de temperatura e +/-2% de umidade relativa. É importante ter em mente que o seu (“sencing period”) é em média de dois segundo (tempo mínimo entre leituras).
O site da Adafruit fornece uma série de informações sobre ambos, DHT22 e seu irmão DHT11. Para mais detalhes, visite a página: Tutorial DHT22 / 11 .
O DHT22 tem 4 pinos (de frente para o sensor, o pino 1 é o mais esquerda):
- VCC (3 a 5V)
- saída de dados
- Não conectado
- GND (Terra)
Uma vez que normalmente você usará o sensor em distâncias inferiores a 20m, um resistor de 10K deve ser conectado entre os pinos de dados e o VCC. O pino de saída deve ser conectado ao pino D5 do Arduino (veja o diagrama acima).
Uma vez que o sensor é instalado fisicamente no Arduino, baixe a biblioteca DHT a partir do repositório de programas: Adafruit github e a instale junto as outras bibliotecas de seu IDE (ambiente de desenvolvimento de programas do Arduino).
Uma vez que você recarregue o IDE, a biblioteca para o sensor de DHT deverá aparecer como instalada. Execute o código abaixo para verificar se tudo está funcionando OK:
/**************************************************************** * DHT Sensor - Setup and Test * Based on the original code written by ladyada, public domain * MJRoBot 21Aug16 ****************************************************************/ // Include DHT Library #include // Sensor defiitions #define DHTPIN 5 // DHT data pin connected to Arduino pin 5 #define DHTTYPE DHT22 // DHT 22 (if your sensor is the DHT 11, only change this line by: #define DHTTYPE DHT11) // Variables to be used by Sensor float tempDHT; // on the final program we will use int insteady of float. No need for high precision measurements float humDHT; float hic; // only used here for testing purposes // Initialize the DHT sensor DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); Serial.println("DHT 22 Setup & Test"); dht.begin(); } void loop() { // Wait a few seconds between measurements. delay(2000); //Read temperature and humidity values from DHT sensor: tempDHT = dht.readTemperature(); humDHT = dht.readHumidity(); // Check if any reads failed and exit early (to try again). if (isnan(humDHT) || isnan(tempDHT)) { Serial.println("Failed to read from DHT sensor!"); return; } // Compute heat index in Celsius (isFahreheit = false) float hic = dht.computeHeatIndex(tempDHT, humDHT, false); // Show measurements at Serial monitor: Serial.print(" Temp DHT ==> "); Serial.print(tempDHT); Serial.print("oC Hum DHT ==> "); Serial.print(humDHT); Serial.print("% Heat index: "); Serial.print(hic); Serial.println(" oC "); }
Sensor de Luminosidade (LDR)
Com o DHT funcionando, é hora de instalar e testar o sensor de luminosidade. Para isso, podemos usar um simples LDR (Resistor variável com luz). Basicamente, o que se deve fazer é criar um divisor de tensão, onde um dos resistores é o LDR e o outro um fixo, sendo o “ponto médio do divisor” conectado a uma entrada analógica do Arduino. Desta forma, variando-se a luz, a resistência LDR variará proporcionalmente e por conseguinte , a tensão no ponto do meio do divisor também vai variar.
Em nosso projeto, por facilidade de instalação, usaremos um módulo LDR barato (KY18) o qual já possui o divisor de tensão integrado. O módulo tem 3 pinos ( “S” para dados; “+” para VCC e “-” para GND). O pino “S” será ligado ao pino analógico Ao do Arduino. O “+” e “-” pinos devem ser ligadas, respectivamente, a 5 V e GND. Se o consumo de energia é uma preocupação, o “+” pode ser conectado a uma das saídas digitais do Arduino, que deverá ser colocada em “HIGH” alguns milésimos de segundo antes de se ler a tensão no pino A0, retornando para “LOW” depois disso.
A função getLumen (LDR_PIN) lerá algumas vezes a saída do sensor (poderia ser de 3, 10 ou mais, você decide o que é melhor para o seu caso) calculando a média dessas leituras (isso para diminuir o risco que uma uma única leitura seja na verdade um ruído). Além disso, uma vez que a saída do conversor analógico digital (ADC) interno do Arduino será um número de 0 a 1023, deveremos “mapear” esses valores, a fim de obter os seguintes resultados como porcentagens:
- “Dark Full” ==> saída ADC: 1023 ==> 0%
- “Full Light” ==> saída ADC: 0 ==> 100%
Abaixo a função em C++:
int getLumen(int anaPin)
{
int anaValue = 0;
for(int i = 0; i < 10; i++) // read sensor 10X ang get the average
{
anaValue += analogRead(anaPin);
delay(50);
}
anaValue = anaValue/10; //Light under 300; Dark over 800
anaValue = map(anaValue, 1023, 0, 0, 100); //LDRDark:0 ==> light 100%
return anaValue;
}
Sensor de Humidade de solo (Higrômetro)
Um sensor para testar a umidade do solo (ou higrômetro) é muito simples. Ele possui o mesmo princípio de funcionamento que o sensor de luminosidade. Um divisor de tensão será usado como ponto de entrada de uma das portas analógicas do Arduino, mas em vez de um resistor que varie com luz, usaremos um que varie com a humidade do solo. O circuito básico é muito simples e pode ser visto abaixo.
Infelizmente, a realidade é um pouco mais complexa do que isso (mas não muito). Um simples sensor como o descrito funcionaría bem, mas não por muito tempo. O problema é que ter uma corrente constante fluindo através dos eletrodos em uma única direção gerará corrosão sobre eles, devido ao efeito de eletrólise. Uma maneira de resolver isso é conectar-se os eletrodos não diretamente ao VCC e terra, mas à portas digitais do Arduino (por exemplo VCC a D7 e GND a D6 como mostrado acima). Ao fazer isso, em primeiro lugar o sensor seria “energizado” apenas quando a leitura realmente ocorresse e a direção da corrente sobre as sondas poderia ser alternada, eliminando o efeito da eletrólise.
Abaixo um código de teste simples, baseada no post “How to: Soil Moisture Measurement?” :
/**************************************************** Soil Moisture Sensor Test ****************************************************/ #define SOIL_MOIST_PIN 1 // used for Soil Moisture Sensor Input #define SMS_VCC 7 #define SMS_GND 6 int soilMoist; // analogical value obtained from sensor void setup () { Serial.begin(9600); pinMode(SMS_VCC,OUTPUT); pinMode(SMS_GND,OUTPUT); } void loop (void) { soilMoist = getSoilMoisture(); Serial.print("Soil Moisture: ") Serial.print(soilMoist) Serial.println(" %") } /*************************************************** * Capture soil Moisture data ****************************************************/ int getSoilMoisture() { int anaValue; digitalWrite(SMS_VCC,LOW); // drive a current through the divider in one direction digitalWrite(SMS_GND,HIGH); delay(1000); // wait a moment for capacitance effects to settle anaValue=analogRead(SOIL_MOIST_PIN); digitalWrite(SMS_VCC,HIGH); // reverse the current digitalWrite(SMS_GND,LOW); delay(1000); // give as much time in 'reverse' as in 'forward' digitalWrite(SMS_VCC,LOW); // stop the current anaValue = map(anaValue, 1023, 0, 0, 100); return anaValue; }
Nos testes preliminares para o desenvolvimento do SW, usaremos um potenciômetro de 10K ohms entre + 5V e GND, simulando a saída analógica do sensor de umidade. Por agora isso será suficiente, uma vez que iremos discutir este sensor mais profundamente no capítulo 1.5.
Agora que todas as rotinas para os sensores estão prontas e testadas individualmente, criaremos uma função específica onde todos os sensores serão lidos ao mesmo tempo:
void readSensors(void)
{
tempDHT = dht.readTemperature(); //Read temperature and humidity values from DHT sensor:
humDHT = dht.readHumidity();
lumen = getLumen(LDR_PIN);
soilMoist = getSoilMoist();
}
Procure fazer alguns testes com os sensores, como cobrir o LDR com um pano ou a mão, colocar o dedo diretamente no DHT, etc. , e veja o range de variação dos dados Use o Serial Monitor como saída para leitura dos dados.
Abaixo o código completo:
1.3: Adicionando um Display LCD para monitoramento local
É claro que nem sempre será possível usar o monitor serial para analisar a leitura de nossos sensores. Assim, para monitorização local, será adicionado um LCD ao projecto. A escolha ficou com um módulo LCD de 4 linhas de 20 caracteres cada, que permite configuração de contraste através de um potenciômetro instalado em sua parte traseira e comunicação I2C.
Para comunicação serial do tipo I2C com o Arduino, o LCD possui 4 pinos:
- GND
- VCC
- SDA
- SCL
O pino SDA será ligado em nosso caso a entrada A4 do Arduino e o pino SCL ao A5, como mostrado no diagrama acima.
Uma vez que os 4 fios são conectados, a próxima coisa a fazer é baixar e instalar a biblioteca I2C para o seu display LCD, a qual pode ser usada tanto para um display do tipo 20 x 4 quanto para o 16 x 2 (2 linhas de 16 caracteres):
https://github.com/fdebrabander/Arduino-LiquidCrys…
Execute em seu Arduino o programa exemplo “Hello World” que vem incluído com a biblioteca, mudando o set-up padrão (16 × 2) para o nosso 20 x 4. O endereço default “0x27” funcionou bem em meu caso:
#include
#include
// Set the LCD address to 0x27 for a 20 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);
void setup()
{
// initialize the LCD
lcd.begin();
// Turn on the blacklight and print a message.
lcd.backlight();
lcd.print("Hello, world!");
}
void loop()
{
// Do nothing here...
}
Nota: Se você não tem certeza sobre o seu endereço I2C de seu LCD, uma simples varredura em seu HW irá mostrar se existem dispositivos I2C conectados, se estão funcionando corretamente e em qual seu endereço. O código para fazer o scanner pode ser encontrado aqui: http://playground.arduino.cc/Main/I2cScanner
Como exemplo, em meu caso ao executar o programa obtive no Monitor Serial :
Scanning..
I2C device found at address 0x27 !
done
Vamos incorporar as funções, definições específicas, etc. referentes ao display em nosso último código, para que possamos assim ver as leituras de sensores em LCD:
1.4: Atuadores e botões para controle local
Atuadores
Até agora, pudemos obter os dados gerados pelos sensores e exibi-los no monitor serial e no LCD. É hora de fazer alguma coisa com esses dados. Vamos pensar sobre os atuadores!
Como discutido na introdução, nosso objetivo final aqui é cuidar de uma plantação de tomate. Com os dados fornecidos por sensores, saberemos a temperatura e umidade do ar, a luminosidade e o mais importante quão “seco” se encontra o solo onde está a plantação. Com esses dados em mãos, o nosso programa deverá decidir se seria necessário irrigar a plantação, ligando uma bomba elétrica para bombear água ou uma lâmpada elétrica para fornecer o calor necessário para a cultura. Para isso, usaremos pequenos Módulos de %V para relés para a ativação da bomba e lâmpada. O diagrama do Módulo de Relé pode ser visto abaixo.
Módulos de relés podem apresentar várias nomenclaturas para seus pinos de entrada, tais como: “G”, “V”, “S” ou “S”, “-“, “+” ou “In”, “Vcc”, ” GND “, etc.
Olhando para o diagrama, dependendo do seu módulo de relé, é necessário conectar:
- Arduino 5V ==> “V” ou “+” ou “Vcc”
- Arduino GND ==> “G” ou “-” ou “GND”
- Arduino OUT ==> “S” ou “In” (em nosso caso o “Arduino OUT” deve ser D10 para Bomba e D8 para Lamp)
Normalmente você vai encontrará como saída, 3 pinos: “NA” (ou NO), “Ref”, e “NF ” (ou NC), que são:” Normal Open ou Aberto”, Referência e” Normal Closed ou Fechado “. Nós usaremos o par: NA e Ref (centro). No diagrama acima, “NA” é o terminal para conectar-se ao positivo da fonte de alimentação (12 ou 9VDC para Bomba e 127 ou 220VAC para a lâmpada, conforme seu caso). O “Ref” será conectado à bomba ou da lâmpada, como mostrado na figura acima. Para saber mais sobre relés, visite: “ Controlling Power with Arduino “.
Juntamente com os relés, opcionalmente 2 LEDs podem ser utilizados para mostrar se os relés estão ligados ou desligados:
- LED vermelho: Bomba
- LED verde: Lâmpada
Para o teste é ótimo se ter os LEDs instalados em seu BreadBord, mas para o projeto final você pode eliminar-los, reduzindo a carga na saída do pino do Arduino (mesmo porque os módulos de relés em geral possuem um pequeno LED vermelho incorporado). Trabalhando juntos, eles “puxarão” uma quantidade razoável de corrente do Arduino (você poderá perceber uma redução no brilho no LCD). Outra alternativa é utilizar saídas digitais diferentes para os LEDs e relés, o que claro reduz a disponibilidade de pinos para outros usos.
Botões
Com base nas leituras dos sensores, um operador poderia decidir controlar manualmente a bomba e / ou lâmpada. Para isso, dois botões do tipo “push-button” serão incorporados ao projeto. Eles vão trabalhar em um modo de “alternância” (“Toggle”): Se um atuador está “ON”, pressionando-se o botão, ele passa a “OFF” e vice-versa. A lógica do botão será “normalmente fechada”, o que significa que a entrada do Arduino estará constantemente em “HIGH” (será usado um resistor de pull-up interno do Arduino). Pressionando-se o botão, uma estado “LOW” será aplicada ao pino do Arduino.
Da mesma maneira que fizemos com os sensores, a toda vez que executemos o loop () , uma função readLocalCmd () será executada. Esta função lerá o estado dos botões, atualizando o status de variáveis correspondentes aos atuadores (pumpSatus e lampStatus). Note que a função debounce(pin) é chamado ao invés de um digitalRead (PIN). Isso é para evitar falsas leituras do botão. Se você quiser saber mais sobre debouncing, consulte: Debouncing Tutorial.
/****************************************************************
* Read local commands (Pump and Lamp buttons are normally "HIGH"):
****************************************************************/
void readLocalCmd()
{
int digiValue = debounce(PUMP_ON);
if (!digiValue)
{
pumpStatus = !pumpStatus;
showDataLCD();
aplyCmd();
}
digiValue = debounce(LAMP_ON);
if (!digiValue)
{
lampStatus = !lampStatus;
showDataLCD();
aplyCmd();
}
}
No caso em que um botão é pressionado, uma outra função será chamada: aplyCmd () . E como o nome diz, ela aplicará o comando correspondente, ligando ou desligando os atuadores:
/***************************************************
* Receive Commands and act on actuators
****************************************************/
void aplyCmd()
{
if (pumpStatus == 1) digitalWrite(PUMP_PIN, HIGH);
if (pumpStatus == 0) digitalWrite(PUMP_PIN, LOW);
if (lampStatus == 1) digitalWrite(LAMP_PIN, HIGH);
if (lampStatus == 0) digitalWrite(LAMP_PIN, LOW);
}
Considerações sobre o “Timming” do programa
Quando pensamos sobre as tarefas a serem executadas, podemos agrupar-las em:
- Ler sensores
- ler botões (comando local)
- Atuar sobre Bomba / Lâmpada
- Exibir todos os dados
Percebemos que o “timming” de quando deveríamos realizar tais tarefas não são necessariamente os mesmos. Por exemplo, para ler os dados de temperatura e de umidade do DHT 22, temos de esperar pelo menos 2 segundos entre medidas, mas diferenças em minutos não farão grandes diferenças. Para o sensor de umidade do solo, quanto menos medições fizermos, melhor (evita corrosão das pontas de prova devido a electrolise) e por último mas não menos importante, a luz do dia não vai variar instantaneamente. Mas quando pensamos sobre os atuadores, logo que se pressione um botão, gostaríamos (e possivelmente precisaríamos) de uma reacção rápida.
Assim, a última instrução antes do final do setup () será a inicialização de um temporizador principal usando a função” millis () ” em vez de espalhar um monte de delays()’s pelo código:
startTiming = millis (); // Iniciar o “relógio do programa”
Durante o loop(), a primeira instrução será a de incrementar a variável startTiming com uma temporização real.
elapsedTime = millis () – startTiming ;
Depois disso, leremos o estado dos botões usando a função readLocalCmd ( ). Esta leitura irá acontecer toda a vez que o programa execute o loop ().
readLocalCmd (); // Ler estado dos botões locais
Em relação aos sensores, fazemos a leitura a cada 5 segundos, por exemplo, e não em cada loop:
if (elapsedTime > (5000))
{
readSensors();
printData();
startTiming = millis();
}
Abaixo o código completo para testar a nossa “Estação local”:
1.5: Aprofundando com o sensor de humidade do solo
Você poderá pular esta etapa se quiser, mas acho que seria interessante aprofundar-nos um pouco mais no estudo deste simples, mas crítico componente para o projeto. Como brevemente explicado anteriormente, o “Soil Moisture Sensor”, ou higrômetro, é um simples “divisor de tensão resistivo”.
Sabendo disso, podemos construir um sensor muito simples usando duas sondas metálicas como pregos galvanizados, pinos ou parafusos. Abaixo você poderá ver o que criei utilizando-se de materiais simples: dois parafusos ligados a dois fios (preto / vermelho). Depois em um segundo sensor, foram adicionados um terceiro fio e um resistor.
Conforme descrito no item 1.2, “R1” é a “resistência do solo” (não é o melhor termo científico, mas está OK). Utilizando-se de 3 amostras de solo em diferentes estados de umidade, podemos medir o valor esse valor R1 utilisando-se de um multímetro comum e corrente, como mostrado na foto abaixo:
- Seco: R1 = >20 Kohm (aprox)
- Húmido: R1 = 4K para 6Kohm (aprox.)
- Molhado: R1 = >1kohm (aprox)
R2 é a resistência física usada para completar o Divisor de Tensão (Vamos começar com um potenciômetro 10K para set-up). Calculando o Vin na porta A1 do Arduino , proporcionalmente à VCC, chegaríamos a equação:
Vin = R2 / (R1 + R2) * VCC ou Vin / VCC = 10K / (R1 + 10K) * 100 [%]
Usando os valores reais medidos com o multímetro, podemos antecipar que os resultados devem ser:
-
Seco: 10K / 30K *100 ==> <30%
- Húmido: 10K / 15K * 100 ==> ~ 67%
- Molhado: 10K / 11K * 100 ==> > 90%
Fazendo as conexões com o Arduino e executando o código desenvolvido até agora, teremos como resultado:
- Seco: 13%
- Húmido: 62%
- Molhado: 85%
Obviamente devido a que mudei a posição dos sensores na terra R1 mudará um pouco, além de que o VCC também não é exatamente 5V, os valores práticos são um pouco diversos do teórico. Mas como o que realmente importa é o intervalo de variação e não o valor absoluto, o resultado foi muito satisfatório.
O sensor será utilizado em 3 estados distintos:
- Molhado (Wet): Mais de 60% (não ligaremos a bomba de maneira nenhuma)
- Húmido: Entre 40 e 60% (Onde queremos trabalhar) e
- Seco: Abaixo de 30% (precisaremos ligar a bomba para aumentar a umidade)
Como você pode observar, utilizando-se R2 como 10K ohm funcionou bem, o que nos leva a substituir o potenciômetro por um resistor fixo em nosso “Soil Moisture Sensor”.
Outra coisa que se percebe quando testamos os sensores, é que ao fazer as medições vai se acumulando um pequeno erro nas leituras. Isto porque o sensor também se comportará como um “capacitor”. Ao se “energizar” o sensor para uma única captura de dados precisamos esperar um tempo razoável, mesmo depois de cortar o fornecimento de energia para que o mesmo possa se “descarregar “. Revertendo a corrente ajudará, mas não é suficiente.
Os gráficos acima mostram 2 conjuntos de medições:
- Linha azul : Um ciclo de 10 medições a cada 1 segundo entre amostras e com 1 minuto entre os ciclos
- Linha Laranja : Um ciclo de 10 medições a cada 1 segundo entre amostras e com 5 minutos entre ciclos
Com intervalos de 1 segundo, cada nova amostra será aumentado significativamente. Esperar 1 minuto após desligar a energia irá diminuir o “efeito de tensão de armazenamento”, mas não vai eliminá-la por completo sendo que um valor residual será adicionado à próxima medição. O aumento do intervalo de ciclos para 5 minutos, por exemplo, praticamente eliminará o erro.
Com base nos resultados acima, o código final não deve tomar amostras com uma frequência de menos do que 10 min.
O vídeo abaixo, mostra os testes efetuados com o sensor:
1.6: Compatibilizando as operações automática e manual

Como pudemos ver na última etapa, precisaremos esperar tempos maiores entre as medições do sensor de umidade, por exemplo: 10minutos. Isto está Ok para as nossas necessidades automáticas, mas para a operação manual não vamos querer “esperar” dezenas de minutos olhando para o ArduFarmBot para saber se um valor medido pelo sensor mudou. Para solucionar o problema, introduziremos um terceiro botão de controle em nosso projeto, o qual será usado para exibir os dados reais e instantâneos dos sensores a qualquer momento, independente das programações de leituras automáticas.
Para o Push-Button, usaremos o pino digital D17 (o mesmo que está compartilhado com a entrada analógica A3). Introduziremos também um “LED de aviso” (o amarelo na foto) conectada ao pino 13. Este LED acenderá toda a vez em que os sensores estão sendo atualizados. Abaixo a nova função readLocalCmd() :
/**************************************************************** * Read local commands (Pump and Lamp buttons are normally "HIGH"): ****************************************************************/ void readLocalCmd() { int digiValue = debounce(PUMP_ON); if (!digiValue) { pumpStatus = !pumpStatus; showDataLCD(); aplyCmd(); } digiValue = debounce(LAMP_ON); if (!digiValue) { lampStatus = !lampStatus; showDataLCD(); aplyCmd(); } digiValue = debounce(SENSORS_READ); if (!digiValue) { digitalWrite(YELLOW_LED, HIGH); lcd.setCursor (0,0); lcd.print("< Updating Sensors >"); readSensors(); digitalWrite(YELLOW_LED, LOW); } }
Outro ponto a considerar, é a introdução de um segundo “Soil Moisture Sensor” (higrômetro). Em nosso projeto final utilizaremos 2 sensores em pontos diferentes da plantação. Nós usaremos a média das leitura para decidir quando se deve ligar a bomba, por exemplo.
O “VCC e GND” dos sensores serão o mesmo (D7 e D6 respectivamente) e usaremos a entrada A2 do Arduino para o segundo sensor. Se a area da plantação é pequena não justificando 2 sensores, somente o valor lido em A1 será considerado pelo SW. (Isto deve ser informado na variável correspondente na area de set-up do SW).
// to be used by SM Sensor
int soilMoist;
int soilMoistAlert = 0;
int DRY_SOIL = 30;
int WET_SOIL = 60;
int numSM = 1; // “numSM” defines number of moisture sensors that are connected
int numSamplesSMS = 1; // “numSamplesSMS” defines number of samples of each reading cycle
O número de amostras de cada ciclo também será definido por uma variável específica: “numSamplesSMS”. Em princípio apenas uma leitura é suficiente, levando-se em consideração que as leituras que fazemos em um curto espaço de tempo introduzirão erros devido ao efeito de capacitância. Se você começar a ver erros na leitura, talvez sejam necessárias tomar amostras extras.
Abaixo a nova função para o “Soil Moisture Sensor”:
/*************************************************** * Capture soil Moisture data ****************************************************/ int getSoilMoist() { int i = 0; int anaValue1 = 0; int anaValue2 = 0; for(i = 0; i < numSamplesSMS; i++) // "numSamplesSMS" defines number of samples of each reading cycle { digitalWrite(SMS_VCC,LOW); // drive a current through the divider in one direction digitalWrite(SMS_GND,HIGH); delay(500); // wait a moment for capacitance effects to settle anaValue1 += analogRead(SOIL_MOIST_1_PIN); delay(500); // wait a moment for ADC settle-up anaValue2 += analogRead(SOIL_MOIST_2_PIN); digitalWrite(SMS_VCC,HIGH); // reverse the current digitalWrite(SMS_GND,LOW); delay(1000); // give as much time in 'reverse' as in 'forward' digitalWrite(SMS_VCC,LOW); // stop the current }
O diagrama abaixo mostra as conexões completas para a estação local de controle
1.7: It’s show time!
Neste ponto, já temos todo o HW no lugar e quase todos os elementos de SW desenvolvidos. O que falta agora é a “inteligência”, que permitirá ao nosso sistema realmente executar a tarefa de irrigar a plantação automaticamente! Para isto, precisaremos adicionar alguns “neurônios” ao nosso cérebro!
Como discutido anteriormente, definiremos o intervalo inicial onde os sensores irão trabalhar. Esses valores deverão ser alterados mais tarde a partir de resultados de testes reias na plantação:
Umidade do solo:
- Molhado (Wet): Mais de 60% (não ligaremos a bomba de maneira nenhuma)
- Húmido: Entre 40 e 60% (Onde queremos trabalhar) e
- Seco: Abaixo de 30% (precisaremos ligar a bomba para aumentar a umidade)
Temperatura:
- Frio: Abaixo de 15oC (Ligar Luz / Calor *)
- Confortável: entre 20 oC e 25 oC
- Calor: Mais que 25 ° C (não vire-a luz / calor)
Leve:
- Escuro (noite): Abaixo de 40% (não ligar bomba)
- Luz (dia): Mais de 40%
(*) Você poderá opcionalmente testar aqui as novas luzes LED para vegetais hidropônicos . Estas lâmpadas de LED podem ser utilizadas tanto para ajudar o crescimento mais rápido devido a luzes de frequências especiais como também para fornecer calor em caso de baixa temperatura.
Você deverá ter em mente que cada tipo de semente possui uma faixa ideal de temperatura na qual ela crescerá mais rápidamente. Por exemplo, para os Tomates o tempo mínimo para as sementes germinarem será de 6 dias em temperaturas entre 20 e 25 oC, aumentando para temperaturas superiores ou inferiores a esta faixa:
- Temperatura: graus (oC): 10 15 20 25 30 35
- Tempo para germinação (dias): 43 14 8 6 6 9
Você pode verificar mais informações sobre esta relação (temp / dias de germinação) aqui: O efeito da temperatura do solo na germinação de sementes
Tendo em mãos estas 4 leitura (temperatura, umidade, Soil Moisture and luz), podemos criar uma matriz que definirá como queremos que os nossos tomates crescem:
Então, tomemos nossas variáveis e definamos algumas novas valores:
Para ser utilizado pelo sensor DHT:
- int tempDHT;
- int HOT_TEMP = 25;
- int COLD_TEMP = 15;
Para ser usado por sensor LDR:
- lumen int;
- int DARK_LIGHT = 40;
Para ser usado pelo higrômetro:
- int soilMoist;
- int DRY_SOIL = 40;
- int WET_SOIL = 60;
Com base nas definições acima, pensemos sobre algumas premissas-chave:
- Se é durante o dia (lumen > DARK_LIGHT) e o solo está SECO (soilMoist < DRY_SOIL) ==> BOMBA = ON
- Se é durante a noite (lumen < DARK_LIGHT) e o solo está SECO (soilMoist < DRY_SOIL) ==> BOMBA = OFF (Tomates não gostam de receber água durante a noite)
- Se estiver frio (tempDHT <COLD_TEMP) ==> LAMPADA = ON
- Se estiver frio (tempDHT <COLD_TEMP) e solo muito húmido (soilMoist > WET_SOIL) ==> LAMP = OFF (para proteger a raiz)
Nesta primeira parte do projeto, vamos mantê-lo simples e não exploraremos todas as combinações possíveis e o papel da humidade do ar na equação. Explorar uma combinação mais complexa de sensores na 3º parte deste projeto, quando aplicaremos o ArduFarmBot em uma plantação real.
O Código :
Criaremos uma nova função, que baseado na leitura dos sensores, lidará automaticamente com os atuadores (ligar / desligar a bomba e lâmpada): AutoControlPlantation (). Esta função mostrada abaixo, será chamada em cada ciclo de leituras dos sensores:
void loop()
{
// Start timer for measurements
elapsedTime = millis()-startTiming;
readLocalCmd(); //Read local button status
showDataLCD();
if (elapsedTime > (sampleTimingSeconds*1000))
{
readSensors();
autoControlPlantation();
startTiming = millis();
}
}
A função terá 2 tarefas principais:
- Controle de bomba
- Controle da lâmpada
O segmento de controle da bomba utilizará uma nova variável: ” soilMoistAlert “.
//--------------------------------- PUMP ------//
if (soilMoist < DRY_SOIL && lumen > DARK_LIGHT)
{
if (soilMoistAlert == HIGH)
{
soilMoistAlert = LOW;
turnPumpOn();
}
else soilMoistAlert = HIGH;
}
else soilMoistAlert = LOW;
Esta variável será utilizada para evitar um “falso verdadeiro”. Então por exemplo, se tivermos um verdadeiro no resultado do teste: soilMoist <DRY_SOIL e que não seja durante a noite (lumen> DARK_LIGHT), não ligaremos imediatamente na bomba, mas ao invés disso, esperaremos o próximo ciclo verificando se o ” solo está muito seco “. Se o resultado for um “sim” (obtendo um “verdadeiro” como resposta duas vezes), somente aí a função turnPumpOn() será chamada:
/***************************************************
* TurnPumOn
****************************************************/
void turnPumpOn()
{
digitalWrite(PUMP_PIN, HIGH);
pumpStatus = 1;
showDataLCD();
delay (timePumpOn*1000);
digitalWrite(PUMP_PIN, LOW);
pumpStatus = 0;
showDataLCD();
}
A bomba deverá permanecer ligada por um determinado período de tempo, definido pela variável: ” timePumpOn” em segundos.
Note que também mudaremos a função que exibe dados no LCD criando um 3o. estado:
- “0”: Bomba OFF (pumpStatus = 0; e soilMoistAlert = 0;)
- “X”: Bomba em alerta (pumpStatus = 0; e soilMoistAlert = 1;)
- “1”: Bomba ON (pumpStatus = 1; e soilMoistAlert = 0;)
lcd.print("Pump: ");
if (soilMoistAlert == 1) lcd.print ("X");
else lcd.print(pumpStatus);
O mesmo princípio será aplicado ao controle da lâmpada, onde uma “baixa temperatura” será o “trigger” para acionar a lâmpada desde que o solo não esteja muito molhado”. Abaixoa função completa: autoControlPlantation ():
/*************************************************** * Automatically Control the Plantation based on sensors reading ****************************************************/ void autoControlPlantation() { //--------------------------------- PUMP ------// if (soilMoist < DRY_SOIL && lumen > DARK_LIGHT) { if (soilMoistAlert == HIGH) { soilMoistAlert = LOW; turnPumpOn(); } else soilMoistAlert = HIGH; } else soilMoistAlert = LOW; //--------------------------------- HEAT ------// if (tempDHT < COLD_TEMP && soilMoist < WET_SOIL) { if (tempLowAlert == HIGH) { tempLowAlert = LOW; digitalWrite(LAMP_PIN, HIGH); lampStatus = 1; } else tempLowAlert = HIGH; } else { tempLowAlert = LOW; digitalWrite(LAMP_PIN, LOW); lampStatus = 0; } }
Neste ponto, o ArduFarmBot esta totalmente funcional em termos de HW e SW e já poderia ser instalado em uma plantação para testes. O código completo pode ser encontrado abaixo:
1.8: Small Form Factor (colocando tudo na “caixinha”)
Uma vez que possuímos nosso protótipo funcional, vamos montar-lo de uma forma melhor, usando-se um “Shield” para o Arduino Nano (no caso, um fabricado pela “Funduino”) e uma caixa plástica, o que ajudará nos testes externos. A grande vantagem de se usar um shield para o Nano, é que cada componente fica melhor montado reduzindo os maus contatos e ruídos, além da facilidade de se ter todos os componentes principais reunidos em uma pequena caixa de plástico.
Se você estiver usando o DHT isolado (sem ser em um módulo), você adicione um resistor de 10K entre VCC e Signal. Se você estiver usando um módulo sensor, a resistência já se encontra incluído. Para este novo teste usarei o módulo DHT11 que tenho disponível. O resultado para o nosso propósito é o mesmo (apenas não se esqueça de alterar a linha no código para definir o sensor apropriado que você irá usar: #define DHTTYPE DHT11).
Faça 4 furos na caixa de plástico para a instalação do LCD (eu o deixei dentro da caixa).
Faça furos laterais na caixa para que que você possa acessar os sensores, ter acesso ao Nano (seja para a fonte de alimentação externa ou atualizações de SW) e ligar os atuadores (Bomba / Lampada) nas saídas de relés
Note que para os botões de controle, usei aqui um teclado do tipo membrana de 4 teclas “1 × 4 Key Matrix Membrane Switch”.
Você pode decidir a melhor maneira de fixar os componentes na caixa. Eu pessoalmente, gosto desse fixador removível da 3M para facilitar a instalação (veja as foto).
1.9: Testes funcionais em laboratório
Uma vez que tudo está fixada em seu devido lugar e o SW carregado, vamos fazer alguns testes funcionais que simulem diferentes condições de sensores, a fim de se verificar que tudo esteja bem ligado:
Com luz e temperatura normais, introduzir o higrômetro em um copo com amostra de solo húmido. Observe a foto 1 (Temp é 22oC;. Soil Hum é de 85% e luz é de 80%). Nada deve acontecer. Pump e Lamp devem ser OFF ( “0”).
Mantendo-se a mesma luz e temperatura, passemos a sonda para o copo com amostra de solo seco. Na foto 2, você pode observar que a bomba foi ligada (Primeiro aparecerá o “X” e depois o “1” durante algum tempo, tal como definido no programa).
Agora, como mostrado na foto 3, o LDR foi coberto com um pano preto e a luminosidade decresceu para 19%. Neste caso, apesar do fato de que o solo esteja seco, a bomba não ligará, porque o ArduFarmBot entenderá que é à noite.
Na foto 4, colocaremos gelo no fundo da nossa caixa, junto ao sensor DHT. A temperatura desceu a 12oC e a lâmpada foi ligada.
E por último, na foto 5 manteremos o gelo, mas mudaremos a sonda novamente para a amostra de solo húmido. Neste caso apesar do fato de estar frio, de acordo com a matriz, a lâmpada permanece desligada.
1.10: “Test Drive”: Regando um tomateiro com o ArduFarmBot
Para os primeiros testes reias, liguei uma bomba elétrica que tinha disponível (no projeto final a bomba será uma pequena bomba DC de 9V). Este primeiro teste é só para ver como o projeto vai funcionar, então não se preocupam com as gotas que você vai ver no vídeo ao lado).
1.11: O ArduFarmBot em acção
Com base em tudo o que nós aprendemos aqui, o passo agora será colocar o ArduFarmBot para controlar sua plantação verdadeira de tomate. Com base nesta experiência real, calibraremos e definiremos melhor os sensores e parâmetros do projeto. As fotos aqui dão uma idéia da sequência da preparação da terra e a introdução das sementes. Essa parte do projeto está a cargo de nosso “Chef” Maurício! Todos os detalhes dos testes reais serão explorados em na 3a. e última parte do projeto.
O filme abaixo mostra o ArduFarmBot em ação:
Agora é só torcer para que tudo de certo e possamos ter uma grande salada no final do projeto!!!! Salut! 😉
1.12: Parte 1 Conclusão
Se você gostou do projeto, não deixe de ver a segunda parte de nosso projeto: ArduFarmBot: Part 2 – “Estação Remota” – IoT, que mostrará a conexão com a internet e sua aplicação na plantação de tomate.
Os arquivos e documentos podem ser encontrados aqui : ArduFarmBot GitHub
Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica, do IoT e dos robôs!
Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook
Este projeto também está disponível em formato Kindle:
Saludos desde el sur del mundo! 😉
Um abraço e até o próximo post!
Obrigado
Marcelo e Maurício
Obrigado Marcelo !!! Muito bom e bem detalhado !!!
CurtirCurtir
PARABÉNS Marcelo! seu Blog é muito bom, venho trabalhando com projetos na formação de professores de Ciências, e montei um KIT chamado LMEC (Laboratório Móvel de Ensino de Ciências), com foco no ESTUDO da ÁGUA, ENERGIA e POLUÇÃO (solo, água e ar). Seus projetos são perfeitos para o módulo do Estudo da Poluição. Envio para você o link do vídeo institucional do projeto, infelizmente não obtive até o momento financiamento para disponibilizar de forma gratuita para as escolas.
Acesse o link https://www.youtube.com/watch?v=OGJKyhYWx1g
CurtirCurtido por 1 pessoa
Muito obrigado, amigo Jeronimo! Seu trabalho é fantástico!!!! 🙂
CurtirCurtir
Hello Marcelo,
I got a error with ‘DHT” does not name a type. How can I solve this problem?
Thanks
Vitt
/* DHT11*/
#include “DHT.h”
#define DHTPIN D3
#define DHTTYPE DHT11
DHT.dht(DHTPIN, DHTTYPE11); <=========
float hum = 0;
float temp = 0;
exit status 1
'DHT' does not name a type
CurtirCurtir
Do you have the DHT library installed?
CurtirCurtir
Cara desculpa a pergunta idiota mas qual caixa plastica voce usou? Tem o link dela? 🙂
CurtirCurtir
Oi Marcos. Eu comprei aqui no Chile “Casa & Ideas”. Eles devem trazer da China.
CurtirCurtir
Parabéns cara! Seu projeto está sensacional. Eu só faria algumas pequenas modificações:
– talvez seja mais interessante medir a luz em lux do que em %. Uma forma de fazer isso pode ser encontrada no site https://www.allaboutcircuits.com/projects/design-a-luxmeter-using-a-light-dependent-resistor/
Lux não é o ideal para medições de luz para crescimento de plantas, mas é um indicativo.
– valeria a pena você investir uma grana a mais em um medidor de umidade do solo bom por capacitância como o VH400 da vegetronix e correlacionar os valores encontrados pelo seu medidor.
Abraço
CurtirCurtir
Oi Gabriel, obrigado.
A idéia original de se utilizar o LDR era mais para saber se era dia ou noite, não importando muito seu valor. Eu creio que o ideal mesmo seria aproveitar a conexão com a internet e obter a hora local desde lá (como fiz isso no projeto:
https://mjrobot.org/2017/03/17/iot-feito-simples-estacao-meteorologica-domestica-com-nodemcu-e-oled/
O LDR poderia ainda ser utilizado como um feedback para confirmar que a lampada acendeu.
Quanto ao sensor de umidade do solo eu tenho um do tipo capacitivo instalado no projeto: (https://www.dfrobot.com/wiki/index.php/Capacitive_Soil_Moisture_Sensor_SKU:SEN01933).
Mas sinceramente, ainda prefiro o que fiz com parafusos. Foi o que melhor se adptou.
Um abraço
Marcelo
CurtirCurtir
Entendi Marcelo. Com relação ao sensor de umidade, eu fiz um parecido com o seu e fiquei decepcionado por ter oxidado super rápido e por fazer leituras inconstantes e sem sentido (estava fazendo leituras a cada 30 segundos). Vou utilizar sua técnica de medir a cada 5 minutos e usar sua estratégia para ver se oxida mais lentamente.
Você sabe me dizer se esse sensor que você projetou pode ser enterrado para fazer medições da zona radicular das plantas? Esse da dfrobot por capacitância parece que não pode ser enterrado. Aproveito para dizer que seu blog é o melhor que encontrei em português para eletrônica e internet das coisas. Parabéns pelo trabalho e continue postando.
CurtirCurtido por 1 pessoa
Oi Gabriel, obrigado! Essa é a idéia, trocar informacões, principalmente em português. Eu em geral escrevo meus posts em inglês primeiro e os publico no Instructables.com e no Hackster.io em seguida (em no maximo 1 ou 2 dias) traduzo para o portugues neste blog. Decidi deixar a lingua principal de meu Blog em portugues porque achei poucos sites em nossa lingua onde encontrar informacoes sobre eletronica.
O sensor resistivo que construí, usa parafusos galvanizados o que ajuda a não oxidar tão rápido e fazer poucas medidas é importante, como vpce escreveu. Tenho usado o mesmo sensor por vários meses sem problemas. Não tem problema enterrar o sensor resistivo, mas isole a parte de cima (por exemplo, faça uma envoltória com cola quente ou use fita isolante, etc.) deixe só as hastes e enterre o sensor a medida da umidade será entre os eletrodos.
Voce estuda agronomia?
Um abraço
Marcelo
CurtirCurtir
Eu comecei a te seguir no Instructables estes dias. =)
Então, eu fiz engenharia ambiental (não sei nada de agronomia) e entrei nesse mundo de programação e eletrônica faz alguns meses. Na real deu na telha de automatizar a minha horta de casa porque eu sou um ser humano irresponsável e esqueço de irrigar e acabo por matar minhas plantas. Hahahaha. Acabou por crescer o projeto e agora por coincidência estou querendo fazer algo parecido com o ArduFarmBot.
Cara é triste ver que a gente tem pouca coisa boa em português e quando tem, não é movimentado.
Aproveito para agradecer o seu tutorial sobre como utilizar o ESP8266 como um “wifi shield”. Procurei em um monte de lugar, cada um fala para fazer uma coisa e alguns não deram certo. O seu está muito bem detalhado e consegui fazer funcionar.
Abraço
CurtirCurtir
Projeto muito bom! Gostei…parabéns!
CurtirCurtido por 1 pessoa
Muito legal, creio que tem potencial bem legal para experimentos de campo em pesquisa agropecuária. Uma agricultura de precisão em pequena escala.
CurtirCurtir
Obrigado Renato. Se alguém da Embrapa se interessar, pode contar com meu projeto. Dou mais detalhes se necessário com o maior prazer.
Abração
CurtirCurtido por 1 pessoa