Leitura da Umidade do Solo

Introdução
Ter plantas em casa sempre nos traz uma sensação de estar próximo da natureza, mas hoje em dia acaba se tornando algo difícil devido à rotina diária de trabalho e estudo, fazendo com que muitas vezes nos esqueçamos de regar as plantas de casa, e muitas vezes deixando o seu solo secar. Portanto seria muito bom se tivéssemos algum método de visualizar se o solo de nossas plantas está precisando ser irrigado ou não.
Neste tutorial aprenderemos como utilizar o sensor de solo capacitivo para realizar a leitura da umidade do solo das plantas, e como aproveitar essa informação para nos informar se devemos regar ou não a planta.
Lista de Materiais
Sensor Capacitivo Vs. Resistivo
Existem basicamente dois modelos de sensores de solo: os resistivos e os capacitivos. Os sensores de solo resistivos identificam a mudança de resistência elétrica no solo: quanto maior a concentração de água, maior será sua condutividade, logo menor será sua resistência, como no GIF abaixo, por exemplo. Entretanto, esse funcionamento vem com um custo. Por ter de identificar a condutividade do solo, este tipo de sensor possui terminais metálicos expostos que tendem a oxidar com o tempo. Essa oxidação não só pode influenciar na leitura do próprio sensor, como também pode ser desagradável para as plantas, pois a oxidação poderá alterar o pH do solo.

Fonte: Last Minute Engineers
Já os sensores de solo capacitivos leem a concentração de água no solo através da variação na sua zona dielétrica. Para entendermos melhor o funcionamento deste tipo de sensor, vamos nos lembrar do que um capacitor é formado. Os capacitores possuem dois terminais e entre esses terminais há um material dielétrico (como na imagem a seguir), que é responsável por armazenar energia elétrica em um campo elétrico.

Fonte: Learn Sparkfun
Para o sensor de umidade de solo, o solo úmido opera como o material dielétrico do sensor, que possui dois terminais que não são expostos. Para realizar uma leitura, o sensor cria um pequeno campo elétrico ao seu redor, como no exemplo da imagem abaixo, que utiliza um sensor touch capacitivo como exemplo.

Fonte: Embedded
Com esse campo elétrico, o solo começa a carregar como um capacitor. Em seguida pode-se determinar a capacitância do ambiente em função do tempo de carga. Como essa capacitância está diretamente relacionada à quantidade de água, obtém-se facilmente que um solo mais úmido resulta em uma tensão menor ou um tempo de carga maior.
Primeiras Leituras do Sensor
Primeiramente iremos coletar uma média de leituras do sensor, para que possamos calibrá-lo corretamente no segundo projeto. Para isso, é recomendado realizar duas baterias de teste, uma com o solo completamente seco e uma com o solo com a concentração máxima de água desejada. Assim saberemos quais são os valores máximo e mínimo do sensor no vaso da planta. Para facilitar essa bateria de testes, é melhor realizar primeiro a coleta da média em solo seco, e então irrigá-lo para medir o solo úmido.
Circuito
Para coletar a média de leituras do sensor, monte o circuito a seguir.

