Calentador de agua portatil/ Calefactor / Caravana

Hola

Éste es el primer proyecto que he emprendido en el mundo de arduino.

Se trata de un calentador de agua portátil, para instalar en una caravana, pero que igualmente puede ser adaptado a cualquier otro proyecto que requiera de unas características similares.

Lo que debe de hacer:

  • El sistema estará alimentado por 12Vcc, ojo, los consumos pueden llegar a 15A, para ser alimentado con batería de 12V (coche, caravana, barco, ...) o a 220Vac mediante una fuente conmutada de Pc
  • Medir la temperatura mediante una sonda ntc
  • Dependiendo del valor de la ntc, activar o desactivar un mosfet que actúa como relé, el cual actúa sobre la resistencia calefactora
  • Mediante 2 pulsadores, programar la temperatura de corte, la cual será la que delimite cual será el estado activado o descativado del mosfet
  • Esa programación en la lectura de corte debe almacenarse en la emproom, de modo que no haya que programarla cada vez que se inicie el sistema
  • la información de la temperatura programada y la temperatura actual debe ser mostrada por un lcd, o display, así como el estado activo o no de los mosfet

Lo que llevo hasta ahora

  • Todo lo anteriormente mencionado, usando como display la pantalla de un Nokia 3310, el cual ha dejado de servir como juguete para los críos :wink:
  • Un o algunos problemillas, que me hacen un poco la puñeta y no soy capaz de solventar, de momento, ya que estoy seguro de que ustedes sabréis que me falta para completarlo

He de decir que en todo esto estoy más bien pegado, recien estoy empezando con esto de la programación y demás, y todo lo que he armado y compilado ha sido recopilando información de diferentes fuentes, cogiendo un poco de código de aquí, otro poco de allá, por lo que el primer fallo que hay en todo esto soy yo mismo, jejejeje

No recuerdo todos los sitios que he visitado recopilando información, pero alguno de ellos, ha sido, lógicamente, éste foro, arduino.cc, tdrobotica.co, ardumania.es o arduteka.com

Una imagen del conexionado

Hay varias cosas que se pueden mejorar, y mucho, pero la que más me preocupa es el hecho de que al estar alimentado a 12v, tiene que trabajar el regulador de tensión incorporado en la placa arduino.

Cuando se inicia el sistema, toma lectura de la ntc y evalua si tiene que activar los mosfet o no, pongamos que la temperatura del agua a controlar es inferior a la temperatura de corte programada, por tanto el mosfet se activa, hasta aquí todo bien, de echo probando el circuito en "VACIO" todo va correcto, el tema que me afecta es cuando el sistema tiene "CARGA", la resistencia consume unos 12 amperios, y la fuente de alimentación fluctua en el momento que se activa el mosfet, de hecho la caida de tension se mantiene, llegando a vajar a 11V

Este echo, que en el estado inicial, no me afecta, es decir con el agua fría, ya que la tension baja a 11V y ahí se mantiene, y como tomo lectura de la ntc de un divisor de tensión que está conectado a los 5v de arduino, si ahí no hay 5.0 voltios no pasa nada, porque aunque el valor de la temperatura medido, varía un poco, al mantenerse estable, pues sigue midiendo sobre esa variación (estoy empezando a dudar si me estoy explicando de manera correcta, jejeje) pero al llegar a la temperatura de corte, la carga se libera, por tanto vuelven los 12v y ahí también varían los 5v de arduino, por tanto me da una lectura distinta del valor de la ntc, lo cual hace que se active de nuevo el mosfet cyendo de nuevo hasta 11v, y de ese modo entra en un bucle del que ya no sale.

Soluciones se que hay, un regulador a la entrada de arduino, una fuente independiente para arduino, etc ... pero me gustaría solventarlo con código, mucha idea no tengo, pero tal vez, comparando la tension de entrada (los 12v) o mejor comprovando y comparando que los 5v sean siempre 5, y si varían, que se corrija matemáticamente y no afecte a la ecuación necesaria para la medida de la temperatura????

No se igual lo que intento no se puede, o tal vez si

Aquí el código integro de mi programa

