Ventilador que se enciende y se apaga segun la temperatura, la humedad y la hora

Hola a todos. Soy nuevo en el foro, novato en Arduino y con escasos conocimientos de electricidad y electrónica. Os presento mi proyecto, que a pesar de mis pocos conocimientos, funciona.

El propósito es construir un sistema que arranque un ventilador según la temperatura, la humedad y la hora; todo ello controlado con un placa Freudiano y los sensores correspondientes.

La placa Freaduino y los sensores del sistema funcionan a 5 voltios y el ventilador a 12 voltios, con lo cual se hace necesario un relé para activar el ventilador y otra fuente de alimentación distinta para alimentarlo.

La idea primera era que todo este sistema estuviera en el exterior, alimentado por una batería de 12V, recargada con un panel solar y controlado todo con un regulador solar, que tiene salida USB y salida 12V, pero debido al consumo de energía (consume la batería en un día) no es posible esto, así que la solución fue poner la instalación en el interior y usar el enchufe domestico para conectar un transformador de 220 V alternos a 12 V continuos; la placa Arduino se alimenta con el USB del ordenador y así, además, puedo modificar el código al instante.

El problema que tengo es el consumo del sistema, que como ya he dicho consume la batería en un día. Leyendo los proyectos del foro he aprendido que hay una cosa que no sabía: se puede dormir el Arduino. Tengo que investigar este tema y ajustar mi código para ahorrar energía.

Sobre el consumo he leído un hilo muy instructivo: Alimentación solar, consumo y acumuladores que es del 2015 (Alimentación solar, consumo y acumuladores - Proyectos - Arduino Forum ) que tengo que leer detenidamente ya que mis conocimientos de electricidad también son mínimos.
COMPONENTES

  • Placa Freaduino v1.8.1
  • Sensor de temperatura y humedad, DH11
  • Reloj en tiempo real, RTC DC3231
  • Pantalla OLED SSD1306 128x64, para mostar los valores
  • Relé para arrancar el ventilador, de dos módulos pero solo su usará uno
  • Led para saber cuándo está encendido
  • Un ventilador de 12V DC
  • Transformador de 220V AC a 12V DC

CABLEADO

El RTC y el OLED comparten el mismo bus de comunicaciones, el I2C; ambos van conectados a los pines A4 y A5 de la placa.

En esta placa Freaduino están duplicadas las entradas analógicas (zona inferior derecha de la imagen) con lo que no hay problema para conectar el RTC y el OLED en la “misma”; en otras placas que no sean Freaduino, y que por lo tanto no tienen duplicadas las entradas analógicas, habrá que ver como conectar el RTC y el OLED.

El resto de componentes van conectados a los pines digitales; éstos se pueden cambiar ya que se determinan en el código.

En cuanto al ventilador, como ya se ha dicho, no se conecta a la placa, va conectado al transformador y al relé, que tiene tres salidas (las remarcadas en amarillo) y cuatro entradas (las remarcadas en rojo):

Las conexiones de las salidas del relé son dos:

  • La del medio, al positivo del transformador que alimenta al ventilador
  • Una del extremo, al positivo del ventilador

Además, el negativo del transformador al negativo del ventilador.

De las cuatro entradas del relé solo se usan tres porque solo se usa un módulo del relé, sus conexiones son:

  • GND a GND
  • VCC a 5V
  • IN1 al pin digital 2, en este caso. El IN2 es para el segundo módulo del relé, se puede conectar a otro pin digital
    A continuación posteo el código

ConexionesRele.jpg

ConexionesRele.jpg

Estas son las instrucciones sin los comentarios que hay en el programa

Se incluye la librería DHT11 para manejar el sensor de temperatura y humedad, se crea el objeto dht11 y se le asigna el pin 8 (al que va conectado el sensor) y se declaran las variables para la temperatura y la humedad

#include <DHT11.h> 
DHT11 dht11(8); 
float temp, hum;

Se incluyen las librerías SPI, Wire, Adafruit_GFX y Adafruit_SSD1306 para el manejo del OLED y la comunicación, se crea el objeto display para el OLED de 128x64

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(128, 64, &Wire, 7);

Se incluye la librería RTClib para el manejo del RTC y se crea el objeto rtc para el RTC.

#include <RTClib.h>
RTC_DS3231 rtc;

El led y el relé no es necesario definirlos

El SetUp del programa es:

