Sensor humedad Capacitivo

Hola a todos.

Después de leer varios hilos, y especialmente el de hiddenotebook, quien, junto con la ayuda de los moderadores ha hecho un trabajo francamente didáctico, me puse a hacer mi proyecto de riego autónomo.

La principal diferencia es que quiero usar cuatro sensores de humedad independientes, y teniendo en cuenta los problemas de corrosión, me decidí a comprar unos sensores como estos

Después de pelearme mucho tiempo para entender un poco el proceso y hacer las pruebas pertinentes, cuando estoy haciendo el montaje en una pared, me doy cuenta de que estoy teniendo problemas con las entradas analógicas.

  • Cuando pincho el pin de datos en A0, me da valores para A0 y A1.

  • Cuando pincho en A1 me da un valor aparentemente correcto para la citada entrada analógica.

  • Si pincho en A2, no me da ningún valor.

  • Si pincho en A3, me da valores para A0 y A1.

A alguien se le ocurre por qué puede ser??

En las fotos está con un clónico, pero en el montaje de pared está con un Arduino UNO original, y me da el mismo problema.

Gracias por vuestra ayuda

Saludos.

Fotos:

Código utilizado:

  #include <SPI.h>  //Cargar libreria de comunicacion SPI
  #include "Ucglib.h" //Librería TFT 2.2 de ElecFreaks 241*320
  Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 4, /*data=*/ 3, /*cd=*/ 6 , /*cs=*/ 7, /*reset=*/ 5);  /*Conexion TFT a Arduino Elec Freaks Shield */ 


// set all moisture sensors PIN ID
  int moisture1 = A0;
  int moisture2 = A1;  
  int moisture3 = A2;
  int moisture4 = A3;

// declare moisture values

  int moisture1_value = 0;
  int moisture2_value = 0;
  int moisture3_value = 0; 
  int moisture4_value = 0;

  
  int hysterisis = 10;  // Margen de riego.


void setup() {
  
   
//-------------- TFT SETTINGS -----------------------
  delay(1000);
   
  ucg.begin(UCG_FONT_MODE_SOLID); //Inicia pantalla
  ucg.clearScreen(); //Linmpia pantalla
  ucg.setRotate90(); //rota la pantalla
 }


void loop() {

//void display(){ // Rutina para mostrar datos en TFT

  

// ------------- SOIL SENSOR ------------------------

//Comprueba si los sensores dan un determinado valor y riega hasta alcanzar otro valor

  //Sensor 1
    moisture1_value = analogRead(moisture1);
    moisture1_value = map(moisture1_value, 670, 340, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100
    
     
 //Sensor 2 
    moisture2_value = analogRead(moisture2);
    moisture2_value = map(moisture2_value, 670, 340, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100


  //Sensor 3
    moisture3_value = analogRead(moisture3);
    moisture3_value = map(moisture1_value, 670, 340, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100
  
       
       
//Sensor 4
    moisture4_value = analogRead(moisture4);
    moisture4_value = map(moisture1_value, 670, 340, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100
    


 //Mostrar en display los datos del DHT11 
  ucg.setFont(ucg_font_timR10_hr);
  ucg.setColor(0, 255, 0); //verde
 
  ucg.setFont(ucg_font_ncenB14_hf);
  
  ucg.setColor(255, 255, 255); //blanco
  
  ucg.setPrintPos(1,35);
  ucg.print("Ambiente");
  
  
  ucg.setPrintPos(35,40);
  ucg.setScale2x2();//duplica tamaño fuente

  ucg.undoScale();
  ucg.setPrintPos(115,80);
  
  ucg.print("*C"); 
   
  ucg.setPrintPos(95,40);
  ucg.setScale2x2();
  //ucg.print(h);
  ucg.undoScale();
  ucg.setPrintPos(235,80);
  ucg.print("%");


//Mostrar en pantalla los datos de los sensores de suelo
  ucg.setPrintPos(60,122);
  ucg.print("Humedad macetas (%)");

//Dibuja círculos en la pantalla
  ucg.drawCircle(40, 175, 35, UCG_DRAW_ALL);
  ucg.drawCircle(120, 175, 35, UCG_DRAW_ALL);
  ucg.drawCircle(200, 175, 35, UCG_DRAW_ALL);
  ucg.drawCircle(280, 175, 35, UCG_DRAW_ALL);
  

//Imprime en display los valores de los sensores de tierra
 
  ucg.setPrintPos(9, 95);
  ucg.setScale2x2();
  if (moisture1_value < 80)
    {  
      ucg.setColor(255, 210, 0); //naranja-amarillo
    } 

  else
    {
     ucg.setColor(100, 255, 0); //verde
     }
      
  if(moisture1_value <= 9) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print(' ');
      ucg.print(' ');
    } 

   if(moisture1_value > 99) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print('9');
      ucg.print('9');
    }  
  
   else
    {
     ucg.print(moisture1_value);
     }
   
  ucg.setPrintPos(49, 95);
   if (moisture2_value < 80)
    {  
      ucg.setColor(255,210, 0); //naranja-amarillo
    } 

  else
    {
     ucg.setColor(100, 255, 0); //verde
     }
    
  if(moisture2_value <= 9) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print(' ');
      ucg.print(' ');
    }   
   if(moisture2_value > 99) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print('9');
      ucg.print('9');
    }  
  
   else
    {
     ucg.print(moisture2_value);
     }
 
  ucg.setPrintPos(89, 95);
  if (moisture3_value < 80)
    {  
      ucg.setColor(255, 210, 0); //naranja-amarillo
    } 

  else
    {
     ucg.setColor(100, 255, 0); //verde
     }
  
  if(moisture3_value <= 9) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print(' ');
      ucg.print(' ');
    }  
   if(moisture3_value > 99) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print('9');
      ucg.print('9');
    }  
  
   else
    {
     ucg.print(moisture3_value);
     } 
  
  ucg.setPrintPos(129, 95);
  if (moisture4_value < 80)
    {  
      ucg.setColor(255, 210, 0); //naranja-amarillo
    } 

  else
    {
     ucg.setColor(100, 255, 0); //verde
     }
  
  if(moisture4_value <= 9) // coloca un cero cuando el valor es menor a nueve
    {  
      ucg.print(' ');
      ucg.print(' ');
    }  
  
   if(moisture4_value > 100) // coloca un cero cuando el valor es menor a nueve
    {   ucg.print('9');
      ucg.print('9');   }  
  
   else
    {
     ucg.print(moisture4_value);
     }
  
  ucg.undoScale();
  
  
  delay(500);     
}

