Go Down

Topic: Control de calefacción central con radiadores. (Heating control NODEMCU) (Read 899 times) previous topic - next topic

nakuadak

Oct 18, 2019, 06:04 pm Last Edit: Oct 23, 2019, 11:53 am by nakuadak Reason: Simplificar el problema
Saludos y gracias por vuestro tiempo. Estoy estancado con un problema y no sé como solucionarlo, estoy con un proyecto de control de zonas para la calefacción central. En el código de abajo quiero que 2 sensores DHT22 me hagan lecturas, y al seleccionar una temperatura, que se me activen los relés de los radiadores y el de la caldera, ejemplo:

- Despacho, lo quiero a 23 grados, al estar a 21 se activa el relé del radiador y el relé de la caldera.
- Salón, lo quiero a 22 grados, al estar a 22.5 el relé del radiador no se activa y el relé de la caldera se desactiva.

¿Cómo hago para que el relé de la caldera, mientres haya un radiador en marcha no se desactive?


Code: [Select]


void loop() {

  if (millis() > anteriorRefreshDatos + 2000){
    anteriorRefreshDatos = millis();
    float tempDespacho = dhtDespacho.readTemperature();
    float tempSalon = dhtSalon.readTemperature();
      if (isnan(tempDespacho) || isnan(tempSalon)){
      Serial.println("Fallo en lectura de temperatura");
      return;}
        if (calderaHabilitada = 1){
          if (tempDespacho + histeresis >= tempDeseadaDespacho && tempDespacho > 0 ) {
            digitalWrite(releDespacho, LOW);
            digitalWrite(releSalon, LOW);
            digitalWrite(releCaldera, LOW);
            }
            if (tempSalon + histeresis >= tempDeseadaSalon && tempSalon > 0 ) {
            digitalWrite(releDespacho, LOW);
            digitalWrite(releSalon, LOW);
            digitalWrite(releCaldera, LOW);
            }
        else if (tempDespacho < tempDeseadaDespacho && tempDespacho > 0 )
        {
        digitalWrite(releDespacho, HIGH);
        digitalWrite(releSalon, HIGH);
        digitalWrite(releCaldera, HIGH);}
        else if (tempSalon < tempDeseadaSalon && tempSalon > 0 )
        {
        digitalWrite(releDespacho, HIGH);
        digitalWrite(releSalon, HIGH);
        digitalWrite(releCaldera, HIGH);}
      else
      {
        digitalWrite(releDespacho, LOW);
        digitalWrite(releSalon, LOW);
        digitalWrite(releCaldera, LOW);
      }

      }  



  

Mikms

Sin ver el codigo, pues no está, dificil va a ser que alguien te diga donde esta el error o como modificar para que haga lo que quieres.

Pero bueno supongo que lo que te pasa es que cuando una de las habitaciones le dice al rele "apagate" y otra de las habitaciones aun necesita que esté funcionando, la caldera hace caso a la orden de apagarse.

es esto?

Pablo_Lucini

Para hacer que la caldera siga encendida si hay algún relé activo podes usar una función OR. 
Por ejemplo: if (rele1==HIGH || rele2==HIGH || rele3==HIGH) { caldera=HIGH }

Mikms

si lo que intentas que es que mientras haya un sensor que demande que la caldera esté activa aunque otro/s no la demanden, lo tienes que hacer comparando sensores, no individualmente, es decir que si alguno de los sensores esta en temperatura de trabajo el estado del rele sea HIGH

cuando una de las siguientes opciones sean verdad---> haga tal (encienda o mantenga encendido)
y cuando todas las siguientes opciones sean verdad ---> haga cual (apague)

No se si me explico, pero aqui puedes ver como puedes coger la idea para hacerlo

Comparadores





Mikms

#4
Oct 20, 2019, 12:29 am Last Edit: Oct 20, 2019, 02:37 am by Mikms
Vamos por partes, primero tienes que saber que necesitas una temperatura de activar el rele y en esa misma otra que lo mantenga durante un tiempo, para que suba ciertos grados, sino estara siempre activandose y desactivandose todo el rato, al no lograr un margen.

Veamos si es algo asi lo que buscas...


Debes de tener dos lecturas separadas, ejemplo t1 sensor 1 y t2 sensor 2 (vamos a pensarlo para un solo rele de caldera)
   
if ( ((t1) <= 20.00)  || ((t2) <= 22.00))  si la temperatura t1 es menor o igual a 20º   O  t2 menor de 22º, si una de las dos es verdad (o ambas lo son) hace lo siguiente

  {
active el rele
}



Para que lo apague solamente cuando ningun sensor demanda que esté activado
if( ((t1) > 23.00)  && ((t2) > 25.00))  si la temperatura t1 es mayor a 23º      Y       t2 mayor de 25º , si las dos son verdad hace lo siguiente

  {
apaga el rele
}



Si lo pones asi en este orden creo que no debes poner nada mas, te es suficiente, recuerda que el loop corre siempre desde arriba a abajo buscando que hacer, por tanto aunque empiece a bajar la temperatura pongamos en t2 de 25º a 24º no se va a activar porque antes le estas diciendo que si en t2 no es menor o igual a 22º no se active. Si le cambias el orden en el loop entonces ya si hay que hacer unos cambios.

Con respecto a lo de ponerle unos grados más para que se desactive ya te digo que es para que le de tiempo a calentar y mantener una temperatura, sino tal como se pare empezara a perder temperatura y estará saltando todo el rato, al ser la diferencia de solamente 0,1º si le pones decimales, o de 1º si no se la pones.

nakuadak

Muchas gracias por tu tiempo ;)

""Vamos por partes, primero tienes que saber que necesitas una temperatura de activar el rele y en esa misma otra que lo mantenga durante un tiempo, para que suba ciertos grados, sino estara siempre activandose y desactivandose todo el rato, al no lograr un margen.""

--Sí, para ello tengo programada la histéresis, de esas forma los relés no están siempre en ON/OFF.

HISTÉRESIS

Code: [Select]
if (tempDespacho + histeresis >= tempDeseadaDespacho && tempDespacho > 0 )

____________________________________________________________________________________________

El problema no es hacer lecturas de los relés, eso lo tengo conseguido, el problema es conseguir que el relé de la caldera se encienda solamente cuando hay un radiador pidiendo calor, y que cuando no haya ningún radiador pidiendo calor, el relé de la caldera se desconecte.

Las temperaturas que he puesto antes son informativas, los rangos en cada uno de los sensores van entre los 21 y los 26 grados y los gestiono con "tempDeseadaDespacho", "tempDeseadaSalon", "tempDeseadaMatrimonio", "tempDeseadaInvitados".

Realmente son 4 zonas las que voy a usar, pero en la ayuda he puesto solamente 2 para que fuera más fácil el ejemplo.

 He probado con algo así, sólo con la zona del despacho, pero si hago eso mismo con las 4 zonas al final no me funciona correctamente:

Code: [Select]
if (calderaHabilitada = 1){
          if (tempDespacho + histeresis >= tempDeseadaDespacho && tempDespacho > 0) {
          digitalWrite(releCaldera, LOW);
          digitalWrite(releDespacho, LOW);
        } else  {
          (tempDespacho < tempDeseadaDespacho && tempDespacho > 0);
        }
        digitalWrite(releDespacho, HIGH);
        digitalWrite(releCaldera, HIGH);
          } else { digitalWrite(releDespacho, LOW);
      }


Lo que pretendo es lo siguiente, ejemplo:

- Quiero despacho a, por ejemplo 23 grados, al estar a 21 se activa el relé del radiador y el de la caldera.
- Quiero el Salon a, por ejemplo 24 grados, al estar a 20 se activa el relé del radiador y el de la caldera.
- Quiero Matrimonio, por ejemplo a 21 grados, al estar a 22 grados no se activa el relé, y manda orden de desconectar el relé de la caldera.
- Quiero Invitados a 22 grados, como está a 23 grados no hace nada.

El problema me viene para poder mover cada uno de los relés de los radiadores y que a su vez me active la caldera, siempre que haya un relé de un radiador activo. Cuando todos los radiadores estén desactivados, que el relé de la caldera se desconecte.

Te dejo un ejemplo que he estado usando para gestionar un sólo relé, cuando tenía la instalación mas sencilla en casa, solamente usando un sensor de temperatura y un relé:

Code: [Select]
if (millis() > anteriorRefreshDatos + 20000){
    anteriorRefreshDatos = millis();
    float temp = dht.readTemperature();
    float humi = dht.readHumidity();
      if (isnan(temp) || isnan(humi)){
      Serial.println("Fallo en lectura de temperatura y humedad");
      return;}
        if (calderaHabilitada = 1){
          if (temp + histeresis >= tempDeseada && temp > 0)  digitalWrite(releCaldera, LOW);
        else if (temp < tempDeseada && temp > 0) digitalWrite(releCaldera, HIGH);
      else digitalWrite(releCaldera, LOW);
      }       


Lo que pretendo es conseguir lo de arriba, pero con 4 DHT22 y 5 relés, uno por cada zona y el de la caldera. La parte lógica se me escapa.


Gracias por tu tiempo.





IgnoranteAbsoluto

¡Cuidado! La línea de código:
Code: [Select]
if (calderaHabilitada = 1){
No está haciendo lo que se espera que haga. La condición se cumple siempre porque lo que está haciendo es asignar el valor 1 a la variable calderaHabilitada y verificar que el valor asignado es distinto de cero, dando siempre por cierta la condición del if. Dicho de otro modo, esa línea hace que calderaHabilitada pase a valer 1 y que siempre se cumpla la condición. Es el fallo que todos cometemos de vez en cuando, el de poner un igual (=) en lugar de un doble igual (==) en las comparaciones.

La línea debería de ser:
Code: [Select]
if (calderaHabilitada == 1){
Hay que añadir un igual y poner == en lugar de = para que funcione como esperamos.

No he mirado sino por encima en código que has puesto, así que no sé si ese condicional es lo único que impide que tu programa haga lo que quieres. Mi consejo es que revises todos los "if" y, una vez corrergirlos, prueba a ver si sólo es eso lo que te está fallando.

Mikms

pero y si todo funciona y lo que buscas ahora es hacer que el rele de la caldera solamente funcione cuando lo demande un rele de uno o varios radiadores, porque no lo dices sencillamente que cuando alguno de los reles estén en High, lo haga tambien el de la caldera, y cuando esten todos en Low, pase a estarlo tambien el de la caldera?

leyendo ese pin de salida (pin hacia el rele de cualquier radiador) sabras su estado y con ello el que deba pasar a estar el de la caldera.

Sin todo el codigo, conexiones electricas y material que usas... sólo te van a poder decir puntualizaciones concretas, que igual realmente no sea lo que te ocurra, pues si como dices con 1 te funciona igual es que al poner más hay algun conflicto en la suma de todo y no en partes concretas

nakuadak

#8
Oct 20, 2019, 09:58 pm Last Edit: Oct 20, 2019, 10:44 pm by nakuadak
@Mikms

Muchas gracias por tu aporte, sí, finalmente he comprobado que el error está en que hay un conflicto en la suma de todo. Realmente me estoy volviendo loco con los IF y demás, en serio. Estoy probando mil combinaciones y seguramente sea mucho más simple de lo que tengo en la cabeza, pero mis limitaciones en programación no me dejan solucionar el problema.

Adjunto muestra básica del circuito. Son 4 sensores DHT y 5 relés. 4 relés para el control de las electrovávulas de los radiadores y un quinto relé para el control de la caldera.

Tengo casi terminado el código (me vais a disculpar por la forma de escribir el código y por las barbaridades que podéis encontrar, no soy informático y funciono a base de copiar código de por ahí y prueba y error). Ahora mismo y con el código que tengo escrito consigo configurar el NODEMCU desde mi teléfono móvil, enviar peticiones GET desde el móvil con un programa android y ver todos los datos en thingspeak.

Pero sigo con el problema del relé de la caldera. Si hago una petición GET pidiendo calor al radiador del DESPACHO, consigo que el relé del despacho se active, si hago un GET para que se apague, lo hace. Igual con los reles del Salon y de matrimonio. Pero no se activa el relé de la caldera.

Peeeeeerooooo si hago un GET al radiador de invitados, éste se activa y me activa el relé de la caldera, aquí sí, y si le hago un GET para que se apague invitados, el relé de invitados se desactiva y también el relé de la caldera.

Así que sí, es un problema en los IF, pero no sé cómo solucionarlo.

Os adjunto la parte del código en el que fallo. (Si queréis ver todo el código os lo mando o cuelgo en el post, no me deja subirlo porque excede de 9000 palabras. Aprovecho y como sugiere el admin, adjunto el archivo .INO con el programa completo que estoy desarrollando. Desde aqui dar las gracias y pedir disculpas por usar de forma incorrecta el foro, lo siento.

Code: [Select]
//--------------------RELE DESPACHO----------------------------------------------------------------------------------------
            if (tempDespacho + histeresis >= tempDeseadaDespacho && tempDespacho > 0){
            digitalWrite(releDespacho, LOW);
            digitalWrite(releCaldera, LOW);
            }
              if (tempDespacho < tempDeseadaDespacho && tempDespacho > 0){
                digitalWrite(releDespacho, HIGH);
                digitalWrite(releCaldera, HIGH);
        }
      

     //----------------------RELE SALON----------------------------------------------------------------------------------------

           if (tempSalon + histeresis >= tempDeseadaSalon && tempSalon > 0){
            digitalWrite(releSalon, LOW);
            digitalWrite(releCaldera, LOW);
            }
              if (tempSalon < tempDeseadaSalon && tempSalon > 0){
                digitalWrite(releSalon, HIGH);
                digitalWrite(releCaldera, HIGH);
        }
    

     //-----------------------RELE MATRIMONIO---------------------------------------------------------------------------------------


           if (tempMatrimonio + histeresis >= tempDeseadaMatrimonio && tempMatrimonio > 0){
            digitalWrite(releMatrimonio, LOW);
            digitalWrite(releCaldera, LOW);
            }
              if (tempMatrimonio < tempDeseadaMatrimonio && tempMatrimonio > 0){
                digitalWrite(releMatrimonio, HIGH);
                digitalWrite(releCaldera, HIGH);
        }
      

     //------------------------RELE INVITADOS--------------------------------------------------------------------------------------

           if (tempInvitados + histeresis >= tempDeseadaInvitados && tempInvitados > 0){
            digitalWrite(releInvitados, LOW);
            digitalWrite(releCaldera, LOW);
            }
              if (tempInvitados < tempDeseadaInvitados && tempInvitados > 0){
                digitalWrite(releInvitados, HIGH);
                digitalWrite(releCaldera, HIGH);
              }

          //---------------------RELE CALDERA----------------------------------------------------------------------------------------------
     if (releDespacho == LOW || releSalon == LOW || releMatrimonio == LOW || releInvitados == LOW){
            digitalWrite(releCaldera, LOW);
            }





surbyte

Si el código supera 9k entonces lo adjuntas como .zip para poder ser analizado.

nakuadak

@IgnoranteAbsoluto

Muchísimas gracias por tu ayuda, revisando el código he podido comprobar que realmente VAL no me sirve para nada, no sé en su día por qué lo utilicé, pero gracias a tu aporte lo he quitado y aligerado el código. Mil gracias.

Mikms

#11
Oct 21, 2019, 01:19 am Last Edit: Oct 21, 2019, 01:42 am by Mikms Reason: corregir error
Así mirando por encima.....Con esto le estas diciendo que si alguna de las siguientes opciones es verdad te apague el rele de la caldera

 ||  (Verdadero si alguna de las condiciones es verdadera). Es imposible entonces que si tienes tan solo uno de esos radiadores apagado te pueda encender el rele de la caldera

Code: [Select]
if (releDespacho == LOW || releSalon == LOW || releMatrimonio == LOW || releInvitados == LOW){
            digitalWrite(releCaldera, LOW);
            }
    



Entiendo que tendrias que usar
&& (Verdadero sólo si todas condiciones son verdaderas) para que en caso de que TODOS los radiadores esten apagados, mantenga apagado el rele de la caldera

Code: [Select]
if ((releDespacho == LOW) && (releSalon == LOW) && (releMatrimonio == LOW) && (releInvitados == LOW))
           {
            digitalWrite(releCaldera, LOW);
            }
            



(Debes meter entre parentesis cada cosa que pretendas comparar)

Mikms

#12
Oct 21, 2019, 01:35 am Last Edit: Oct 21, 2019, 01:57 am by Mikms
Code: [Select]
if (tempDespacho + histeresis >= tempDeseadaDespacho && tempDespacho > 0){
            digitalWrite(releDespacho, LOW);
            digitalWrite(releCaldera, LOW);
            }
              if (tempDespacho < tempDeseadaDespacho && tempDespacho > 0){
                digitalWrite(releDespacho, HIGH);
                digitalWrite(releCaldera, HIGH);}
        else{
          digitalWrite(releDespacho, LOW);
          digitalWrite(releCaldera, LOW);
        }


y recuerda que cada cosa que quieres comprarar debes tenerla metida entre parentesis para que sepa que parte concreta es la que estas comparando con cual
Code: [Select]
if ( (tempDespacho < tempDeseadaDespacho) && (tempDespacho > 0) )
 

Porque le dices siempre .... xxxxxxxl && xxxxxx MAYOR de 0?, para que que repites siempre que sea mayor de 0, en caso de ser menor no debe activarse? es que lo pones tanto en activarse como en desactivarse, por lo que no entiendo bien para que sirve (lo he mirado por encima, y lo mismo me he perdido algo)

esta parte? ... ya le estas diciendo arriba que si la temperatura es tal lo apague, y si es otra tal temperatura que lo encienda, entonces se entiende que si es la temperatura de arriba lo mantendrá apagado, y si es la de abajo lo mantendrá encendido, por lo que el "SINO apagalo", creo que no tiene mucho sentido.  
Code: [Select]
else{
          digitalWrite(releDespacho, LOW);
          digitalWrite(releCaldera, LOW);
        }


Un detalle (que a mi ya me volvio loco una vez y ademas con temas de temperatura y era ese despiste el que me daba fallo). El programa siempre lee de arriba a abajo, creo que lo mejor es siempre ponerle que primero sea encender y debajo apagar, para cuando compruebe no haya que ponerle más ordenes de apagar debajo cuando ya la tienes justo arriba, que igual es lo que te pasa y por eso usas ese ELSE,


nakuadak

@Mikms

Muchas gracias por todo. Resulta que los 2 NODEMCU que tengo se han estropeado, he pedido un par mas por Amazon y lo que tarden en llegarme. En cuanto los tenga en casa me pongo con todo lo que me has comentado y te voy informando, esto tengo que hacerlo funcionar como sea, jeje..


Muchas gracias, te cuento en breve.

surbyte

Como que se han estropeado? que has hecho para que eso ocurra, describe como los estas usando porque seguramente repetirás la falla con los nuevos y debes comenzar a usarlos debidamente.
No se queman porque si.

Tienes un esquema de como esta todo conectado?

Go Up