void setup() {

Se abre la comunicación con el puerto serie a 9600 baudios. Esto solo es necesario si se quieren sacar datos por el puerto serie.

Serial.begin(9600);

Se comprueba el OLED. La dirección 0x3C es para un OLED de 128x64.

if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {

Si el OLED falla, se muestra en el puerto serie y no procede seguir, se hace un bucle infinito.

Serial.println(F("Asignacion fallida del OLED"));
for(;;);
  }

Si el OLED está bien, se muestra el buffer inicial, el logo de Adafruit, se espera un segundo y se limpia la pantalla.

display.display();
delay(1000);
display.clearDisplay();

Se comprueba el RTC; si falla la inicialización, se muestra el mensaje de error en el puerto serie y se hace un bucle infinito porque no procede seguir.

if (! rtc.begin()) { 
     Serial.println("Modulo RTC no encontrado !"); 
     while (1);
 }

Se configuran de salida los pines donde se conectan el led y el relé. El pin 11 para el led y el 2 para el relé.

pinMode(11, OUTPUT);
pinMode (2, OUTPUT);

Se cierra el setup

}

El Loop del programa es el siguiente.

void loop() 
{

Se lee el sensor de temperatura y humedad y se sacan los datos por el puerto serie. Para ello se declara una variable y se comprueba que tanto la variable hum como la temp son distintas de cero, si es así, se muestra en el puerto serie, si no se muestra un mensaje de error

int err;

  if((err = dht11.read(hum, temp)) == 0) 
     {
          Serial.print("Temperatura: ");
          Serial.print(temp);
          Serial.print(" Humedad: ");
          Serial.print(hum);
          Serial.println();
     }
  else
     {
          Serial.println();
          Serial.print("Error Num :");
          Serial.print(err);
          Serial.println();
      }

Se lee el RTC y se sacan los datos por el puerto serie. Para la lectura se usa la función DateTime de la librería y se asigna el valor a la variable fecha.

DateTime fecha = rtc.now();

Se construye una cadena, con el formato de fecha y hora elegido, para mostrarla en el puerto serie.

char buf0[] = "Ahora es: DD-MM-YYYY  hh:mm:ss";
Serial.println(fecha.toString(buf0));

Se declaran dos variables miHora y miMinuto para usarlas posteriormente en las condiciones.

int miHora = fecha.hour();
Serial.print ("miHORA es = ");
Serial.println(miHora);

int miMinuto = fecha.minute();
Serial.print("miMINUTO es = ");
Serial.println(miMinuto);

Se llama a la función testdrawstyles(); que escribe el OLED letras y líneas.

testdrawstyles();

Se sitúa el cursor del OLED en la columna 70 de la fila 2 para escribir la temperatura.

display.setCursor(70,2); 
display.println(int(temp));

Se sitúa el cursor en la columna 66 de la fila 17 para escribir la humedad.

display.setCursor(66,17); 
display.println(int(hum));

Se sitúa el cursor en la columna 5 de la fila 32 para escribir la fecha.

display.setCursor(5,32);

Se construye la cadena de la fecha con el formato deseado y se muestra en la pantalla.

char buf2[] = "DD/MM/YYYY";
display.println(fecha.toString(buf2));

Se sitúa el cursor en la columna 18 de la fila 48 para escribir la hora.

display.setCursor(18,48);

Se construye la cadena de la fecha con el formato deseado y se muestra en la pantalla.

char buf3[] = "hh:mm:ss";
display.println(fecha.toString(buf3));

Se representa todo en el display; por lo leído por ahí, las instrucciones de display se almacenan en la memoria del OLED y no se representan en la pantalla hasta que se ejecuta esta instrucción.

display.display();

Las cuatro siguientes instrucciones hacen parpadear la pantalla, invierten el color de la pantalla.

display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);

Una vez escritos los datos en el OLED, se evalúan las condiciones que encenderán el led y el rele.
En este caso, lo que se pretende es que el ventilador funcione siempre entre la una de la tarde (las 13 horas) y las cinco de la tarde (las 17 horas); también cuando la humedad sea menor que 55 y cuando sea mayor que 75; también tiene que estar apagado siempre entre las 21 horas y las 11 horas.