Todo lo que midas siempre debe tener alguna referencia. Si el pin esta al AIRE y esperas que como no tiene nada conectado te diga 0 porque no hay nada, estas equivocado.
Asi que una R de 10k entre pin y GND es una buena práctica.
Donde pongas un sensor, puedes retirar la Resistencia, pero si mides dos y uno no tiene sensor Capacitivo entonces consérvala.
Bien, entonces en tu código veo demasiadas cosas y no digo que este mal.

Primero verifica los AD, entonces mide los 4 sensores con los 4 A0...A3

moisture1_value = analogRead(moisture1);
moisture1_value = map(moisture1_value, 670, 340, 0, 100);

Verifica esto y muestralo en el monitor Serie. Deja la pantalla para luego.
A ver que resulta.

Nada de conectar (pinchar) 1 y el otro no. O conectas todos o le pones a todos R de 10K y desconectas en aquel que uses el sensor.

Mil gracias Surbyte!!

surbyte:
Si el pin esta al AIRE y esperas que como no tiene nada conectado te diga 0 porque no hay nada, estas equivocado.

El que no sabe, es como el que no ve. Eso que dices es lo que yo me creía.

He "pinchado" 5 resistencia a los A, y en todos me ha clavado un 0 en el monitor serie. Después he ido conectando el sensor (uno a uno) desde A0 a A3, y en todos me ha clavado el valor "566" (sin mapear, valor directo del sensor). Casi se me saltan las lágrimas.

surbyte:
Bien, entonces en tu código veo demasiadas cosas y no digo que este mal.

Salvo que no sea estrictamente necesario, no te enseñaré el código completo, para que no llores.

El proyecto se complementa con cuatro selenoides(uno para cada maceta) y un motor de 12v para el impulsar el agua. Esta parte del código me costó un mundo, y seguro que es ineficiente, pero creo que funciona. Bueno, ya veremos.

Saludos y Gracias

Quería compartir mis impresiones sobre los sensores capacitativos que estoy usando.

Lo más positivo que tienen es que no se corroen, pero tienen muchos peros:

  • Tienen un comportamiento errático , me explico, si el sensor está en la la tierra durante un tiempo dando un valor, por ejemplo 60%, y lo sacamos de la tierra y lo volvemos a introducir, el valor será de 50$ y no volverá a subir. Creo que esto se produce por la compresión/densidad del material que rodea al sensor.

  • La capa de plástico que la cubre es muy delicada y se deteriora rápidamente, se despega y le salen burbujas.

  • En un mes de pruebas hay sensores que no miden igual que al principio. Pongo dos juntos y dan medidas distintas.

