Go Down

Topic: Control Sistema de calor/frío por Fancoils (Read 4641 times) previous topic - next topic

surbyte

Quote
No acabo de entender la necesidad de juntar los GND,
Supon que tienes una pila o batería y la mides con el tester. Leerás 1.5V

Ahora busca otra batería y la mides, y solo para hacerme caso supongamos lees 1.55V

Bien como haces para que puedas leer las dos? debes tener un punto de referencia. Ese punto de referencia es el negativo de la dos pilas.

Asi que tendrías un borne positivo pila 1, otro positivo pila 2 y los dos negativos comunes.

Lo mismo ocurre con las fuentes de Arduino.

Werttty

Vale, creo que entiendo. Gracias por la explicación.

Werttty

#17
Nov 09, 2017, 11:15 am Last Edit: Nov 09, 2017, 02:18 pm by Werttty
Ya, abusando totalmente de vuestra amabilidad, la de la gente de este foro en general y la de surbyte en concreto, os pediría consejo de nuevo.

Antes de que me llegue todo el material, me he cogido una placa de circuito impreso que tenía en el taller del curro y que era para tirar, y la he pretendido usar de práctica de soldadura. Digo lo de "pretendido" porque lo que realmente he conseguido son dos cosas:
- Frustrarme
- Quemarme

Tengo dos soldadores de lapiz de 30W sencillos (uno del LDL y otro de calidad análoga) y una bomba de desoldadura de pistón y no tengo soporte. Lo máximo que consigo con ellos es que el estaño se convierta en una pasta densa y, estirando y con sacrificios, logro sacar alguna resistencia; ni soñar sacar nada de 3 pines o más, ya no hablemos de succionar el estaño. Las puntas estaban oxidadas, así que las he lijado, pulido reestañado y hecho todo lo que he visto por internet, pero nada funciona.
Conclusión: Tengo que cambiar de soldador.

Mirando en Amazon he visto estos dos, a ver qué os parecen:

Opción 1  (el kit con el soporte con muelle)
Opción 2
Opción 3
Opción 4 (Mi favorita por el momento, trae tierra y es el que tiene más valoraciones positivas y menos negativas; el diseño es atractivo y el precio ajustado)

La verdad es que con este proyecto por delante y los que me imagino que vendrán en el futuro, no me apetece hacer más el memo y quiero tener algo que sea sencillo (lo estaré todos los días soldando, a lo mejor hago una cosilla cada 3 meses) pero funcional. Obviamente, si aconsejáis algún otro que no esté en la lista, me lo miraré con cariño.
Soy una persona hábil y se que le pillaré el truco rápido a esto de la soldadura electrónica, pero necesito que las herramientas no me pongan palos en las ruedas, si no imposible.

Gracias por adelantado.

Werttty

Al final me he comprado la Opción 3; el de la Opción 4 tenía un comentario que decía que sólo llegaba hasta 160ºC, mientras que el de la Opción 3 es cómo el de la Opción 2 pero con menos trastos que no necesito y precio menor y, además, parece que las temperaturas están testeadas y te habla en la descripción del margen de error entre lo que le pides por el mando y la temperatura real, además de no tener comentarios negativos sobre este aspecto.
Espero dejar de pasear pasta de estaño de un lado a otro y poder hacer algo útil con esta herramienta.

Werttty

Madre mía, suerte que todo el material me está llegando con cuentagotas, porqué me estoy dando cuenta poco a poco de la cantidad de fallos que tengo y así no frío el Arduino.

Acabo de percatarme que en la mayoría de tutoriales recomiendan conectar los pulsadores de esta forma:



Si os fijáis en mi último esquema,



yo lo que hacía era alimentar el botón con 5V y, antes de irme al pin digital correspondiente, ponerle una resistencia de 10kΩ. Por lo que veo, lo correcto es "empalmar" la resistencia e ir a GND con ella (vamos, siguiendo el esquema primer esquema). Entiendo que si lo hago de este modo, conseguiré lectura HIGT al pulsar el botón y LOW cuando no está pulsado.