const int led = 13;      // pin de salida led
float analog = A1;   // pin de entrada termistor
float voltIn = A2;
const int mosfet1 = 11;  // pin salida mosfet 1
const int mosfet2 = 12;  // pin salida mosfet 2
const int boton1 = 8;    // pin pulsador +
const int boton2 = 9;    // pin pulsador - 
const int boton3 = 10;   // pin pulsador
int temperatura;
int tempConfig;

byte horquilla = 2; // valor para evitar la histeresis
float tempActual, tempMedia;

byte point, cont;
int boton1Estado, boton2Estado;
int boton1UltimoEstado, boton2UltimoEstado;
byte boton1ContPulsacion, boton2ContPulsacion;
int botonMas, botonMenos, estado;
int calaberaX;

//--------------------------
// datos para las ecuaciones
//--------------------------

float vIn;    // 5.0 por defecto
float rFija = 1000; // resistencia divisora de tension   
float r25 = 15000;  // resistencia NTC a 25º
float beta = 3950;  // beta NTC 3950 por defecto
float t0 = 293.15;  // temperatura de refencia, 293.15 por defecto

float vOut = 0.0;
float rNtc = 0.0;

float tempK = 0.0;
float tempC = 0.0;

float voltios = 0.0;
float lectura;

//---------
//Funciones
//---------

void activado();           //Funcion Estado ACTIVADO de las salidas
void desactivado();        //Funcion Estado DESACTIVADO de las salidas
void inicio();
void pantalla();

#include <PCD8544.h>
#include <math.h>
#include <EEPROM.h>

static PCD8544 lcd;
byte addr=0;
byte valor= EEPROM.read(addr);
int referencia = valor; // temperatura de referencia
int tempProg = referencia;

// Grafico sonrisa
static const byte glyph[] = 
{ 
  B00010000, B00110100, B00110000, B00110100, B00010000 };

// Imagen Angela
static const byte angela_ancho = 84;
static const byte angela_alto = 48;
static const byte angela [] = {
	 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xBC,0xBC,0xB8,0xB8,0x78,0x38,0x31,0x31,0x31,0x31,0x31,0x39,0x19,0x1D,0x1F,0x1D,0x0E,0x0C,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

};

