Disminuir el consumo de energía al máximo de Arduino REV UNO.

He montado un proyecto de un sistema de riego automático con un fotosensor LDR, un módulo de medición de temperatura ambiente y humedad, un sensor de la humedad en el suelo con 2 antenas de TV y una minibomba de agua para acuario.

Mi objetivo que placa Arduino consuma lo menos posible. Alimento la placa Arduino Rev Uno con una pila de 3,7V y 6000 mAh (según el fabricante). Para recargar la pila de 3,7V he usado un panel solar, un regulador de carga y un regulador de voltaje y un módulo que evita que la pila 3,7V se dañe por defecto o exceso de carga.

He leido que delay incrementa bastante el consumo de recursos de la placa y que es mejordelayMicroseconds(). Otra opción sería la funcion millis. Pero me ha interesado especialmente el modo sleep

Otro problema que tengo es que la bomba de agua riega en exceso. ¿Se puede poner un delay por varias horas entre el primer y el segundo riego? No quiero usar un módulo de reloj, es añadir mas elementos al proyecto y no me gusta esa idea. ¿Algún consejo o idea?

Les dejo el código para que lo vean:

/* SISTEMA DE RIEGO AUTOMÁTICO CON SENSOR DE HUMEDAD DE SUELO, SENSOR
DE HUMEDAD DE AIRE, SENSOR DE LUZ Y SENSOR DE NIVEL DE LÍQUIDOS */
#include <SimpleDHT.h>
// Librería  <SimpleDHT.h> del sensor de temperatura y humedad relativa
#include <SPI.h>
//Librería <SPI.h> del motor DC compatible con la minibomba de agua DC
#define humidity_sensor_pin A0
//Se define variable del sensor de humedad en el suelo en el pin A0
#define ldr_pin A5
//Defino variable del sensor de fotoresistencia LDR en el pin A5

// for DHT11, 
//      VCC: 5V or 3V
//      GND: GND
//      DATA: 2
int pinDHT11 = 2;
// Se declara la variable pinDHT11 y lo asocio al pin 2
SimpleDHT11 dht11;
int ldr_value = 0;
//Se declara la variable ldr_value (fotoresistencia) y 
int water_pump_pin = 3;
//Se declara la variable mini bomba de agua y lo asocio al pin 3
int water_pump_speed = 255;
//Velocidad de la minibomba de agua oscila entre 100 como mínimo y 255 como máximo. Yo he //elegido 255 pero ustedes pueden elegir la que estimen conveniente. A más velocidad, mayor //bombeo de agua
int pin_water_sensor = 13;

void setup() {
  Serial.begin(9600);
  pinMode(pin_water_sensor, INPUT);
}
void loop() {
    // start working...
// Mide la temperatura y humedad relativa y muestra resultado
  Serial.println("*******************************");
  Serial.println("Sample DHT11...");
  
  // read with raw sample data.
  byte temperature = 0;
  byte humidity_in_air = 0;
  byte data[40] = {0};
  if (dht11.read(pinDHT11, &temperature, &humidity_in_air, data)) {
    Serial.print("Read DHT11 failed");
    return;
  }
  
  Serial.print("Sample RAW Bits: ");
  for (int i = 0; i < 40; i++) {
    Serial.print((int)data[i]);
    if (i > 0 && ((i + 1) % 4) == 0) {
      Serial.print(' ');
    }
  }
  Serial.println("");
  
  Serial.print("Sample OK: ");
  Serial.print("Temperature: ");Serial.print((int)temperature); Serial.print(" *C, ");
  Serial.print("Relative humidity in air: ");Serial.print((int)humidity_in_air); Serial.println(" %");
  
  // DHT11 sampling rate is 1HZ.

  // Ground humidity value in %
// Mide la humedad en el suelo en % y muestra el resultado
  
  int ground_humidity_value = map(analogRead(humidity_sensor_pin), 0, 1023, 100, 0);
  Serial.print("Ground humidity: ");
  Serial.print(ground_humidity_value);
  Serial.println("%");

  // Light value in %
// Mide la luminosidad en % y muestra el resultado

  int ldr_value = map(analogRead(ldr_pin), 1023, 0, 100, 0);
  Serial.print("Light: ");
  Serial.print(ldr_value);
  Serial.println("%");
   Serial.println("*******************************");

  int estado = digitalRead(pin_water_sensor);
  Serial.print("Estado sensor: ");
  Serial.println(estado);
  switch(estado) {
    case 0: // Hay agua en el depósito
    	//**************************************************************
    	// Condiciones de riego 
    	// Si la humedad en el suelo es igual o inferior al 50%, si la luminosidad es inferior al 30%,
    	// Si la temperatura es inferior al 30%, entonces el sistema de riego riega. 
    	// En caso de que no se  cumpla alguno o ninguno de los 3 requisitos anteriores,
    	// el sistema de riego no riega
    	//**************************************************************
    	 if( ground_humidity_value <= 50 && ldr_value < 30 && temperature < 30) {
    	 digitalWrite(water_pump_pin, HIGH);
    	 Serial.println("Irrigate");
    	 analogWrite(water_pump_pin, water_pump_speed);
    	 }
    	//El motor de la bomba de agua arranca con la velocidad elegida anteriormente en el código    	 
    	 else{
    	 digitalWrite(water_pump_pin, LOW);
    	 Serial.println("Do not irrigate");
    	//El motor de la bomba de agua se para y no riega
    	 }
      break;
    case 1: // No hay agua en el depósito
         digitalWrite(water_pump_pin, LOW);
	 Serial.println("NO WATER");
      break;
  } 
  delayMicroseconds (50); 
}

