Proyecto control de temperatura para nevera

Buenas noches, quiero hacer un control de temperatura para una nevera, trabajo con un arduino uno y una sonda DS18B20, la idea principal es que cuando prenda la neverita ella debe tener un ciclo de espera, eso es fácil porque se hace un delay, después ella debe prenderse y bajar hasta 2° cuando llegue a este margen debe apagarse y volverse a prender cuando este en 8° lo primero que pensé en hacer fue en hacer un if que estuviera entre 2 y 8, pero tengo el problema que la nevera empieza con 28° entonces me toca hacer el primer ciclo de enfriamiento hasta 2 y después el ciclo repetitivo de 2 y 8, intente hacerlo con if y anidarlo pero no e encontrado la manera de hacerlo, agradezco cualquier asesoría les anexo el código que llevo, ella va ir a un rele que es el encargado de prender y apagar la neverita

#include <OneWire.h>
#include <DallasTemperature.h>
 // Pin donde se conecta el bus 1-Wire
#define pinData 2
// Instancia a las clases OneWire y DallasTemperature
OneWire oneWire(pinData); //se estancia la libreria dallas
DallasTemperature sensors(&oneWire);
int TEMP ;
int RELE = 4;
void setup(){
  Serial.begin(9600);
  sensors.begin();
  pinMode(RELE, OUTPUT);
}

void loop(){
  TEMP = (sensors.getTempCByIndex(0));
 temperatura();
  pantalla();
        } 
void pantalla(){
  sensors.requestTemperatures();
  Serial.print(TEMP); //se mide en centigrados
  Serial.println("°C");
  delay(1000);
}
void temperatura(){
  digitalWrite(RELE, LOW);
   if (TEMP < 2){
    digitalWrite(RELE, HIGH);
    }
   else{ digitalWrite(RELE, HIGH);
   }
}

EL truco está en sólo en cambiar el esto del pin cuando se sobrepasa alguno de los umbrales:

void temperatura(){
   if (TEMP < 3) digitalWrite(RELE, HIGH);
   else if (TEMP > 7) digitalWrite(RELE, LOW);
}

Así, el relé se activará solo cuando la temperatura alcance o supere los 8 grados; y se desactivará cuando alcance los 2 grados o menos. Mientras se mantenga dentro del rango nada va a cambiar porque en ese entonces se está esperando a que se enfríe o se caliente lo suficiente para reaccionar.
Cuando alcanza los 8 grados, se enciende pero no se apaga hasta que alcance los 2 grados; y viceversa: apaga a los 2 grados, pero no se enciende hasta que alcance los 8 grados.

Cambié los umbrales porque al medir la temperatura como un valor entero, el sistema se hubiera apagado hasta alcanzar 1 grado o menos, y se hubiera encendido a partir de 9; en vez de los supuestos 2 y 8.

PD: si la nevera es de compresión-evaporación (distinguido en la parte trasera por una pieza negra y redondeada de la que salen tres tubos), sería prudente colocar unos 5 minutos de espera antes de arrancar el sistema en caso de un corte de energía eléctrica (y aunque la temperatura ya alcanzara los 8 grados porque podría ser un error del termómetro).

Aquí te hice un código (sin probar) con la opción de agregarle un potenciómetro en el pin A0 para el control de temperatura de 0° a 15° pero puedes anularlo y dejar una valor TEMP fijo.

Al encender arduino tardará 30 segundos en tomar la primera temperatura y así sucesivamente.

#include <OneWire.h>
#include <DallasTemperature.h>
 // Pin donde se conecta el bus 1-Wire
#define pinData 2
// Instancia a las clases OneWire y DallasTemperature
OneWire oneWire(pinData); //se estancia la libreria dallas
DallasTemperature sensors(&oneWire);
DeviceAddress outsideThermometer;
int TEMP;
byte MargenTemp = 3; 
int ValPot = 0;
int RELE = 4;
byte RelayEstatus = 0;

void setup(){
  Serial.begin(9600);
  sensors.begin();
  pinMode(RELE, OUTPUT);
  digitalWrite(RELE,HIGH);
}