// Imagen Calabera
static const byte calabera_ancho = 84;
static const byte calabera_alto = 48;
static const byte calabera [] = {
	 	0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x06,0x06,0x07,0x07,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x03,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

//-----------------
//Funcion principal
//-----------------

void setup() 
{
  lcd.begin(84, 48);
  pinMode (led, OUTPUT);    // configura led como salida
  pinMode (analog, INPUT);  // configura termistor como entrada
  pinMode (voltIn, INPUT);  
  pinMode (mosfet1, OUTPUT);  // configura mosfet1 como salida
  pinMode (mosfet2, OUTPUT);  // configura mosfet2 como salida
  digitalWrite (boton1, LOW);
  digitalWrite (boton2, LOW);
  digitalWrite (boton3, LOW);

  //Pantalla Iniciando
  lcd.setCursor(0,0);
  lcd.createChar(0,glyph); // añade el grafico sonrisa a la posicion "0" de la tabla ASCII
  lcd.drawBitmap(angela, angela_ancho, angela_alto );
  delay(2 *1000);
  lcd.print("Iniciando ");
  delay(0.5 *1000);

  for (point=0; point<4 ; point++)
  {
    lcd.print(".");
    delay(0.4 *1000);
  }

  lcd.setCursor(20, 2);
  lcd.print("Virtudes");
  lcd.setCursor(17, 3);
  lcd.print("Te Quiero");
  delay(1 *1000);
  digitalWrite (led, LOW);
  digitalWrite (mosfet1, LOW);
  digitalWrite (mosfet2, LOW);
  lcd.setCursor(0, 5);
  lcd.print("Mosfet ");
  lcd.print("OFF --)");
  delay(1 *1000);
  lcd.clear();
  delay(0.5 *1000);

  lcd.setCursor(20, 3);
  lcd.print("Midiendo");
  lcd.setCursor(5, 5);
  lcd.print("####>> ");
  for (point=0; point<5 ; point++)
  {
    lcd.write(0);     // escribe el grafico sonrisa
    delay(0.5 *1000);
  }
  for (int addr = 0; addr < 512; addr++)
    EEPROM.write(addr, valor);
}

//--------------- 
//Funcion Ciclica
//---------------

void loop(){
  lcd.setCursor(0, 0);
  lcd.print("Temp prog ");
  lcd.print(tempProg);
  lcd.print(" C");
  lcd.setCursor(0, 1);
  lcd.print("-----)*(-----");

  botonMas = digitalRead(boton1);
  botonMenos = digitalRead(boton2);

    if ((botonMas) || (botonMenos)== HIGH){
    tempConfig = HIGH;
     calaberaX = LOW;}
    else if ((botonMas) || (botonMenos)== LOW){
      tempConfig = LOW;
      calaberaX = LOW;}
     
    if ((botonMas) && (botonMenos) == HIGH)
    {
    tempConfig = LOW;
    calaberaX = HIGH;
    }

    
    switch (calaberaX){
      case HIGH:
pantalla();
break;
case LOW:
break;}
    
    
//if (botonMas == HIGH)
//estado = 1;
//else if (estado = 0);
//if (botonMenos == HIGH)
//estado = 2;
//else if (estado = 0);

switch (tempConfig){
  case LOW:
    desactivado();
    break;

  case HIGH:
    activado();
    break;
  }

  delay (0.3 *1000);
}

void activado(){

  lcd.clear();
  
  switch (botonMas) {
  case HIGH:
    tempProg = (tempProg+1);
    lcd.setCursor(0, 0);
    lcd.print("Temp prog ");
    lcd.print(tempProg);
    lcd.print(" C");
    lcd.setCursor(0, 1);
    lcd.print("- + -)+(- + -");
    lcd.setCursor(0, 3);
    lcd.print("- + -)+(- + -");
    valor = tempProg;
    EEPROM.write(addr, valor); 
    delay(0.3 *1000);
    break;
    
    case LOW:
    break;
  }
  
  switch (botonMenos){
    case HIGH:
    tempProg = (tempProg-1);
    lcd.setCursor(0, 0);
    lcd.print("Temp prog ");
    lcd.print(tempProg);
    lcd.print(" C");
    lcd.setCursor(0, 1);
    lcd.print("-(-)-)-(-(-)-");
    lcd.setCursor(0, 3);
    lcd.print("- - -)-(- - -");
    valor = tempProg;
    EEPROM.write(addr, valor); 
    delay(0.3 *1000);
    break;
    
    case LOW:
    break;}


  lcd.setCursor(0, 5);
  lcd.print("Configurando");
}


void desactivado(){
  for (cont=0; cont<5; cont++)
  {
   float lectura = (analogRead(voltIn));
   voltios = (((lectura *5) / 1024) * 2);
   vIn = voltios;
    vOut=(vIn/1024)*(analogRead(analog));
    rNtc=(vIn*rFija)/(vIn-vOut);
    tempK = beta/(log(rNtc/r25)+(beta/t0));
    tempC = tempK-273.15;
    tempMedia = tempMedia+tempC;
    delay (0.2 *1000);
  }

  tempMedia = tempMedia/(cont+1);
  tempActual = tempMedia;

  lcd.setCursor(0, 3);
  lcd.print("Temp: ");
  lcd.print(tempActual);
  lcd.print(" C");
  lcd.setCursor(6,4);
  lcd.print("VIn:  ");
  lcd.print(voltios);
  lcd.print(" V");

  if (tempMedia > tempProg)
  {
    digitalWrite (led, LOW);
    digitalWrite (mosfet1, LOW);
    digitalWrite (mosfet2, LOW);
    lcd.setCursor(0, 5);
    lcd.print("Mosfet ");
    lcd.print("X-X OFF");
    lcd.setCursor(0,2);
    lcd.print("XXX--XXX--XXX");

  }
  else if (tempMedia < (tempProg-horquilla))
  {
    digitalWrite (led, HIGH);
    digitalWrite (mosfet1, HIGH);
    digitalWrite (mosfet2, HIGH);
    lcd.setCursor(0,2);
    lcd.print("             ");
    lcd.setCursor(0,2);
    for (cont=0; cont<7; cont++)
    {
      lcd.write(0);
      lcd.print(" ");
      delay (0.2 *1000);
    }
    lcd.setCursor(0, 5);
    lcd.print("Mosfet ");
    lcd.write(0);
    lcd.write(0);
    lcd.write(0);
    lcd.print(")");
    lcd.print(" ON");
  }
}

void pantalla(){
  lcd.clear();
    lcd.drawBitmap(calabera, calabera_ancho, calabera_alto );
  delay(3 *1000);
    lcd.clear();

}

Y ésta es la parte del código donde toma lectura tanto de los 5v como de la resistencia de la ntc para medir la temperatura

void desactivado(){
  for (cont=0; cont<5; cont++)
  {
   float lectura = (analogRead(voltIn));
   voltios = (((lectura *5) / 1024) * 2);
   vIn = voltios;
    vOut=(vIn/1024)*(analogRead(analog));
    rNtc=(vIn*rFija)/(vIn-vOut);
    tempK = beta/(log(rNtc/r25)+(beta/t0));
    tempC = tempK-273.15;
    tempMedia = tempMedia+tempC;
    delay (0.2 *1000);
  }

  tempMedia = tempMedia/(cont+1);
  tempActual = tempMedia;

  lcd.setCursor(0, 3);
  lcd.print("Temp: ");
  lcd.print(tempActual);
  lcd.print(" C");
  lcd.setCursor(6,4);
  lcd.print("VIn:  ");
  lcd.print(voltios);
  lcd.print(" V");

  if (tempMedia > tempProg)
  {
    digitalWrite (led, LOW);
    digitalWrite (mosfet1, LOW);
    digitalWrite (mosfet2, LOW);
    lcd.setCursor(0, 5);
    lcd.print("Mosfet ");
    lcd.print("X-X OFF");
    lcd.setCursor(0,2);
    lcd.print("XXX--XXX--XXX");

  }
  else if (tempMedia < (tempProg-horquilla))
  {
    digitalWrite (led, HIGH);
    digitalWrite (mosfet1, HIGH);
    digitalWrite (mosfet2, HIGH);
    lcd.setCursor(0,2);
    lcd.print("             ");
    lcd.setCursor(0,2);
    for (cont=0; cont<7; cont++)
    {
      lcd.write(0);
      lcd.print(" ");
      delay (0.2 *1000);
    }
    lcd.setCursor(0, 5);
    lcd.print("Mosfet ");
    lcd.write(0);
    lcd.write(0);
    lcd.write(0);
    lcd.print(")");
    lcd.print(" ON");
  }
}

he añadido esto, pero no lo he probado aún con la carga, pero no se así estará o no bien para que compare la tensión real de 5v y que la utilice en la ecuación, lógicamente he añadido al circuito un divisor de tensión más, para poder comparar la entrada analógica voltIn

   float lectura = (analogRead(voltIn));
   voltios = (((lectura *5) / 1024) * 2);
   vIn = voltios;

Filtra las lecturas de temperatura o añade una histieresis.

Si la señal analogica está bien, aunque en las placas Arduino brillan por lo bien que está concebido el bloque analógico, el regulador debería aislarte de los cambios de tensión en la alimentación de 5V.

Por otro lado, mira a ver cómo de cerca o lejos está la manguera de 12A del sensor de temperatura y el cable que va a la pista analógica. Por último ponle una resistencia de entre 100Ohms a 1K a la base del FET y su correspondiente pull-up o down dependiendo de si es canal N o P.

Hola, gracias por tu respuesta, efectivamente el regulador de arduino funciona de maravilla

Ya he solucionado el problema, y es que la ntc se me había fastidiado ¿?¿? le he cambiado por otra y listo, todo resuelto

En cuanto a la resistencia pull-down para el mosfet, no había pensado que le hiciera falta, creía que mayormente se usan en pulsadores, para evitar errores de lectura de estado, pero al ser el pin del mosfet de salida, pues pensé que no era necesario, le he colocado una de 10K según la imagen, y también le he puesto una resistencia de 1K a la base del mosfet, como me recomendabas, de modo que el circuito se ha quedado así y ahora es bastante estable.

Perfecto! Un saludo.