Me tocará retocar el esquema otra vez. No, si al final lo lograré y todo y hasta aprenderé un poco de electrónica por el medio.

surbyte

Existen 2 modos de conectar un pulsador y de uno de ellos se deriva otro.

Busca pull-up y pull-down.
En pull-up resulta que hay dos como te dije antes. Uno con R y otro usando la R interna del arduino.

Cualquiera de los dos métodos esta bien. R a 5V y cuando pulsas tienes GND o R a GND y cuando pulsas tienes 5V.

Asi que eso no esta mal.

Werttty

Ya he modificado el esquema y ayer hice unas pequeñas pruebas y, a falta de profundizar más, parece que la cosa funciona más o menos de la forma prevista. Hoy me ha llegado todo el material que me faltaba, por lo que seguramente mañana haré las pruebas de todo.
De momento, dejo enlace al esquema definitivo con -creo- todos los errores subsanados. Lo pongo también en cómo adjunto.


Werttty

#22
Nov 17, 2017, 02:33 pm Last Edit: Nov 17, 2017, 08:14 pm by Werttty
Pues al fin me ha llegado todo y he hecho las primeras pruebas según el último esquema (excepto por la fuente de energía suplementária para los relés, lo he hecho todo con los 5V del Arduino) y compilando el último código.
La verdad es que ha sido un éxito a medias, ya que aunque he podido comprobar que se me encendían y apagaban los relés y leds conectados a las salidas digitales y se registraban las lecturas de las entradas digitales, a la hora de funcionar la doble condicional, lo hacía correctamente o no según el estado de OONOFF. Releyendo mi código, usando el sentido común y elaborando una tabla, he logrado dar con el problema y -espero, no he compilado- solucionarlo.

El código inicialmente decía lo siguiente:

Code: [Select]

  int valor4 = digitalRead(OONOFF) ;                    // Leemos el valor de la orden paro/marcha
  if ( valor4 == true ) {                               // esto es que hay solicitud de marcha
      int valor5 = digitalRead(OFRICALOR) ;             // Leemos si estamos en modo frio o calor
      if (valor5 == true ) {                            // Esto es que estamos en modo calor
          digitalWrite( RONOFF, true) ;                 // Se enciende el rele RONOFF encendiendo la bomba de calor en modo invierno (calor)
          digitalWrite( LEDCALOR, true) ;               // Se enciende el led rojo
      }
      else     {
          digitalWrite( RONOFF, false) ;                // Se apaga el rele RONOFF encendiendo la bomba de calor en modo verano (frío)
          digitalWrite( LEDFRIO, true) ;                // Se enciende el led azul
      }
  }
  else  {

        int valor6 = digitalRead(OFRICALOR) ;           // Leemos si estamos en modo frio o calor
        digitalWrite( LEDCALOR, valor6) ;               // Encendemos led rojo si esta en modo calor apagamos en modo frio
        digitalWrite( LEDFRIO, !valor6) ;               // Encendemos led azul si esta en modo frio apagamos en modo calor
        digitalWrite( RONOFF, !valor6) ;                // Apagamos el rele en modo calor y lo encendemos en modo frio
        digitalWrite( RFRICALOR, !valor6) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar

  }
}


Me he dado cuenta de que, según este código, si OONOFF es False, definía de forma clara e inequívoca los 4 valores en juego LEDCALOR, LEDFRIO, RONOFF y RFRICALOR dependiendo del estado de OFRICALOR, pero si OONOFF era True, entonces -y dependiendo del estado de OFRICALOR- definía únicamente el estado de 2 de los 4 valores en juego, por lo que el comportamiento del Arduino era confuso. He definido los 4 valores en todas las variables posibles para que no haya nunca ningún valor sin definir, por lo que esa parte del código queda así:

Code: [Select]

  int valor4 = digitalRead(OONOFF) ;                    // Leemos el valor de la orden paro/marcha
  if ( valor4 == true ) {                               // esto es que hay solicitud de marcha
      int valor5 = digitalRead(OFRICALOR) ;             // Leemos si estamos en modo frio o calor
      if (valor5 == true ) {                            // Esto es que estamos en modo calor
          digitalWrite( RONOFF, true) ;                 // Se enciende el rele RONOFF encendiendo la bomba de calor en modo invierno (calor)
          digitalWrite( LEDCALOR, true) ;               // Se enciende el led rojo
          digitalWrite( LEDFRIO, false) ;               // Se apaga el led azul
          digitalWrite( RFRICALOR, false) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar

      }
      else     {
          digitalWrite( RONOFF, false) ;                // Se apaga el rele RONOFF encendiendo la bomba de calor en modo verano (frío)
          digitalWrite( LEDCALOR, false) ;              // Se apaga el led rojo
          digitalWrite( LEDFRIO, true) ;                // Se enciende el led azul
          digitalWrite( RFRICALOR, true) ;              // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar
      }
  }
  else  {                                               // esto es que hay solicitud de paro

        int valor6 = digitalRead(OFRICALOR) ;           // Leemos si estamos en modo frio o calor
        digitalWrite( RONOFF, !valor6) ;                // Apagamos el rele en modo calor y lo encendemos en modo frio
        digitalWrite( LEDCALOR, valor6) ;               // Encendemos led rojo si esta en modo calor apagamos en modo frio
        digitalWrite( LEDFRIO, !valor6) ;               // Encendemos led azul si esta en modo frio apagamos en modo calor
        digitalWrite( RFRICALOR, !valor6) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar

  }


Entiendo que ahora, además de compilarme, el Arduino debería comportarse conforme a esta tabla:


(Todas las conexiones a los relés se realizarán en posición normalmente cerrado). Pongo el código completo para referencia: (Siguiente mensaje por exceder caracteres)


Werttty

(Recordemos que esta tabla define el encendido y apagado y el modo de funcionamiento de una bomba de calor para calefacción contra un depósito de inercia)


Code: [Select]

int RFRICALOR   = 2 ;
int RBOMBA1     = 3 ;
int RBOMBA2     = 4 ;
int RBOMBA3     = 5 ;
int RONOFF      = 6 ;
int LEDFRIO     = 7 ;
int LEDCALOR    = 8 ;
int OFRICALOR   = 9 ;
int OONOFF      = 10 ;
int OBOMBA3     = 11 ;
int OBOMBA2     = 12 ;
int OBOMBA1     = 13 ;

void setup() {
  pinMode( RFRICALOR , OUTPUT);                         // Rele cambio de temporada (abieto invierno, cerrado verano), entrada 1 Tarjeta regulación unidad interior
  pinMode( RBOMBA1 , OUTPUT);                           // Rele bomba planta 1
  pinMode( RBOMBA2 , OUTPUT);                           // Rele bomba planta 2
  pinMode( RBOMBA3 , OUTPUT);                           // Rele bomba planta 3
  pinMode( RONOFF , OUTPUT);                            // Rele Paro / Marcha, entrada 6 Tarjeta de regulación unidad interior
  pinMode( LEDFRIO , OUTPUT);                           // Led modo frio
  pinMode( LEDCALOR , OUTPUT);                          // Led modo calor
  pinMode( OFRICALOR , INPUT);                          // Cambio modo frio / calor
  pinMode( OONOFF , INPUT);                             // Orden Paro / Marcha
  pinMode( OBOMBA3 , INPUT);                            // Orden bomba planta 3
  pinMode( OBOMBA2 , INPUT);                            // Orden bomba planta 2
  pinMode( OBOMBA1 , INPUT);                            // Orden bomba planta 1
}

