Arduino controlled 12v cooler

Hello forum, I am kinda new to Arduino but only because I need something to make to drive me to learn, so here is what I need;

I have in my work truck a Coleman 12volt TEC cooler. This is basicly a picnic cooler that cools with 12v instead of ice. You plug it in, it runs constantly, not even a power switch. Problem is that it works too well, my items often freeze. What I thought would be fun would be to use say a tiny, or a nano to monitor a thermistor and compare the temp it gets to a temp that I could set with a knob or buttons. I would also love a display (7 segment or LCD) to show desired and current temp. It draws about 5amps @12volts so I figure a relay will be needed. I have tons of Arduino parts and stuff kicking about that I can use.

The only other feature I would like to include is a dual pole dual throw DPDT relay to facilitate reversing power to the TEC so that turning the desired temp above current would flip the power to the TEC so that it would keep food warm if needed.

What I want to know is if this, or something really similar has already been done. I tried searching without luck.

Also, do TEC coolers modules work better with constant power, or pwm? Anyone know? If pwm makes them work better, the Arduino could handle driving a FET or something to facilitate this.

I know that I could just go on eBay or the like and buy a capillary tube based fridge tstat, (except this wouldn't do the heating, I know this) but I want to do this with an Arduino, I have like 8 of them kicking around. Also mega cool factor.

Comments or advise would be awesome.

Thanks in advance, hope to get going soon with it, with your help. Cheers.

The temperature falling or rising slow, so you don't need pwm. Just turn them on and off.
You can use PID, the library is ment for analog output, but there is also an example for relay output.
http://playground.arduino.cc/Code/PIDLibrary

If you use it to heat something, will the plastic melt ?

To switch 5A, a relay can be used, but also a mosfet. You have to be careful with a mosfet and how the current is going through your circuit.

What kind of temperature range would you like to measure ?
A thermistor is a simple sensor.

(click on 'Tutorial' and on the third one "Thermistor, Measure temperature using a resistor!".

Example of heater with display:

Update

I have finished my Coleman Cooler modifications now, and it holds between 8c and 8.5c.

No more freezing, which is what I wanted in the beginning.

There are no controls on the outside, it is just programmed in code on the Arduino Nano v3.

here is the code, please comment on any ways you think I could shrink this down to less than 6k, I would love to use a Tiny or a teensy in here instead of a Nano.

Thanks
Michael

/* This is the sketch to go along with the Coleman 12Volt TEC Cooled Cooler.
by Michael Illingby 3/10/2014
I was tired of having it freeze my beverages, which it did in a couple hours.

This is intended to monitor a OneWire temp sensor, and activate a 5v relay 
that is interupting the power to the cooling system. Hopefully I will now 
just have COLD Red Bull, instead of Red Bull Popsicles. :)

Lines 105 -109 are where I set the temperature and padding.
*/


// The DallasTemperature library 
// http://milesburton.com/Dallas_Temperature_Control_Library

#include <OneWire.h>

OneWire  ds(3);  // on pin 10 (a 4.7K resistor is necessary)
int relay = 2; // Pin that relay signal pin is connected to

void setup(void) {
  Serial.begin(9600); // Open serial monitor to watch temp for debugging
  pinMode(relay, OUTPUT); // this is the signal wire to relay board 5v
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;
  
  if ( !ds.search(addr)) {
    
    ds.reset_search();
    delay(250);
    return;
  }
  
  for( i = 0; i < 8; i++) {
    Serial.write(' ');

  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    case 0x22:
      type_s = 0;
      break;
    default:
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // delay between polling OneWire Chip 750ms is MIN, I choose between 10-60 seconds
                    // Longer delay reduces 
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }
  
  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0; // convert output from sensor to Celsius


    if (celsius <= 8) {
            digitalWrite(relay, LOW); //De-energize the relay, where at or below temp
            Serial.print("Standby Mode - Current Temp in Celsius ");
    }
    else if (celsius >= 8.5){
            digitalWrite(relay, HIGH); //Energize the relay for cooling, we are above temp
            Serial.print("Cooling Mode - Current Temp in Celsius ");
    }

  // print the analog value:
  Serial.println(celsius); // Print debugging info to serial monitor showing mode and temp
  
}

Coleman_OneWire_Temp_Control.ino (3.33 KB)

here is the code, please comment on any ways you think I could shrink this down to less than 6k, I would love to use a Tiny or a teensy in here instead of a Nano.

Now it's working you can get rid of all references to serial; that pulls it well below 6K

Updated again to include LCD

It now shows whats going on using the LCD

Heres the code;

/* This is the sketch to go along with the Coleman 12Volt TEC Cooled Cooler.
by Michael Illingby 3/10/2014
I was tired of having it freeze my beverages, which it did in a couple hours.

This is intended to monitor a OneWire temp sensor, and activate a 5v relay 
that is interupting the power to the cooling system. Hopefully I will now 
just have COLD Red Bull, instead of Red Bull Popsicles. :)

Updated 5-15-14 : Now outputs current temp on a 16x2 LCD so I know just how cold everything is in there.

Lines 109-125 are where I set the temperature and padding.
*/


// The DallasTemperature library 
// http://milesburton.com/Dallas_Temperature_Control_Library

#include <OneWire.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

OneWire  ds(A3);  // on pin 10 (a 4.7K resistor is necessary)
int relay = A0; // Pin that relay signal pin is connected to

void setup(void) {
  Serial.begin(9600); // Open serial monitor to watch temp for debugging
  pinMode(relay, OUTPUT); // this is the signal wire to relay board 5v
  lcd.begin(16,2);
  
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;
  
  if ( !ds.search(addr)) {
    
    ds.reset_search();
    delay(250);
    return;
  }
  
  for( i = 0; i < 8; i++) {
    Serial.write(' ');

  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    case 0x22:
      type_s = 0;
      break;
    default:
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // delay between polling OneWire Chip 750ms is MIN, I choose between 10-60 seconds
                    // Longer delay reduces 
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }
  
  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0; // convert output from sensor to Celsius

    if (celsius <= 6) {
            digitalWrite(relay, LOW); //De-energize the relay, we are at or below temp
            Serial.print("Standby Mode - Current Temp in Celsius ");
            lcd.setCursor(11,1);
            lcd.print("Done!");
    }
    else if ((celsius >= 6.01) && (celsius <= 6.49)){
            Serial.print("Standby Mode - Current Temp in Celsius ");
            lcd.setCursor(10,1);
            lcd.print(" Cold     ");
            delay(500);
            lcd.setCursor(10,1);
            lcd.print("          ");
            delay(250);

    }
    else if (celsius >= 6.5){
            digitalWrite(relay, HIGH); //Energize the relay for cooling, we are above temp
            Serial.print("Cooling Mode - Current Temp in Celsius ");
            lcd.setCursor(9,1);          
            lcd.print("Cool   ");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print(" Cool  ");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print("  Cool ");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print("   Cool");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print("   Cool ");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print("  Cool  ");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print(" Cool ");
            delay(400); 
            lcd.setCursor(9,1);
            lcd.print("Cool");
            delay(400); 
            lcd.setCursor(9,1);            
            lcd.print("       ");
            delay(400);             
    }

  // print the analog value:
  Serial.println(celsius); // Print debugging info to serial monitor showing mode and temp
  lcd.setCursor(0,0);
  lcd.print("*Coleman Cooler*");
  lcd.setCursor(0,1);
  lcd.print("Temp:");
  lcd.print(celsius);
}

Have had an issue where twice this Arduino has locked up.

Anyone have any idea why this may be happening? And anything I can do to rectify the problem?