if (miHora >= 13 and miHora <= 17)    

  {
                                                        // Estas dos instrucciones ENCIENDEN el led y el rele
    digitalWrite(11, HIGH);             // Enciende el LED
    digitalWrite(2, LOW);                // Cambia el estado del rele: lo baja, 

  }
   else if (miHora >= 21 or miHora <= 11)
     {
                                                         // Estas dos instrucciones APAGAN el led y el rele
      digitalWrite(11, LOW);             // Apaga el LED
      digitalWrite(2, HIGH);              // Cambia el estado del rele: lo sube, 

     }
  else if (hum <= 55 or hum >= 75) 
    {
                                                        // Estas dos instrucciones ENCIENDEN el led y el rele
      digitalWrite(11, HIGH);           // Enciende el LED
      digitalWrite(2, LOW);              // Cambia el estado del rele: lo baja, 

    } 
  else
    {
                                                // Estas dos instrucciones APAGAN el led y el rele
    digitalWrite(11, LOW);                      // Apaga el LED
    digitalWrite(2, HIGH);                      // Cambia el estado del rele: lo sube, 

    }

Y por último, se cierra el Loop

}

miVentilador05_SensorRtcYOled128x64.ino (12 KB)

Esta es la función es la que escribe las letras y las líneas.

void testdrawstyles(void) {

1.- Limpia la pantalla

display.clearDisplay();

2.- Establece la escala del texto a 2. Las escalas son: Escala normal UNO; con DOS entran cuatro líneas en la pantalla 128x64; con TRES solo una línea y queda otra pequeña debajo; con CUATRO llena la pantalla con una sola línea.

display.setTextSize(2);

3.- Establece texto color blanco (posiblemente no necesaria, el OLED es monocromo)

display.setTextColor(SSD1306_WHITE);

4.- Dibuja una línea horizontal en la primera fila, la cero

display.drawLine(0,0,127,0,WHITE);

5.- Dibuja una línea horizontal en la fila sesenta y tres, la ultima

display.drawLine(0,63,127,63,WHITE);

6.- Dibuja una línea vertical en el primera columna, la cero

display.drawLine(0,0,0,63,WHITE);

7.- Dibuja una línea vertical en la última columna, la ciento veintisiete

display.drawLine(127,0,127,63,WHITE);

8.- Se sitúa el cursor de la pantalla en la columna 8 de la fila 2 y se imprime el texto de la temperatura y la C de los grados centígrados “Temp: C”

display.setCursor(8,2); 
display.println("Temp:   C");

9.- Dibuja en las posiciones adecuadas para representar el º de los grados centígrados ya que ese símbolo no está incluido en el conjunto de ellos que maneja el OLED

display.drawPixel(96, 4, WHITE);           // Dibuja un solo pixel Columna 96, fila 4 
display.drawPixel(96, 5, WHITE);
display.drawPixel(96, 6, WHITE);

display.drawPixel(97, 3, WHITE);
display.drawPixel(97, 4, WHITE);
display.drawPixel(97, 5, WHITE);
display.drawPixel(97, 6, WHITE);
display.drawPixel(97, 7, WHITE);

display.drawPixel(98, 2, WHITE);
display.drawPixel(98, 3, WHITE);
display.drawPixel(98, 7, WHITE);
display.drawPixel(98, 8, WHITE);

display.drawPixel(99, 2, WHITE);
display.drawPixel(99, 3, WHITE);
display.drawPixel(99, 7, WHITE);
display.drawPixel(99, 8, WHITE);

display.drawPixel(100, 2, WHITE);
display.drawPixel(100, 3, WHITE);
display.drawPixel(100, 7, WHITE);
display.drawPixel(100, 8, WHITE);

display.drawPixel(101, 3, WHITE);
display.drawPixel(101, 4, WHITE);
display.drawPixel(101, 5, WHITE);
display.drawPixel(101, 6, WHITE);
display.drawPixel(101, 7, WHITE);

display.drawPixel(102, 4, WHITE);
display.drawPixel(102, 5, WHITE);
display.drawPixel(102, 6, WHITE);

10.- Se sitúa el cursor en la columna 20 de la fila 17 y se escribe el texto de la humedad y el % del porcentaje.

display.setCursor(20,17);
display.println("Hum:   %");

11.- Se cierra la función

}

Muy bueno, una pregunta, ¿Por qué relé en vez de un octoacoplador o un Mofset? el relé consume corriente todo el tiempo.

Ten cuidado con poner a dormir el arduino

https://www.prometec.net/el-modo-sleep-en-arduino/, además aquí información sobre cómo evitar que los leds de arduino consuman electricidad (no apto para cardiacos)

https://forum.arduino.cc/index.php?topic=510635.0
https://forum.arduino.cc/index.php?topic=549710.0

Moderador:
Hola @jucalopez, bienvenido al foro Arduino en Español.
Aunque has presentado maravillosamente bien todo tu proyecto, no califica como tal y por lo tanto lo muevo a la sección Software, para que siga allí con las consultas necesarias.