void loop() {
  int valor1 = digitalRead(OBOMBA1) ;                   // Leemos el valor de la primera planta
  digitalWrite( RBOMBA1, valor1) ;                      // Escribimos valor en RBOMBA1


  int valor2 = digitalRead(OBOMBA2) ;                   // Leemos el valor de la segunda planta
  digitalWrite( RBOMBA2, valor2) ;                      // Escribimos valor en RBOMBA3


  int valor3 = digitalRead(OBOMBA3) ;                   // Leemos el valor de la tercera planta
  digitalWrite( RBOMBA3, valor3) ;                      // Escribimos valor en RBOMBA3

  int valor4 = digitalRead(OONOFF) ;                    // Leemos el valor de la orden paro/marcha
  if ( valor4 == true ) {                               // esto es que hay solicitud de marcha
      int valor5 = digitalRead(OFRICALOR) ;             // Leemos si estamos en modo frio o calor
      if (valor5 == true ) {                            // Esto es que estamos en modo calor
          digitalWrite( RONOFF, true) ;                 // Se enciende el rele RONOFF encendiendo la bomba de calor en modo invierno (calor)
          digitalWrite( LEDCALOR, true) ;               // Se enciende el led rojo
          digitalWrite( LEDFRIO, false) ;               // Se apaga el led azul
          digitalWrite( RFRICALOR, false) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar

      }
      else     {
          digitalWrite( RONOFF, false) ;                // Se apaga el rele RONOFF encendiendo la bomba de calor en modo verano (frío)
          digitalWrite( LEDCALOR, false) ;              // Se apaga el led rojo
          digitalWrite( LEDFRIO, true) ;                // Se enciende el led azul
          digitalWrite( RFRICALOR, true) ;              // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar
      }
  }
  else  {                                               // esto es que hay solicitud de paro

        int valor6 = digitalRead(OFRICALOR) ;           // Leemos si estamos en modo frio o calor
        digitalWrite( RONOFF, !valor6) ;                // Apagamos el rele en modo calor y lo encendemos en modo frio
        digitalWrite( LEDCALOR, valor6) ;               // Encendemos led rojo si esta en modo calor apagamos en modo frio
        digitalWrite( LEDFRIO, !valor6) ;               // Encendemos led azul si esta en modo frio apagamos en modo calor
        digitalWrite( RFRICALOR, !valor6) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar

  }
}


Si todo va cómo debe, y no veo razón para que no sea así, el siguiente paso será pasar de la protoboard a montar de una forma un poco más elegante con la ayuda de un Screw Shield 1.0 y en una caja IP65 para su instalación en la sala de calderas.

Deseadme suerte con esas soldaduras, que soy muy novato, y gracias por seguir este hilo y ayudarme en lo que creáis oportuno.

surbyte

Un error que veo en tu código que no luce como error es que el tuyo aunque sea un ambiente hogareño o semi industrial, puede presentar problemas con los pulsadores.
Los pulsadores suelen rebotar. Y eso genera problemas en el accionamiento de equipos grandes.

Si hasta el momento no has visto comportamientos erráticos, olvidalo pero ten presente este comentario.
Si ocurre, te voy a sugerir una librería que hace lo que se llama una rutina antirebote. Se llama Bounce2 y solo le dices el tiempo que quieres que un valor se confirme en un estado y listo... el devuelve el estado cuando éste esta confirmado.

tu lees esto
Code: [Select]
int valor4 = digitalRead(OONOFF) ; 
Dicho sea de paso es una exageración usar una variable int para leer el estado 0 1 de un switch/pulsador.
Con bool sobra

asi que bien podrias definirlo asi

Code: [Select]
bool valor4 = digitalRead(OONOFF) ; 
y todo lo demás igual.

Werttty

#25
Nov 17, 2017, 07:54 pm Last Edit: Nov 17, 2017, 08:00 pm by Werttty
Buenas!

Cómo no podía ser de otra forma, ya que hay que saber reconocer la experiencia y el conocimiento cuando sobrepasan por tanto los propios, he seguido tu consejo y me he puesto en plan "programador mamporrero" y le he metido un tute al código que ya no lo reconozco ni yo. Admito que no entiendo todo lo que he modificado, pero la cuestión es que me compila, que es mucho más de lo que esperaba. La cosa ha quedado así:

Code: [Select]

#include <Bounce2.h>                                    // Incluimos biblioteca Bounce para eliminar el debouncing producido por los pulsadores / reles de entrada