Código
Com o circuito montado, carregue o exemplo a seguir para a sua placa.
/*******************************************************************************
* Sensor de Umidade de Solo Capacitivo - Coletor de Media de Leituras (v1.0)
*
* Este codigo realiza um calculo de media de leitura de uma determinada
* quantidade de amostras, para facilitar na calibracao futura do sensor.
* O ideal e iniciar o teste com o sensor ja inserido na terra e em duas
* circunstancias distintas, com o solo seco e com o solo com a concentracao
* maxima de agua desejada. Talvez seja melhor comecar os testes com o solo seco,
* para facilitar a obtencao dos valores.
*
* Copyright 2020 RoboCore.
* Escrito por Giovanni de Castro (08/10/2020).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version (<https://www.gnu.org/licenses/>).
*******************************************************************************/
//Declaracao do pino conectado ao sensor
const int PINO_SENSOR = A0;
//Declaracao da variavel que armazena as leituras do sensor
int leitura_sensor = 0;
//Declaracao da variavel que armazena a quantidade de amostras que serao coletadas
const int NUMERO_AMOSTRAS = 100;
//Altere a variavel acima com a quantidade de amostras que deseja coletar para o calculo da media
//Declaracao da variavel que armazena a soma das leituras
long somatoria = 0;
void setup() {
Serial.begin(9600);
Serial.println(" ---*****--- ");
Serial.println("Sensor de Umidade de Solo Capacitivo - Primeiros Passos");
Serial.println("Coletando media de leituras do sensor...");
Serial.println("");
//Configuracao do pino conectado ao sensor como uma entrada
pinMode(PINO_SENSOR, INPUT);
//Realiza a leitura do sensor de acordo com a variavel "NUMERO_AMOSTRAS"
for(int i = 1; i <= NUMERO_AMOSTRAS; i++){
leitura_sensor = analogRead(PINO_SENSOR); //Le o sensor
somatoria = somatoria + leitura_sensor; //Soma a variavel "somatoria" a leitura atual do sensor com seu valor anterior
float tensao = leitura_sensor*(5.0/1023); //Converte a leitura para tensao para referencia
Serial.print("Amostra ");
Serial.print(i);
Serial.print(" | ");
Serial.print("Leitura: ");
Serial.print(leitura_sensor);
Serial.print(" | ");
Serial.print("Tensao: ");
Serial.println(tensao);
delay(1000);
}
//Calcula a media das leituras utilizando a variavel "somatoria" e a variavel "NUMERO_AMOSTRAS"
int media = somatoria / NUMERO_AMOSTRAS;
Serial.println("");
Serial.print("Media obtida: ");
Serial.println(media);
}
void loop() {
//Nao ha nada para executar aqui
}
Entendendo o Código
O código inicia com a declaração das variáveis PINO_SENSOR
e leitura_sensor
, que são responsáveis por armazenar o pino em que o sensor está conectado e a leitura do sensor, respectivamente. A variável NUMERO_AMOSTRAS
, por sua vez, armazena a quantidade de amostras de leitura do sensor que iremos coletar para calcular a média. Para finalizar as declarações globais do código, temos a variável somatoria
, que é responsável por receber os valores das leituras do sensor somados para o cálculo da média.
xxxxxxxxxx
//Declaracao do pino conectado ao sensor
const int PINO_SENSOR = A0;
//Declaracao da variavel que armazena as leituras do sensor
int leitura_sensor = 0;
//Declaracao da variavel que armazena a quantidade de amostras que serao coletadas
const int NUMERO_AMOSTRAS = 100;
//Altere a variavel acima com a quantidade de amostras que deseja coletar para o calculo da media
//Declaracao da variavel que armazena a soma das leituras
long somatoria = 0;
A rotina de configuração do código é onde coletamos a média de leituras do sensor, e começamos inicializando o monitor serial com a velocidade de 9600 bps para que possamos visualizar as leituras e a média coletada. Em seguida, configuramos o pino conectado ao sensor como uma entrada do sistema e entramos no laço for(int i = 1; i <= NUMERO_AMOSTRAS; i++)
, que irá executar a lógica dentro dele enquanto a variável auxiliar i
for menor que o valor configurado na variável NUMERO_AMOSTRAS
.
Dentro do laço "for", a leitura analógica do pino conectado ao sensor é atribuída à variável leitura_sensor
. Feito isso, a variável somatoria
possui seu valor anterior somado à leitura do sensor armazenada na variável leitura_sensor
. Para finalizar a lógica deste laço, apenas convertemos o valor lido pelo sensor para um valor entre 0 e 5 V para que possamos ter como referência a tensão fornecida pelo sensor e entendermos um pouco melhor o seu funcionamento.
xxxxxxxxxx
Serial.begin(9600);
Serial.println(" ---*****--- ");
Serial.println("Sensor de Umidade de Solo Capacitivo - Primeiros Passos");
Serial.println("Coletando media de leituras do sensor...");
Serial.println("");
//Configuracao do pino conectado ao sensor como uma entrada
pinMode(PINO_SENSOR, INPUT);
//Realiza a leitura do sensor de acordo com a variavel "NUMERO_AMOSTRAS"
for(int i = 1; i <= NUMERO_AMOSTRAS; i++){
leitura_sensor = analogRead(PINO_SENSOR); //Le o sensor
somatoria = somatoria + leitura_sensor; //Soma a variavel "somatoria" a leitura atual do sensor com seu valor anterior
float tensao = leitura_sensor*(5.0/1023); //Converte a leitura para tensao para referencia
Serial.print("Amostra ");
Serial.print(i);
Serial.print(" | ");
Serial.print("Leitura: ");
Serial.print(leitura_sensor);
Serial.print(" | ");
Serial.print("Tensao: ");
Serial.println(tensao);
delay(1000);
}
Assim que o laço "for" é finalizado, calculamos a média das leituras feitas, declarando a variável media
, e já a atribuindo ao valor da variável somatoria
dividido pelo valor da variável NUMERO AMOSTRAS
.
xxxxxxxxxx
//Calcula a media das leituras utilizando a variavel "somatoria" e a variavel "NUMERO_AMOSTRAS"
int media = somatoria / NUMERO_AMOSTRAS;
Serial.println("");
Serial.print("Media obtida: ");
Serial.println(media);
O Que Deve Acontecer
Após carregar o código para a placa, abra o monitor serial em 9600 bps e aguarde alguns instantes para que as amostras sejam coletadas, e a média calculada. Vale lembrar que deve-se iniciar o código com o sensor já inserido no solo.
Para a bateria em solo seco, você deve obter um valor muito próximo ao nível alto do sensor, como na imagem à esquerda a seguir. Para a bateria em solo úmido, você deve obter um valor próximo ao nível baixo do sensor, como na imagem à direita a seguir.