Gracias por contestar.

La fotorresistencia cumple con la función de que riegue de noche o cuando hay poca luz. Las raices de las plantas pueden dañarse si se riegan a pleno sol porque pueden quemarse. Ahora bien, si introduces el RTC, reconozco que una fotorresistencia podría ser prescindible.

Yo vivo en una región que no nieva nunca ni tiene temperaturas bajas porque vivo al lado de la costa. En verano hay sol pero también días con nubes y bastante humedad ambiental. Solo un eclipse convertiría al fotorresistor en algo inútil por instantes.

El famoso sensor de humedad YL69 acaba destrozado a los pocos días por culpa del fenómeno de electrolisis, la superficie metálica se desprende y queda inservible. Te sorprendería el sensor de humedad de la maceta que he hecho con una resistencia de 10K y 2 antenas de TV cromadas. El cromado ayuda a que las antenas de TV duren todo el verano sin problemas y las mediciones son bastante precisas, el único inconveniente es que las antenas de TV son un poco largas pero por lo demás, son geniales.. Hay gente que usa clavos galvanizados pero son más caros y terminan por deteriorarse aunque duren más tiempo.

El DHT11 puede que no sea muy preciso pero tampoco vivo en una region con temperaturas extremas, mientras mida la temperatura de noche y sea inferior a lo que he puesto en el condicional if, es más que suficiente.

El problema es la bomba de agua, que riega como loca, porque cuando riega y alcanza el nivel de humedad en el suelo para que deje de funcionar, al poco tiempo desciende ese nivel mínimo de humedad y vuelve a regar un poco, de tal manera que riega bastante y vacia el depósito.

Una solución sería ponerle un módulo de reloj, otra solución sería usar un módulo de Bluetooth y arrancar el motor cuando conviniese. Y la otra solución seria conectar la placa a una fuente de alimentaciión de 9V y conectar esta a la red eléctrica de mi casa. Las macetas están cerca de mi ventana pero claro, tendría que dejar un poco abierta la ventana para que entre el cable. Usar una bateria de 12V me parece muy aparatoso y tendría que añadir paneles solares para cargarla.

Moderador: No repitas lo que se lee arriba.

El famoso sensor de humedad YL69 acaba destrozado a los pocos días por culpa del fenómeno de electrolisis, la superficie metálica se desprende y queda inservible

Este sensor acaba destrozado si lo tienes en uso continuo. Si lo usas solo cuando tienes que medir no pasa eso.
Para ello debes alimentalo con un pin y medir con otro. O puedes usar un transistor asociado a un pin.

De todos modos si armaste algo mejor esta resuelto.

El DTH11 mide con resolución de 1 grado. Nada mas que decir. Ya te lo han dicho.

Lo demas, son cosas a resolver. Si tu tanque de agua es pequeño, pues lo agrandas. Una cosa es mantener el riego y otra quedarte sin agua. Pero solo es un comentario.
Para mi el riego no debe ser por RELOJ sino por SOL asi que en parte estoy de acuerdo con el uso del LDR.
Estan dadas las condiciones para regar o no lo estan? El RTC no te lo dirá.. y el sol se pone en diferentes momentos todo el aÑo de modo que un LDR puede ajustarse mejor o fallar, si el dia es malo te dira que puedes regar antes, y si el sensor de humedad de suelo dice que esta húmedo no habrá que hacerlo.

Gracias @surbyte

Mi problema es de exceso de riego. Coloco un cubo de 5 L para 2 macetas de tomates y el agua desaparece en una noche. Evidentemente eso es un problema porque ahogas a las plantas.

Yo lo que quiero es un código que cuando haya condiciones de riego, funcione la bomba de agua durante 2 minutos y se quede parado durante 3 horas (por ejemplo) y salga de la condificional if para que el código vuelva a ejecutarse el loop por completo en 50 microsegundos.

Por ejemplo, he hecho esta modificación del código.

switch(estado) {
    case 0: // Hay agua en el depósito
     //**************************************************************
     // Condiciones de riego 
     // Si la humedad en el suelo es igual o inferior al 50%, si la luminosidad es inferior al 30%,
     // Si la temperatura es inferior al 30%, entonces el sistema de riego riega. 
     // En caso de que no se  cumpla alguno o ninguno de los 3 requisitos anteriores,
     // el sistema de riego no riega
     //**************************************************************
     if( ground_humidity_value <= 50 && ldr_value < 30 && temperature < 30) {
     digitalWrite(water_pump_pin, HIGH);
     Serial.println("Irrigate");
     analogWrite(water_pump_pin, water_pump_speed);
 delay (120000); // La bomba de agua riega durante 2 minutos
 digitalWrite(water_pun_pin, LOW);
 delay (10800000); // La bomba de agua para durante 3 horas
     }
     //El motor de la bomba de agua arranca con la velocidad elegida anteriormente en el código     
     else{
     digitalWrite(water_pump_pin, LOW);
     Serial.println("Do not irrigate");
     //El motor de la bomba de agua se para y no riega
     }
      break;
    case 1: // No hay agua en el depósito
         digitalWrite(water_pump_pin, LOW);
 Serial.println("NO WATER");
      break;
  } 
  delayMicroseconds (50); 
}