void loop(){
  unsigned long currentMillis = millis();
  if (currentMillis % 30000 < 3) {
    MideTemperatura();
    delay(3); 
  }
}
     
void MideTemperatura() {
    if (sensors.getAddress(outsideThermometer, 0)) {  // Si hay comunicación con el sensor DS18B20
      sensors.requestTemperatures();   //Se envía el comando para leer la temperatura
      TEMP = sensors.getTempCByIndex(0); //Se obtiene la temperatura en ºC
      Termostato();
    }
    else  {  // Si no hay comunicación con el sensor porque se ha cortado el cable, etc.
      Serial.print("Falla el sensor"); // Falla el sensor
    }
}

void Termostato() {
  ValPot = analogRead(A0);  // Usar un potenciómetro con el pin central a A0, un extremo a +5v y el otro a masa.
  ValPot = map(ValPot, 0, 1023, 0, 15);
  // ValPot = 2;  // Valor fijo de temperatura de corte // Descomentar si no se usa potenciómetro para ajustar
  Serial.print("La temperatura es: ");
  Serial.print(TEMP); //se mide en centigrados
  Serial.println("°C");
  
      if (TEMP < ValPot and RelayEstatus == 0  ) { 
        digitalWrite(RELE,HIGH); RelayEstatus=1; // Apaga el rele
        Serial.print("Nevera apagada"); 
        } 
      
      if (TEMP > ValPot + MargenTemp and RelayEstatus == 1) {
        digitalWrite(RELE,LOW); RelayEstatus=0; // Activa el rele
        Serial.print("Nevera encendida"); 
        }  
}

Gracias Lucario448 me sirvio bastante, estoy ahora es colocandole el temporalizador al arranque de la nevera que sea de 5 minutos, pero con delay no e podido hacerlo porque se me suben todos los tiempos estoy intentando con milis, tambien algo asi como lo dijo Daniel_Arg, modificar la temperatura tanto de apagado como de encendido de la maquina por boton, pero eso toca poco a poco, al igual muchas gracias por su colaboracion en el proyecto :slight_smile:

En un còdigo donde debes mantener una temperatura un delay de 5 minutos te dejaría 5 minutos sin verificar el valor de la temperatura, asi que tu ciclo puede pasarse de frio o descongelarse en exceso.
NO USES DELAY.
El ejemplo de @Daniel_Arg incluye el uso de millis().
Si no entiendes millis() ve a Documentación => Indice de temas tutoriales => millis() e infórmate al respecto.

Tu código debe ser tal que la consulta de temperatura se haga en todo momento para asegurar el control de tu nevera en este caso.

buenos dias, les cuento que tengo el proyecto de esta manera, la nevera esta prendiendo a los -5 grados y esta apagando la los -15 grados con un tiempo de arranque de 5 minutos, ahora quiero hacerle un menu donde me deje cambiar estos valores con 4 botones y que me guarde estos valores cuando falle la energia,

//libreria de pantalla
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

#include <OneWire.h>
#include <DallasTemperature.h>
 // Pin donde se conecta el bus 1-Wire
#define pinData 2
// Instancia a las clases OneWire y DallasTemperature
OneWire oneWire(pinData); //se estancia la libreria dallas
DallasTemperature sensors(&oneWire);
int TEMP ; 
int RELE = 4;  
int ENCENDIDO;
int APAGADO; 
unsigned long time;
//pines de conexion sensor 2, rele el 4 pantalla a4 sda y a5 scl
void setup(){
  Wire.begin();    // Inicia el puerto I2C
  lcd.init();
 lcd.backlight();
 lcd.clear();
  Serial.begin(9600); //inicia comunicacion con pc
  sensors.begin();    //inicia el sensor
  pinMode(RELE, OUTPUT);
  digitalWrite(RELE, LOW);  //inicia el rele apagado

  }

void loop(){
  time = millis(); //registro de tiempo de encendido
  
   TEMP = (sensors.getTempCByIndex(0));
 temperatura();
  pantalla();
  ENCENDIDO = -15;
  APAGADO = -5;
  
   } 