bool RFRICALOR   = 2 ;
bool RBOMBA1     = 3 ;
bool RBOMBA2     = 4 ;
bool RBOMBA3     = 5 ;
bool RONOFF      = 6 ;
bool LEDFRIO     = 7 ;
bool LEDCALOR    = 8 ;
bool OFRICALOR   = 9 ;
bool OONOFF      = 10 ;
bool OBOMBA3     = 11 ;
bool OBOMBA2     = 12 ;
bool OBOMBA1     = 13 ;

Bounce debouncer1 = Bounce();                           // Iniciado un objeto Bounce
Bounce debouncer2 = Bounce();                           // Iniciado un objeto Bounce
Bounce debouncer3 = Bounce();                           // Iniciado un objeto Bounce
Bounce debouncer4 = Bounce();                           // Iniciado un objeto Bounce
Bounce debouncer5 = Bounce();                           // Iniciado un objeto Bounce

void setup() {
  pinMode( RFRICALOR , OUTPUT);                         // Rele cambio de temporada (abieto invierno, cerrado verano), entrada 1 Tarjeta regulacion unidad interior
  pinMode( RBOMBA1 , OUTPUT);                           // Rele bomba planta 1
  pinMode( RBOMBA2 , OUTPUT);                           // Rele bomba planta 2
  pinMode( RBOMBA3 , OUTPUT);                           // Rele bomba planta 3
  pinMode( RONOFF , OUTPUT);                            // Rele Paro / Marcha, entrada 6 Tarjeta de regulación unidad interior
  pinMode( LEDFRIO , OUTPUT);                           // Led modo frio
  pinMode( LEDCALOR , OUTPUT);                          // Led modo calor

  pinMode( OFRICALOR , INPUT_PULLUP);                   // Cambio modo frio / calor
  debouncer1.attach(OFRICALOR);
  debouncer1.interval(50);                              // intervalo en ms, mas alto por ser un interruptor manual
  pinMode( OONOFF , INPUT_PULLUP);                      // Orden Paro / Marcha
  debouncer2.attach(OONOFF);
  debouncer2.interval(25);                              // intervalo en ms
  pinMode( OBOMBA3 , INPUT_PULLUP);                     // Orden bomba planta 3
  debouncer3.attach(OBOMBA3);
  debouncer3.interval(25);                              // intervalo en ms
  pinMode( OBOMBA2 , INPUT_PULLUP);                     // Orden bomba planta 2
  debouncer4.attach(OBOMBA2);
  debouncer4.interval(25);                              // intervalo en ms
  pinMode( OBOMBA1 , INPUT_PULLUP);                     // Orden bomba planta 1
  debouncer5.attach(OBOMBA1);
  debouncer5.interval(25);                              // intervalo en ms
}