Habrá que probar con otros.

Salvo que no sea estrictamente necesario, no te enseñaré el código completo, para que no llores.

No lloro a veces nos ocurre que somos demasiado estrictos y queremos hacer las cosas a nuestra manera. Y vemos algo y decimos.. Noooo porque repites tantas veces esto.. o lo otro. Bueno por ahi va.

Bueno. Respecto de los sensores TU supones que sacar un sensor y volverlo a introducir te dará la misma lectura pero sabes si ha cambiado la capacidad en torno al sensor? Dale al menos una oportunidad de creer que mide mejor de lo que uno supone.

Ahora que dos sensores midan distinto es otro tema. Se debe 1ro a su calidad. 2do a la falta de calibración.
Si vieramos su esquema electronico dudo mucho que tenga una fuente de pulsos de precisión. Supongamos y permiteme la licencia que sea una etapa formada por una Resistencia y un capacitor. Tal vez se mida durante la carga o durante la descarga. Da igual pero ambos tiempos dependen de R y C y de su calidad. También esta el detector de umbral que dice he llegado a determinado valor y acá me detengo.. y eso traducido tal vez en una PWM que luego se filtra y se traduce en una salida analógica. Todo es mi estimado... tiene algunos posibles drift por temperatura, tensión, componentes, etc.

Bien, compramos algo de 5 dolares y esperamos maravillas. Medimos si. Algo bastante proximo con un error de 10 al 20% tal vez. Quieres algo mejor... cuesta otro precio.

Pregunta a la gente que trabaja en agricultura cuando cuesta un sensor bueno... yo he comprado uno por 200 dolares.

Hola Rafa, que tipo y de que longitud son tus cables de los sensores de humedad ?

Lo que probablemente te esta ocurriendo es que el ruido eléctrico es muy grande respecto a la señal misma y sumados ambos obtienes grandes fluctuaciones de medida y ya no sabes si es la humedad o el ruido lo que estas midiendo.

Te recomiendo hacer una prueba con un cable apantallado, lo mas corto posible, soldado con estaño en ambos extremos y considerar obtener la media (o quizás mediana) de varias lectura.

Los cables delgados, largos y con conexiones mecánicas son la peor opción.

Pero hay un truco @ArduMyth que es no estar midiendo continuamente!! Para que hacerlo si la humedad de suelo no cambia a velocidad del tic tac. Mides y luego apagas el sensor.
Lo alimentas con un pin o un transistor para mayor seguridad, mides con el que haga falta (sea un analógico de seguro) y lo apagas. Eso evita el deterioro del sensor.

Bueno, por supuesto estoy de acuerdo en todo lo que se ha dicho aquí, pero al final vale la pena gastar un poco más de dinero, sin llegar a los 200 que menciona Surbyte.

Los cables que uso son apantallados pero algo finos, pero en las pruebas he cambiado los sensores, unos por otros, y los comportamientos que no me gustaban seguían repitiéndose. Como por ejemplo el que tardan mucho en registrar los nueevos valores, y eso, en un proyecto en el que intento cortar a un nivel determinado de humedad, es un verdadero problema. El otro problema que comenté, el de la fragilidad de la pegatina plástica que los cubre, es definitivo, ya que al meterlos y sacarlos de la tierra se producen arañazos, y esto hace que cambien los valores de salida.

He estado probando los Soilwatch10 con unos resultados claramentoe mejores. Además, vienen ya impermeabilizados y son de material similar a una PCB, con lo que no se arañan. La salida la dan invertida a un capacitativo normal, es decir, cuanto más alto en valor de salida, mayor humedad, y solo resta normalizar la variable entre 0 y 100.

Bueno cierro esta respuesta sobre mi opinión sobre los sensores y abro una nueva para consultar problemas y pedir ayuda.

Rafagp:
Bueno cierro esta respuesta sobre mi opinión sobre los sensores y abro una nueva para consultar problemas y pedir ayuda.

Hola,
Medir la humedad del terreno no es una cuestión fácil. Que yo sepa lo suyo es usar una "mufla" (una especie de horno pequeño) para secarla y comprar el peso -de la muestra- con el original. Naturalmente, este es un ensayo destructivo, por lo que no vale para el caso ...
Me da la sensación de que te vas a tener que armar de paciencia y de talante científico: con los sensores que tienes haz mediciones en diferentes situaciones y toma notas; coloca dos (o más) sensores en la misma parte del terreno; mira a ver si promediando los valores lo que obtienes es más estable; prueba con diferentes sensores; si tienes varios -muchos- prueba a descartar las medidas máximas y/o mínimas y/o que se alejen mucho de la media, ...
Probablemente lo que se dice más arriba de usar un sensor más caro también ayude, pero yo haría antes pruebas como las que te digo.
Suerte