void pantalla(){
  sensors.requestTemperatures();
  Serial.print(TEMP); //se mide en centigrados
  Serial.println("°C");
  Serial.print(sensors.getTempCByIndex(0));
  Serial.println("°C");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temp:");
  lcd.print(sensors.getTempCByIndex(0));
  lcd.setCursor(11, 0);
  lcd.print("T=");
  lcd.print(millis()/60000);
  lcd.setCursor(0, 1);
  lcd.print("E:");
  lcd.print(ENCENDIDO);
  lcd.setCursor(6, 1);
  lcd.print("A:");
  lcd.print(APAGADO);
  lcd.setCursor(11, 1);
  lcd.print("TE:5");
 
}
void temperatura(){
  if (time > 300000){                                        //tiempo de espera del rele en milisegundos
   if (TEMP <= APAGADO) digitalWrite(RELE, LOW);           //comprobacion de arranque de nevera temperatura final al inicio (temperatura minima)
   else if (TEMP >= ENCENDIDO) digitalWrite(RELE, HIGH);      //temperatura de apagado de la nevera (temperatura maxima)
   }

}

este es el codigo que tengo hasta ahora, ya cree las variables para poder cambiar la temperatura ya mire varios videos de como hacer los menus pero ninguno me guarda datos para falla electrica

Te hice un código por el cual no has dado ningún comentario.

En 10 minutos podría agregar al código que te ofrecí un menú con encoder y que grabe en la eeprom la temperatura.

¿Crees que me sobran ganas de hacerlo?

No pide un menu con encoder sino con 4 botones.
Existen librerías que lo hacen de modo muy simple.

MENWIZ
Menubackend

y la mejor para mi gusto
LCDMenuLib2

max 254 menu elements
max 254 menu elements per layer
based on a tree model (parent, child, sibling)
max support for 6 buttons up, down, left, right, back/quit, enter
min 3 buttons needed up, down, enter
separation of structural and functional level
support for screensaver which is shown after x seconds
display a scrollbar when more menu elements in a layer then display rows
the menu function are only updated when a button is hit or a trigger is set
it is possible to set special conditions to display an element
it is possible to change parameter direct from the menu
possibility to jump from one menu element directly to another
examples for many different LCD libraries
examples for different functionality (change param, set params, ...)

y mira que fácil puede elegir entre estas opciones

// (0) Control over serial interface  with asdw_e_q
// (1) Control over one analog input
// (2) Control over 4 - 6 digital input pins (internal pullups enabled)
// (3) Control over encoder [third party lib] (Download: https://github.com/PaulStoffregen/Encoder)
// (4) Control with Keypad  [third party lib] (Download: http://playground.arduino.cc/Main/KeypadTutorial )
// (5) Control with an IR remote [third party lib] (Download: https://github.com/z3t0/Arduino-IRremote )
// (6) Control with a joystick
// (7) Control over I2C PCF8574
// *********************************************************************

#define _LCDML_CONTROL_cfg      0

0 Control x puerto serie
1 con entrada analogica como cuando usas el LCD Keyboard Shield de arduino
2 con botones desde 4 a 6
3 con Enconder
4 con Keypad matricial
5 con IR remote control
6 con Joystick
7 via I2C PCF8574

Miras los ejemplos y cuando entiendas la lógica veras lo simple que es.

surbyte:
No pide un menu con encoder sino con 4 botones.

¿Y que?

Para fijar la temperatura de un termostato le sobra con un pulsador y hasta podría ser el mismo contacto de la luz de la nevera, que además podría hacer sonar un buzzer en caso de que la puerta quede abierta.

De esta forma entraría a la programación.
setup()

if (digitalRead(BotonPuerta) == HIGH) {
delay(1500);
if (digitalRead(BotonPuerta) == LOW) {
AjustaTemp();
}
}
Solo tendría que abrir la puerta, conectar la nevera y cerrar la puerta antes de un segundo y medio.

¿Y porque no prescindir de la pantalla usando beeps del buzzer que representen los grados ajustados?

Todo esto, incluso con pantalla alcanza con un attiny85

¿Y que?