Te diré que has presentado todo como si fueramos alumnos de una clase y tal es así que me cuesta responderte.
Asi que te pido que postees todo el código completo para poder verlo de una sola vez.
Como tu problema es dormir el arduino, dejaré que leas el hilo en cuestión pero te aseguro que es muy facil.
Solo siguiendo el ejemplo de la librería pones a dormir el arduino y lo despiertas a intervalos que consideres adecuados para sostener la situacion.
Te adelanto que hacerlo (dormir el arduino) te hara perder el control asi que estas en un dilema. Controlar o mantener la batería.

Si ese es el caso entonces tu problema esta en que consumes demasiado.
Comienza viendo como apagar el OLED.
Tal como te ha dicho TonyDiana, olvida el uso del RELE y considera los MOSFET porque vas a ahorar en mucho consumo.
Creo que ese es tu problema pero veamos con detenimiento.

El arduino consume unos 65mA.
Cada rele consume unos 65mA tmb, solo se usa uno.
Debo agregar algo al uso del ventilador, digamos otros 60 o mas mA. Calculo 65mA.
el OLED no se, supongamos 30 a 40mA como mucho
Estas en 130+65+40 = 235 mA mas o menos.

Una bateria de 12V 7Ah no puede agotarse en un día!!!
Veamos 235mA x 24hs = 5640mAh o 5.64Ah la verdad me sorprende pero estas ahi nomás.
Por lo visto estas en problemas.

Luego te comento algunas ideas.

Y habría que ver si el ventilador no consume más que 65mA. No aclara si es un cooler de notebook o un ventilador de techo.

De todos modos, la mayor carga que imagino es el ventilador, ¿está 24hs encendido?

Algo no cierra o no estoy viendo...

Edito: había salteado el párrafo donde habla del horario.

Hi,
Una cosa que no mencionas es de si le anadistes un diodo al conectar el panel solar y el regulador ya que si no se instala el regulaodor te va a descargar la bateria. Al anadirle el diode una vez que la luz solar se va entonces cuando el voltaje baja el diode no te pemite que la bateria se descargue hacia el regulaador. El diodo se conecta a la salida del regulador que se conecta a la bateria

Y una cosa más, que puede parecer tonta.

A un amigo mío, si a un amigo mío no a mi, a mi para nada, le pasó que devolvió un cargador solar para el celular como 5 veces, hasta que descubrió, este amigo mío que no yo, que lo ponía en un lugar donde recibía demasiada sombra y realmente no funcionaba porque no recibía suficiente luz.

Yo cambiaría el Uno por Nano que consume solo 15mA y le "volaría" el LED power, son unos 5mA de consumo innecesario.
Lo mismo al resto de las placas, que no quede ningún gasto superfluo, por ejemplo el LED de actividad del relé es un consumo innecesario (en el supuesto que se siga utilizando).
Una alternativa al reemplazo del relé por un mosfet puede ser el optotiristor como el H11C6, se activa con solo 5mA y maneja hasta 5A y 400V.
Obviamente apagar el display cuando no sea necesario (se podría poner un botón para activarlo en caso de consulta/control de la información).
Para la alimentación del arduino, en caso de hacerlo desde la batería, usar una fuente stepdown que por ser switching tiene mucho mayor rendimiento que un regulador lineal tipo LM7805, LM317 o similares .
Seguramente se puede hacer alguna "poda" más.

Tal como te dice @gatul debes poner todo tu sistema.
Intercalar el amperímetro de tu tester, medir lo que consumes ahora y empezar a quitar cosas innecsarias.
Olvidate de poner a dormir y que conserve estados a menos que uses reles de enclavamiento o pienses en alguna electrónica de bajo consumo que se enclave (conserve el estado) un simple flip flop RS serviría.

Hay muchas soluciones usando el ingenio.
Puedes reducir considerablemente el consumo y alargar el uso de la batería.

Hola a todos
Aqui pongo el codigo completo, menos la funcion que dibuja en el OLED porque excede el tamaño

// La libreria del sensor y su definicion
#include <DHT11.h>
DHT11 dht11(8);
float temp, hum;

// Las librerias y la definicion del OLED
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Declaracion para un OLED SSD1306 128x64 conectado a I2C (pins SDA y SCL)
Adafruit_SSD1306 display(128, 64, &Wire, 7);

// La libreria del RTC y su definicion
#include <RTClib.h>
RTC_DS3231 rtc;

// SETUP
void setup() {

 Serial.begin(9600);
 
// Setup del OLED
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("Asignacion fallida del OLED"));
    for(;;);
  }

  display.display();

  delay(1000);

  display.clearDisplay();
  