Os recuerdo que el proyecto que estoy desarrollando se basa en 4 sensores de humedad independientes, que controlan el riego independiente de 4 maceteros. Recalco esto porque no he encontrado ningún proyecto similar, así que no he podido copiar y pegar código. Y que quede claro que todo código que he copiado y pegado, ha sido después de entenderlo.

El proyecto, visualmente va así:

La parte sobre la que tengo muchas dudas, porque no la he copiado de ningún sitio, es donde se decide que en función de que haya algún sensor por debajo de un umbral de humedad, se abran los selenoides/ válvulas correspondientes y la bomba de agua, y cuando alcanzan otro valor (el umbral + histerisis) se cierren las válvulas y la bomba de agua.

Esta parte funciona mal. A veces se queda colgado y se cierra la válvula, pero no la bomba.

A veces lo que pasa es que al apagarse la bomba se reinicia el arduino. Esto creo que es problema de la electrónica. Creo haber leído algún post (que ahora no encuentro) donde Surbyte explicaba que había que colocar un ¿condensador?? entre los bornes del motor para evitar una onda de rebote que ... (vaya, ciencia ficción).

En fin, supongo que habrá muchas más deficiencias en el código que irán aflorando, pero paso a paso, de momento me gustaría arreglar estas.

La parte de la bomba de agua y válvulas es:

//Comprueba si los sensores dan un determinado valor y riega hasta alcanzar otro valor

  //Sensor 1
    moisture1_value = analogRead(moisture1);
    moisture1_value = map(moisture1_value, 0, 590, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100
    
    if (moisture1_value < tomate)        // si humedad sensor 1 es < tomate
       {
        digitalWrite(relay1, LOW);    // Activamos relé
       }
    if (moisture1_value > (tomate + hysterisis))  // Si detecta mas de ? %H
       {
       digitalWrite(relay1, HIGH); // Apaga el relé
       }
     
 //Sensor 2 
    moisture2_value = analogRead(moisture2);
    moisture2_value = map(moisture2_value, 0, 590, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100
    
    if (moisture2_value < pimiento)        // si humedad sensor 2 es < pimiento
       {
        digitalWrite(relay2, LOW);    // Activamos relé
       }
        if (moisture2_value > (pimiento + hysterisis))  // Si detecta mas de ? %H
       {
        digitalWrite(relay2, HIGH); // Apaga el relé
       }


  //Sensor 3
    moisture3_value = analogRead(moisture3);
    moisture3_value = map(moisture3_value, 620, 325, 0, 100);   //Nos convierte el valor que da la sonda en un valor entre 0 y 100
    
    if (moisture3_value < lechuga)        // si humedad sensor 3 es < lechuga
       {
        digitalWrite(relay3, LOW);    // Activamos relé
        }
    if (moisture3_value > (lechuga + hysterisis))  // Si detecta mas de ? %H
       {
        digitalWrite(relay3, HIGH); // Apaga el relé
       }
       
       
//Sensor 4
    moisture4_value = analogRead(moisture4);
    moisture4_value = map(moisture4_value, 620, 325, 0, 100);//Nos convierte el valor que da la sonda en un valor entre 0 y 100
    
    if (moisture4_value < semillero)        // si humedad sensor 4 es < semillero
       {
        digitalWrite(relay4, LOW);    // Activamos relé
       }
    if (moisture4_value > (semillero + hysterisis))  // Si detecta mas de 65%H
       {
        digitalWrite(relay4, HIGH); // Apaga el relé
       } 


//Enciende o apaga la bomba
    if (moisture1_value < tomate || moisture2_value < pimiento || moisture3_value < lechuga || moisture4_value < semillero )
      {
       digitalWrite(pump, LOW);
      }

     if (moisture1_value > (tomate + hysterisis) && moisture2_value > (pimiento + hysterisis) && moisture3_value > (lechuga + hysterisis) && moisture4_value > hysterisis > (semillero + hysterisis))

      {
       digitalWrite(pump, HIGH);
      }

Adjunto fichero con código completo, porque recibía warning de exceso de palabras.

Riego_autonomo_rgp.ino (9.11 KB)

Esta parte funciona mal. A veces se queda colgado y se cierra la válvula, pero no la bomba.

A veces lo que pasa es que al apagarse la bomba se reinicia el arduino. Esto creo que es problema de la electrónica. Creo haber leído algún post (que ahora no encuentro) donde Surbyte explicaba que había que colocar un ¿condensador?? entre los bornes del motor para evitar una onda de rebote que ... (vaya, ciencia ficción).

No es un condensador sino un diodo y va en antiparalelo. O sea.. siempre sobre la electroválvula o bomba o rele.
Te lo explico con un gráfico para que no haya dudas malos entendidos.

Gracias Surbyte por la detallada explicación, y disculpa por haber dicho "condensador". Te habrá sentado como un atentado.

Ya he colocado el diodo en antiparalelo con el motor de 12 v.

Ahora creo que necesito algo de ayuda con el código. Muchas veces lo que pasa es que cuando se alcanza el umbral para regar se abre la válvula correspondiente y se enciende el motor, pero cuando se alcanza el nivel de corte, se cierra la válvula pero no se apaga el motor.

Cualquier ayuda será agradecida.

y disculpa por haber dicho "condensador". Te habrá sentado como un atentado.

Para nada me molesta. Entiendo que al foro llegan personas de todo tipo, electronicos y no electronicos.
Asi que ningún atentado. Hay otras cosas que si me molestan pero no viene al caso ahora.

Respecto a tu código mira lo que encontré mientras lo ordenaba

if (moisture1_value > (tomate + hysterisis) && 
      moisture2_value > (pimiento + hysterisis) && 
      moisture3_value > (lechuga + hysterisis) && 
      moisture4_value > hysterisis > (semillero + hysterisis)) {  // esta sección no esta bien sobra algun >
     digitalWrite(pump, HIGH);
  }

Justo ahora me acababa de dar cuenta de un problema en esa parte del código .... pero no era lo que me
has pillado.

Gracias, corregido.

El código que he montado no funciona, porque para que se apague la bomba, todos los sensores tienen que estar en el máximo de humedad (ie. : tomate+Histerisis). Y esto no se dará casi nunca y no tiene sentido. Tengo que buscar otra idea para cerrar la bomba.

Gracias.

una bomba para 4 elementos con diferentes humedades me parece un error.

Usa si quieres una bomba y 4 electroválvulas.
Cuando se alcance la humedad de cada sistema apagas la electroválvula y ese sector dejaré de recibir agua.
Si todos estan con lo esperable entonces apagas la bomba.

Asi al menos sabras que la que recibe agua es porque lo necesita.

Surbyte, es así como está, una bomba , cuatro electroválvulas y cuatro sensores.

El problema es que no sé como dar la orden de apagar la bomba.

Lo que había programado no vale porque solo se apagaba la bomba cuando todos los sensores estaban en el máximo y no en cualquier otro valor del rango considerado como adecuado.

Se me ocurre que una opción puede ser que se apague la bomba cuando todas los relés delas electroválvulas estén apagadas, pero esto no sé como se hace, es decir, como se pregunta si un determinado relé está en hight o low.

Este código puede tener sentido para apagar la bomba cuando todos los relés/electroválvulas estén apagados??

if (Relay1 = HIGH && Relay2 = HIGH && Relay3 =HIGH && Relay4 = HIGH)

{
digitalWrite(pump, HIGH);
}

Esté código parece que sí me funciona:

// Enciende o apaga la bomba
    
   if(digitalRead(relay1)== 0 || digitalRead(relay2) == 0 || digitalRead(relay3) == 0 || digitalRead(relay4) == 0) // Si algún relay/válvula está encendido
 
      {
       digitalWrite(pump, LOW); //Enciende bomba
      }

   else
      {
      digitalWrite(pump, HIGH);  // Apaga bomba
      }

Pero parece que a pesar del diodo, al apagarse la bomba sigue reiniciándose el Arduino (aunque no me preocupa mucho)

Saludos.

Da gusto oíros hablar!!!

Me voy una semana fuera y hasta que regrese no podré seguir con los experimentos.

Revisaré todas las conexiones o posibles contactos con el arduino y la instalación que hice del diodo.

Gracias.

Lo que te indiqué en el post #12 debes tenerlo en cuenta para toda bomba, y toda electroválvula que funcione con DC.
O sea, siempre colocar un diodo en antiparalelo del tipo 1N4002 como mínimo.
Eso reducirá o eliminará posibles problemas como los que comentas.

Otro tema es que cuento 5 relays. 5x60 mA = 300mA. Ese valor de corriente debería ser soportado por el Arduino si es lo que usas para alimetnar los reles. Observemos si con los diodos desaparece tu reinició de Arduino y de lo contrario tendras que usar/probar con una fuente externa.