Para fijar la temperatura de un termostato le sobra con un pulsador y hasta podría ser el mismo contacto de la luz de la nevera, que además podría hacer sonar un buzzer en caso de que la puerta quede abierta.

Y si le sobra con un pulsador para que sugieres un encoder?

En 10 minutos podría agregar al código que te ofrecí un menú con encoder y que grabe en la eeprom la temperatura.

Yo le di sugerencias y librerías para lo que el pidió. Nada mas.

surbyte:
Y si le sobra con un pulsador para que sugieres un encoder?

¿Quien le sugiere un encoder? El texto es claro y dice que es el tiempo que me llevaría hacerlo de esa forma, que por desatento o desagradecido te quitan las ganas de ayudar. Ni se tomo la molestia de cargar el código, aunque cuando lea este mensaje diga otra cosa.

Cuando escribes un código para otra persona ¿No esperas al menos que lo pruebe?

El usuario puede creer que necesita hacer un menú pero, estamos hablando de una nevera donde No hay que establecer dos valores de temperatura, basta con un valor solo y luego definir lo que sería la histéresis.

¿Es necesario hacer un menú y aprender a manejar una librería para ello? Sobre todo para alguien que manifiesta no entender el tema de los millis().

Habiendo solo dos datos que mostrar ni siquiera es necesario hacer un lcd.clear durante el programa.

Aquí va el código con solo un pulsador donde clic baja el valor, doble clic lo aumenta y manteniendo presionado lo graba en la memoria eeprom.

Incluye una animación en pantalla para cuando el motor se encuentra en marcha y un apagado del mismo por si falla el sensor de temperatura.

/*
 * Arduino nano pinout:
 *             _______________
 *            |      USB      |
 *            |13           12| 
 *            |3V3          11|  
 *            |AREF         10| Relay
 *            |A0            9| 
 *            |A1            8| 
 * Pulsador   |A2            7| 
 * DS18B20    |A3            6| 
 *RTC LCD SDA |A4            5| 
 *RTC LCD SCL |A5            4| 
 *            |A6            3| 
 *            |A7            2| 
 *            |5V          GND|
 *            |RST         RST|
 *            |GND   1/INT2/RX|
 *            |VIN   0/INT3/TX|
 *            |MISO         SS|
 *            |SCK        MOSI|
 *            |_______________|
 *
*/
 /*  LIBRERIAS NECESARIAS PARA EL FUNCIONAMIENTO DEL CODIGO
 */


#include <DallasTemperature.h>
#include "OneButton.h"
OneButton button(A2, true);

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7);

#include <EEPROM.h>

OneWire oneWire(A3); //se estancia la libreria dallas
DallasTemperature sensors(&oneWire);
DeviceAddress outsideThermometer;

int TempVal;  // Valor de temperatura establecido
float Frio;   // Valor capturado por el sensor

int Relay = 10;  // Pin salda para el Relay
byte RelayEstatus = 0;
byte cursor = 0;

int tmax = 5;  
int tmin = -15;
int MargenTemp = 3;  // Histéresis de temperatura

void setup() {
  lcd.begin(16, 2);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);  
  
  pinMode(Relay, OUTPUT);
  digitalWrite(Relay,HIGH);
  
  button.attachClick(click);
  button.attachDoubleClick(doubleclick);
  button.attachLongPressStart(longPressStart);
  
  if (EEPROM.read(50) == 255) EEPROM.put(0,-5);  // Si es la primera vez que se graba en la eeprom
  EEPROM.get(50 , TempVal); // Establece el valor de lo previamente guardado

  sensors.requestTemperatures();
  delay(1000);
  lcd.setCursor(0,0);
  lcd.print("T: ");
  MideTemperatura();
  lcd.setCursor(10,0);
  lcd.print("E:");
  lcd.setCursor(12,0);
  lcd.print(TempVal);lcd.print("\337");

}