// Setup del RTC - Reloj en Tiempo Real
  if (! rtc.begin()) {
   Serial.println("Modulo RTC no encontrado !");
   while (1);
   }

 pinMode(11, OUTPUT);

 pinMode (2, OUTPUT);
 
}
// Fin Setup

// LOOP
void loop() 
{
// Lectura del sensor y salida por el puerto serie    
    int err;
            
    if((err = dht11.read(hum, temp)) == 0)                  
      {
        Serial.print("Temperatura: ");
        Serial.print(temp);
        Serial.print(" Humedad: ");
        Serial.print(hum);
        Serial.println();
      }
    else
      {
        Serial.println();
        Serial.print("Error Num :");
        Serial.print(err);
        Serial.println();
      }

// Lectura del RTC y salida por el puerto serie
  DateTime fecha = rtc.now(); 
 
  char buf0[] = "Ahora es: DD-MM-YYYY  hh:mm:ss";
  Serial.println(fecha.toString(buf0));
  
  int miHora = fecha.hour();
  Serial.print ("miHORA es = ");
  Serial.println(miHora);

  int miMinuto = fecha.minute();
  Serial.print("miMINUTO es = ");
  Serial.println(miMinuto);
       
// Salida por el OLED
  testdrawstyles();
                                        
  display.setCursor(70,2);
  display.println(int(temp));
  display.setCursor(66,17);
  display.println(int(hum));
  display.setCursor(5,32);
  char buf2[] = "DD/MM/YYYY"; 
  display.println(fecha.toString(buf2));
  display.setCursor(18,48);
  char buf3[] = "hh:mm:ss";
  display.println(fecha.toString(buf3));
  display.display();                                        
  display.invertDisplay(true); 
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

// Las condiciones de encendido y apagado del led y el rele
 if (miHora >= 01 and miHora <= 02)              
    {
      digitalWrite(11, HIGH);                     
      digitalWrite(2, LOW);                       
    }
     // else if (miHora >= 21 or miHora <= 11)
       // {
        // digitalWrite(11, LOW);
        // digitalWrite(2, HIGH);
       // }
     else if (hum <= 50 or hum >= 95) 
       {
                                                  
        digitalWrite(11, HIGH);                   
        digitalWrite(2, LOW);                     
       } 
    else
      {
                                                  
      digitalWrite(11, LOW);                      
      digitalWrite(2, HIGH);                      
}

Pero nosotros hablamos de consumos no de código.
En este momento creo que es mas importante y crítico ese tema, me parece.

Y si desistes de alimentarlo a baterías, con lo cual el consumo pasaría a segundo plano, replanteate la forma en que lo alimentas porque hacerlo desde un puerto de computadora no es la mejor opción, no es lógico tener 24hs encendida la misma para alimentar un arduino, máxime que tienes una alimentación de 12V para los periféricos de donde puedes "colgar" una fuente steepdown.

Hola a todos

Ante todo, gracias por vuestro interés y vuestros mensajes.
Creo que no he explicado bien mi “proyecto”.
Adjunta va una imagen de los componentes y otra de las conexiones del ventilador al Arduino.
Empezando por el final: gatul, eso que dices es lo que he hecho, no tengo problema con tener el PC encendido todo el rato (es como está habitualmente).
Surbyte, estoy contigo: el problema es el consumo. Ya me ha llegado un Voltimetro/Amperimetro USB y lo he conectado al sistema, el mayor consumo que he visto es 0.107A (adjunto imagen)
TonyDiana: creo que has dado con el problema de fondo: mi placa no alimenta lo suficiente la batería porque no tiene suficiente horas de sol, y lo peor, no tengo otro sitio.
Tauro0221: adjunto una imagen de la batería y el regulador solar. El panel solar es policristalino de 10Wp/18V; Detalles técnicos: Potencia: 10Wp; Tensión: 17,8V; Corriente: 0,57A
Por lo demás, sí, tengo que mirar como cambiar algunos componentes de esos que me sugerís para consumir menos; estoy en ello
Gracias

Pregunta de alguien que no sabe, pero por una solución que dimos a un tema parecido ¿más paneles? me imagino que en paralelo pero otro te dirá si esa es la solución

Hi,
Sugerencia hay paneles de diferentes voltajes y corrientes que se pueden comprar. Me parece que el menciono que no habia mucha luz solar entonces una solucon seria considerar un panel que tenga mas area para asi compenzar por la falta de sol pero el tambien dijo que elimino alimentar el systema con panele solares y usar una fuente de toma corriente.