void loop() {

  debouncer1.update();                                  // Actualizar los estados Bounce
  debouncer2.update();                                  // Actualizar los estados Bounce
  debouncer3.update();                                  // Actualizar los estados Bounce
  debouncer4.update();                                  // Actualizar los estados Bounce
  debouncer5.update();                                  // Actualizar los estados Bounce
 
  bool valor1 = debouncer5.read();                      // Leemos el valor de la primera planta
  digitalWrite( RBOMBA1, valor1) ;                      // Escribimos valor en RBOMBA1


  bool valor2 = debouncer4.read();                      // Leemos el valor de la segunda planta
  digitalWrite( RBOMBA2, valor2) ;                      // Escribimos valor en RBOMBA3


  bool valor3 = debouncer3.read();                      // Leemos el valor de la tercera planta
  digitalWrite( RBOMBA3, valor3) ;                      // Escribimos valor en RBOMBA3

  bool valor4 = debouncer2.read();                      // Leemos el valor de la orden paro/marcha
  if ( valor4 == true ) {                               // esto es que hay solicitud de marcha
      bool valor5 = debouncer1.read();                  // Leemos si estamos en modo frio o calor
      if (valor5 == true ) {                            // Esto es que estamos en modo calor
          digitalWrite( RONOFF, true) ;                 // Se enciende el rele RONOFF encendiendo la bomba de calor en modo invierno (calor)
          digitalWrite( LEDCALOR, true) ;               // Se enciende el led rojo
          digitalWrite( LEDFRIO, false) ;               // Se apaga el led azul
          digitalWrite( RFRICALOR, false) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor como debe operar

      }
      else     {
          digitalWrite( RONOFF, false) ;                // Se apaga el rele RONOFF encendiendo la bomba de calor en modo verano (frio)
          digitalWrite( LEDCALOR, false) ;              // Se apaga el led rojo
          digitalWrite( LEDFRIO, true) ;                // Se enciende el led azul
          digitalWrite( RFRICALOR, true) ;              // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor cómo debe operar
      }
  }
  else  {                                               // esto es que hay solicitud de paro

        bool valor6 = debouncer1.read();                // Leemos si estamos en modo frio o calor
        digitalWrite( RONOFF, !valor6) ;                // Apagamos el rele en modo calor y lo encendemos en modo frio
        digitalWrite( LEDCALOR, valor6) ;               // Encendemos led rojo si esta en modo calor apagamos en modo frio
        digitalWrite( LEDFRIO, !valor6) ;               // Encendemos led azul si esta en modo frio apagamos en modo calor
        digitalWrite( RFRICALOR, !valor6) ;             // Indicamos al rele de cabio frio(true)/calor(false) de la bomba de calor como debe operar

  }
}


He actualizado tras eliminar todas las tildes de los comentarios (por si acaso)

Verás que he dado 25ms a todas entradas provinientes de un relé (en el esquema muchos los represento con pulsadores, pero todo son relés excepto el interruptor basculante) y al interruptor basculante le he dado 50ms.

La verdad es que, siguiendo con mi constante abuso de tu tiempo, me gustaría que revisases este nuevo código a ver si te percatas de algún disparate.
Por mi parte, parece que hasta mediados de la próxima semana no podré cargarlo en mi Arduino, así que no podré probarlo físicamente hasta dentro de unos días, pero si tengo un código seguro y estable para entonces, habré avanzado mucho.

Gracias ante todo.

surbyte

Por ahora luce bien. Luego miraré a ver que otro consejo darte.

Werttty

Buenas de nuevo.

Por fin he podido compilar el nuevo código en el Arduino y, ¡sorpresa!, no funcionaba.

Por probar, y porque estaba seguro de que todo lo referente a la biblioteca antirebote lo había hecho bien, he probado de modificar todos los "bool" por "int" otra vez y ¡sorpresa!, ahora funciona perfectamente. No se si tú surbyte le verás la lógica a esto, pero la cuestión es que ahora esto chuta, mientras que del otro modo estaba muerto.

Ya sólo me queda comprar los Display AKO, la caja para montarlo y liarme a soldar el shield y montar cablecitos. Gracias mil por la ayuda, seguiré posteando sobre la marcha del proyecto.

surbyte

La librería dice 

Code: [Select]
// Returns the updated pin state
    bool read();


De modo que debería funcionar.
Sin embargo el ejemplo dice

Code: [Select]
// Get the updated value :
  int value = debouncer.read();


No se que responderte. Debo revisar mis casos.
Yo no uso definiciones como tu dentro del mismo código, las hago locales al comienzo del void loop o globales.

Werttty

¡Seguimos con el proyecto!

Ya he montado la caja con el Arduino y mañana o pasado iré a colocarla en su lugar. En las siguientes fotos puede verse cómo ha quedado por dentro (a falta de conectar todo lo externo al sistema, la señal de los fancoils, las bombas, la maniobra de paro/marcha y el cambio de temporada de la bomba de calor) y cómo queda por fuera a falta de colocar el segundo display Ako (en el momento de montar, sólo tenía uno). Podéis ver cómo al mover el interruptor se apaga o enciende el led correspondiente y el display que le corresponde.







Una vez montado, el sistema respondía a las pruebas según lo esperado, por lo que supongo que no dará mayores problemas una vez instalado.

Ya os mantendré informados.

Go Up