void loop() {
  unsigned long currentMillis = millis();
  button.tick();
  
  if (currentMillis > 60000) {  // Pasado el primer minuto de arranque del programa
    if (currentMillis % 20000 < 3) {  // Cada 20 segundos 
      MideTemperatura();  // Mide la temperatura
      Termostato();       // Consulta el termostato
      delay(3);
     }
   }

   if(RelayEstatus == 1) {  // Si el motor esta funcionando muestra en pantalla una animación
    if (currentMillis % 1000 < 2) {  // Por cada segundo transcurrido
      lcd.setCursor(cursor,1);
      lcd.print(" ");
      cursor++;
      if (cursor > 15) cursor = 0;
      lcd.setCursor(cursor,1);
      lcd.print("*");
      delay(2);
    }
   }

}

void click() {   //  Baja la temperatura establecida y la muestra en pantalla
  TempVal--;
  if(TempVal < tmin) TempVal = tmin;
  lcd.setCursor(12,0);
  lcd.print("    ");
  lcd.setCursor(12,0);
  lcd.print(TempVal);lcd.print("\337");
}

void doubleclick() {  // Sube la temperatura establecida y la muestra en pantalla
  TempVal++;
  if(TempVal > tmax) TempVal = tmax;
  lcd.setCursor(12,0);
  lcd.print("    ");
  lcd.setCursor(12,0);
  lcd.print(TempVal);lcd.print("\337");
}

void longPressStart() {  // Graba en la eeprom ell valor establecido
  EEPROM.put(50 , TempVal);
  lcd.setCursor(cursor,1);
  lcd.print(" ");
  lcd.setCursor(0,1);
  lcd.print("** Guardado **");
  delay(1500);
  lcd.setCursor(3,1);
  lcd.print("                ");
}

void MideTemperatura() {
    if (sensors.getAddress(outsideThermometer, 0))  {  // Si hay comunicación con el sensor DS18B20
      sensors.requestTemperatures();   //Se envía el comando para leer la temperatura
      Frio = sensors.getTempCByIndex(0); //Se obtiene la temperatura en ºC
      lcd.setCursor(3,0);
      lcd.print("    ");
      lcd.setCursor(3,0);
      lcd.print(Frio,1); // Imprime la temperatura con un decimal
      lcd.print("\337"); // Imprime simbolo °
    }
    else  {  // Si no hay comunicación con el sensor porque se ha cortado el cable, etc.
      lcd.clear();
      lcd.setCursor(2,1);
      lcd.print("Falla sensor"); // Falla el sensor.
      digitalWrite(Relay,HIGH);  // Apaga el motor.
      while(1){ }  // Detiene el programa.
    }
}

void Termostato() {
      if (Frio <= TempVal) {
        digitalWrite(Relay,HIGH); RelayEstatus = 0;  // Apaga el rele
        lcd.setCursor(0,1); lcd.print("                ");
        }
      if (Frio > TempVal + MargenTemp) {
        digitalWrite(Relay,LOW); RelayEstatus = 1;  // Activa el rele
        }
}

Saludos

Amigos muchas gracias por su ayuda y colaboracion gracias Daniel_arg, por ese codigo voy a mirarlo y aplicarlo, cualquier cosa estoy escribiendo, tambien gracias a surbyte, por lo de los menus, voy a profundizar mas en ese tema porque me parecio muy interesante, ya e visto bastantes videos por youtube porque quiero aprender bastante de arduino, acepto sugerencias de donde estudiar para poder aprender mas, quiero aprender a programar desde lo basico(sabiendo que ya e hecho varios de los ejemplos que vienen en arduino) hasta obtener un buen nivel, al igual muchas gracias por su ayuda :slight_smile: :smiley: :smiley:

picojohn:
ese codigo voy a mirarlo y aplicarlo, cualquier cosa estoy escribiendo

Hola, acabo de modificar el código para que tengas el dibujo de los pines. El display debe ser adaptador
I2C. Con esta base que ya es bastante podes mejorarlo poniendo una alarma de puerta abierta. Las heladeras o neveras "No frost" traen un calefactor que se enciende unos momentos durante el día para descongelar el radiador, eso es algo que también lo puedes agregar y no olvidar que traen unn electroventilador.

Aquí tienes un canal de Youtube que da cursos de arduino con mucha paciencia y explicación. Saludos