surbyte:
Este sensor acaba destrozado si lo tienes en uso continuo. Si lo usas solo cuando tienes que medir no pasa eso.
Para ello debes alimentalo con un pin y medir con otro. O puedes usar un transistor asociado a un pin.

De todos modos si armaste algo mejor esta resuelto.

El DTH11 mide con resolución de 1 grado. Nada mas que decir. Ya te lo han dicho.

Lo demas, son cosas a resolver. Si tu tanque de agua es pequeño, pues lo agrandas. Una cosa es mantener el riego y otra quedarte sin agua. Pero solo es un comentario.
Para mi el riego no debe ser por RELOJ sino por SOL asi que en parte estoy de acuerdo con el uso del LDR.
Estan dadas las condiciones para regar o no lo estan? El RTC no te lo dirá.. y el sol se pone en diferentes momentos todo el aÑo de modo que un LDR puede ajustarse mejor o fallar, si el dia es malo te dira que puedes regar antes, y si el sensor de humedad de suelo dice que esta húmedo no habrá que hacerlo.

La pregunta es si poniendo 2 delay con tanto tiempo, afecta negativamente al consumo de energía de la placa arduino.

Edito: Hay que tener en cuenta que Arduino es alimentado con una pila de 3,7V y que de nada vale que delay consuma mucha energía si el motor de bomba de agua están funcionando continuamente. Supongo que el motor de la bomba de agua consume mucha más energía que delay.

Edito2: En caso de que no haya agua, el sensor de nivel de líquidos actúa como interruptor y el motor de agua no arranca aunque haya condiciones de riego. Lo que ayuda a optimizar el funcionamiento del sistema de riego y a evitar un consumo de recursos innecesario.

Gracias a todos por contestar.

@ArduMyth gracias por contestar

El motor de agua bombea cerca de 1,5 L de agua en 2 minutos a través de 4 mangueras (2 por cada planta) desde un cubo de 5L de capacidad. Teniendo en cuenta que son 2 tomateras en maceta, toca a 750 ml por planta. Cantidad que considero más que suficiente porque tampoco hace mucho calor. Ese periodo de 2 minutos se puede modificar por 1 minuto o minutos dependiendo de la época y lo que estimes.

Me gustaría que mis sensores funcionasen continuamente y que solo el motor funcionase cada 3 horas y 2 minutos. De eso se trata, que el motor solo riegue 2 o 3 veces por la noche, 6 minutos como maximo durante la noche y con la luz solar deje de regar.

Has puesto una foto de motor de bomba de agua de acuario similar al que uso yo, funciona con menos de 5V. Tambien he pensado que seria buena idea reducir el numero de revoluciones por minuto del motor que ahora esta en 255 y dejarlas en el minimo 100.

No es mi intencion ahogar las plantas en agua, todo lo contrario. Hay gente que usa un sistema de riego por goteo durante todo el día y quiza sea bueno en ese caso, pero si quieres echarle cierta cantidad de agua durante un breve periodo de tiempo, tienes que hacerlo por la noche.

No, no tengo ningún kit por goteo. No sé como se comportaría la bomba de riego si regase por exceso y excediese el caudal que soporta las manguera, si le pones una boca muy pequeña al final de la manguera, el agua no podría circular y la minibomba de agua solo abastece 2 plantas y a una corta distancia. Yo he usado tubos de goma normales adaptados a la boca de la minibomba de agua.

Veo que usas un relé, entiendo que lo conectas a la red eléctrica de tu casa. Personalmente,yo prefiero usar un cargador de alimentación de 9V para Arduino y conectarlo a la toma de red electrica. Las macetas están en la terraza que lindan con mi habitacion, es más podria enchufar un temporizador y conectar a dicho temporizador un cargador de alimentacion de 9V.

La fotorresistencia indica el grado de luminosidad nocturna que en este caso es bajo y sirve para indicar a Arduino que puede regar.

Yo quiero que el código lea las mediciones de los sensores y el motor funcione 2 minutos y se pare y vuelva a funcionar dentro de 3 horas independientemente de lo que digan las mediciones. Con 2 o 3 riegos por la noche es suficiente.

La diferencia entre delay y timer radica que delay hace comprobaciones continuas (lo que hace consumir más recursos) los timer programan una interrupción para cuando llegue el momento ejecutar las serie de instrucciones y la verdad, prefiero esto ultimo. Me gustaría usar timer solo con el motor y que los demas sensores siguiesen funcionando de forma ininterrupida. ¿Me podrías orientar un poco con alguna librería timer y ejemplo de código?