É interessante observar com esses resultados que com o solo úmido a tensão lida no sensor é menor do que a tensão lida no solo seco, e isso se deve ao fato que a capacitância do solo úmido é maior que a capacitância com o solo seco, o que prova o que vimos anteriormente.
Vale lembrar que os resultados que você vai obter nas baterias de teste com o seu sensor podem e devem ser diferentes dos valores obtidos acima, pois as condições de teste irão mudar.
Projeto Monitoramento de Umidade
Para este projeto iremos utilizar o LCD com interface I2C para nos alertar quando a umidade do solo estiver abaixo do valor desejado para a planta.
Circuito
Para este projeto, monte o circuito a seguir.

Código
Com o circuito montado, carregue o código a seguir para a sua placa. As variáveis VALOR_MINIMO
e VALOR_MAXIMO
foram declaradas inicialmente com os valores que obtivemos em testes internos, portanto altere-as de acordo com os valores que você obteve em seus testes. Além disso, a variável CONCENTRACAO_MINIMA
foi declarada com um valor padrão de 30% de concentração de água, mas você pode alterá-la para o valor que desejar e que seja melhor para a sua planta.
xxxxxxxxxx
/*******************************************************************************
* Sensor de Umidade de Solo Capacitivo - Monitoramento de Umidade de Solo (v1.0)
*
* Este codigo coleta a leitura do sensor, e a mapeia entre 0 e 100 % utilizando
* as medias maxima e minima coletadas no codigo anterior. Essa leitura mapeada e
* entao exibida no LCD, e e entao, caso a leitura seja menor que a concentracao
* minima desejada, o LCD irá nos alertar que e necessario irrigar o solo.
*
* Copyright 2020 RoboCore.
* Escrito por Giovanni de Castro (08/10/2020).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version (<https://www.gnu.org/licenses/>).
*******************************************************************************/
//Inclusao das bibliotecas
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//Criacao do objeto "lcd" com o endereco I2C, e o numero de linhas e colunas
LiquidCrystal_I2C lcd(0x20, 16, 2);
//Altere o endereco I2C acima de acordo com o que foi configurado no DIP switch do seu modulo
//Declaracao do pino conectado ao sensor
const int PINO_SENSOR = A0;
//Declaracao da variavel que armazena as leituras do sensor
int leitura_sensor = 0;
//Declaracao das variaveis que armazenam os valores de calibracao
const int VALOR_MAXIMO = 634; //Valor com solo seco
const int VALOR_MINIMO = 304; //Valor com solo umido
//Altere o valor das variaveis acima de acordo com as medias obtidas atraves do codigo do projeto anterior
//Declaracao da variavel que armazena a concentracao minima desejada
const int CONCENTRACAO_MINIMA = 30;
//Altere a variavel acima com o valor ideal para a sua planta
void setup() {
//Inicia o display LCD com o backlight aceso, e exibindo o nome do projeto
lcd.begin();
lcd.backlight();
lcd.print("Monitoramento de");
lcd.setCursor(0,1);
lcd.print("Umidade de Solo.");
delay(5000);
lcd.clear();
//Define o pino conectado ao sensor como uma entrada do sistema
pinMode(PINO_SENSOR, INPUT);
}
void loop() {
//Realiza a leitura do sensor, a mapeia entre 0 e 100 % e exibe o valor no LCD
leitura_sensor = analogRead(PINO_SENSOR);
leitura_sensor = map(leitura_sensor, VALOR_MINIMO, VALOR_MAXIMO, 100, 0);
lcd.print("Umidade = ");
lcd.print(leitura_sensor);
lcd.print(" %");
//Verifica se a leitura esta abaixo da concetracao minima desejada
if(leitura_sensor < 30){ //Se sim, informamos pelo LCD que precisa irrigar
lcd.setCursor(0,1);
lcd.print("Precisa Irrigar!");
lcd.noBacklight();
delay(500);
lcd.backlight();
delay(500);
} else { //Caso contrario, apenas esperamos 5 segundos para a proxima leitura
delay(5000);
}
lcd.clear(); //Limpa o LCD para atualizacao
}
Entendendo o Código
Nas configurações globais deste código, começamos incluindo as bibliotecas "Wire" e "LiquidCrystal_I2C" que nos ajudarão a controlar o display LCD com interface I2C, e então criamos o objeto lcd
pela biblioteca "LiquidCrystal_I2C", com o endereço 0x27 (lembre-se que o endereço I2C do módulo irá variar de acordo com a configuração do DIP switch e de seu lote, portanto altere esse valor se precisar) e o número de colunas e linhas do display (16 x 2). Em seguida, criamos as variáveis PINO_SENSOR
e leitura_sensor
, que armazenam o pino que está conectado ao sensor e a leitura obtida no sensor, respectivamente. Por fim, temos a declaração das variáveis VALOR_MAXIMO
e VALOR_MINIMO
, que armazenam as médias máxima e mínima obtidas no código anterior. Além disso, também declaramos a variável CONCENTRACAO_MINIMA
, que recebe o valor mínimo de concentração de água no solo desejado, e a princípio mantemos esse valor como 30, pois ele tende a ser um valor bom para maioria das plantas, mas altere-o de acordo com o que é ideal para a sua planta e para o seu ambiente.
xxxxxxxxxx
//Inclusao das bibliotecas
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//Criacao do objeto "lcd" com o endereco I2C, e o numero de linhas e colunas
LiquidCrystal_I2C lcd(0x27, 16, 2);
//Declaracao do pino conectado ao sensor
const int PINO_SENSOR = A0;
//Declaracao da variavel que armazena as leituras do sensor
int leitura_sensor = 0;
//Declaracao das variaveis que armazenam os valores de calibracao
const int VALOR_MAXIMO = 634; //Valor com solo seco
const int VALOR_MINIMO = 314; //Valor com solo umido
//Altere o valor das variaveis acima de acordo com as medias obtidas atraves do codigo do projeto anterior
//Declaracao da variavel que armazena a concentracao minima desejada
const int CONCENTRACAO_MINIMA = 30;
//Altere a variavel acima com o valor ideal para a sua planta
Na rotina de configurações do código, iniciamos o display LCD através do comando lcd.begin()
, e então exibimos o cabeçalho do código nele. Em seguida, apenas configuramos o pino conectado ao sensor como uma entrada do sistema, graças ao comando pinMode(PINO_SENSOR, INPUT)
.
xxxxxxxxxx
//Inicia o display LCD com o backlight aceso, e exibindo o nome do projeto
lcd.begin();
lcd.backlight();
lcd.print("Monitoramento de");
lcd.setCursor(0,1);
lcd.print("Umidade de Solo.");
delay(5000);
lcd.clear();
//Define o pino conectado ao sensor como uma entrada do sistema
pinMode(PINO_SENSOR, INPUT);
A repetição do código consiste na atribuição da leitura analógica do pino conectado ao sensor à variável leitura_sensor
utilizando o comando leitura_sensor = analogRead(PINO_SENSOR)
, e então mapeamos essa leitura entre 0 e 100 % usando o comando leitura_sensor = map(leitura_sensor, VALOR_MINIMO, VALOR_MAXIMO, 100, 0)
, de acordo com os valores configurados nas variáveis VALOR_MINIMO
e VALOR_MAXIMO
. Feito isso, exibimos o valor no display LCD, e então o verificamos através da condição if(leitura_sensor < CONCENTRACAO_MINIMA)
se a leitura mapeada do sensor está abaixo do valor configurado na variável CONCENTRACAO_MINIMA
. Se essa condição for verdadeira, nós enviamos um alerta no display LCD e piscamos o seu backlight para chamar atenção. Porém, se a condição for falsa, apenas aguardamos 5 segundos para executar a repetição novamente. Por fim, limpamos o display LCD através da função lcd.clear()
.
xxxxxxxxxx
//Realiza a leitura do sensor, a mapeia entre 0 e 100 % e exibe o valor no LCD
leitura_sensor = analogRead(PINO_SENSOR);
leitura_sensor = map(leitura_sensor, VALOR_MINIMO, VALOR_MAXIMO, 100, 0);
lcd.print("Umidade = ");
lcd.print(leitura_sensor);
lcd.print(" %");
//Verifica se a leitura esta abaixo da concetracao minima desejada
if(leitura_sensor < 30){ //Se sim, informamos pelo LCD que precisa irrigar
lcd.setCursor(0,1);
lcd.print("Precisa Irrigar!");
lcd.noBacklight();
delay(500);
lcd.backlight();
delay(500);
} else { //Caso contrario, apenas esperamos 5 segundos para a proxima leitura
delay(5000);
}
lcd.clear(); //Limpa o LCD para atualizacao
O Que Deve Acontecer
Após carregar o código para a placa, insira o sensor no solo e aproveite o monitoramento. Quando o solo secar, o display ficará piscando e informando que é necessário irrigar a planta, como no GIF a seguir.
No GIF acima utilizamos um copo d'água e aceleramos um pouco as leituras do sensor para facilitar a demonstração do comportamento do projeto, porém, em solo, esse aviso só deve ser apresentado após alguns dias depois da primeira irrigação.
Indo Além
Projetos mais sofisticados de controle de umidade de solo utilizam uma bomba peristáltica para irrigar o solo automaticamente quando ele estiver seco. Em nosso tutorial de projeto irrigador automático, ensinamos como criar um controle simples de umidade de solo, para não precisarmos nem regar as plantas, apenas abastecer o tanque de armazenamento.
Conclusão
Neste tutorial aprendemos como utilizar o sensor de solo capacitivo e como calibrá-lo de acordo com as leituras em solo seco e úmido para criar uma lógica de controle. Além disso, pudemos observar na prática o conceito sobre sensores capacitivos de solo e como sua tensão varia de acordo com a concentração de água.