Thermostat (or, its happening again)

Share

This is just a quick post at the moment because the project isn’t done and I am distracted by other things… The thermostat for the central heater in my house became unreliable a week or two ago. My wife rang around and a new one from the manufacturer of the heater was going to be $450 AUD. So, it seemed obvious to make my own. I’ve just installed the 1.0 of it, with the board layout and manufacture being done by Doug once again.

Other people seem to lack a PCB manufacturing back neighbour. I highly recommend you acquire one if possible.

Share

Building a hygrometer with a HS1101

Share

The next sensor I wanted to add to my home was a set of hygrometers. Specifically I wanted an exterior one, and a matching interior one. This would be useful as we have evaporative cooling, and if the humidity level outside is already high, then it doesn’t make a lot of sense to put extra water into the air. Worse than that, it can also damage my books and make the house really clammy. So, adding some sensors was the first step in some form of alerting.

I picked up two HS1101s from ebay quite cheaply (about $4 each IIRC). These devices are capacitors whose capacitance varies proportionally with relative humidity. You also need to provide a temperature at the sensor to correct the value, although the correction is pretty minor so I guess you could skip this if you really wanted to cut costs. Given I have plenty of code for Dallas 1820s now, I just dropped one of those onto the board too.

I just used the circuit from the data sheet for my design, with a few simple tweaks (like the DS1820). Here’s my surprisingly unprofessional circuit diagram:

The DS1820 stuff that’s not on the data sheet is in red. When built, it looks like this (note the crazy amount of jumper wire):

This gives us temperature on a 1-Wire pin, and an oscillator on another pin which relates to the current humidity. You’ll notice that my circuit has some extra wires, that’s because I power down the 555 / HS1101 when I’m not taking a sample. I do this because Peter H. Anderson suggested that noise would be a problem otherwise. This circuit was actually quite hard to build and get working. There are a few reasons for that:

  • The large number of jumpers on the prototype PCB.
  • The lack of documentation from other arduino hackers (with the notable exception of the rather good Peter H. Anderson page).
  • The HS1101 data sheet forgets to mention that connecting pins 1 and 8 on the 555 is assumed knowledge.
  • The values for R1 and R2 vary depending on what model 555 you are using, and are crazily specific. For the LMC555 that I used, R1 is 1238K and R2 is 562K. I got close to these values, but not exact and it did seem to affect accuracy.
  • You must use a CMOS 555. That’s buried in a six word sentence in the middle of a page on the data sheet, and I didn’t notice it for a while. With a NMOS 555, you get effectively random numbers out of the circuit. Worse than that, CMOS 555s are actually a little hard to find, and I had to get mine from Farnell.
  • I attempted to calibrate with the government weather data from the next suburb over. Unfortunately, as best as I can tell, that data is wrong. It claims that its currently as humid here as it is in Cairns in the wet season, which I deny. Calibration is an ongoing issue for me, although I have some ideas on how to progress there. It might also not matter, as I am building an identical sensor for inside the house and as long as they are both equally wrong I can still detect the “turn off the water to the evap” state that I want to.

Here’s a comparison between my data for today and the weather service’s:

The code to run the HS1101 is relatively simple:

// Temperature and humidity sensor node. Based on the FridgeControlWeb project of mine
// as well as http://www.phanderson.com/picaxe/relhum_count.html

#include <enc28j60.h>
#include <etherShield.h>
#include <ip_arp_udp_tcp.h>
#include <ip_config.h>
#include <net.h>
#include <websrv_help_functions.h>
#include <avr/io.h>
#include <math.h>

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONEWIRE 3
#define HS1101DATA 5
#define HS1101POWER 7

int count_transitions(int ms);

// How long between measurement cycles
#define SLEEP_SEC 10

OneWire oneWire(ONEWIRE);
DallasTemperature sensors(&oneWire);

unsigned long last_checked = 0, this_check = 0;

// Web server setup
#define MYWWWPORT 80
#define BUFFER_SIZE 550
#define ERROR_500 "HTTP/1.0 500 Error\r\nContent-Type: text/html\r\n\r\n<h1>500 Error</h1>"

static uint8_t mymac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x25};
static uint8_t myip[4] = {192, 168, 1, 252};
static uint8_t buf[BUFFER_SIZE + 1];
char data[BUFFER_SIZE + 1];

// The ethernet shield
EtherShield es = EtherShield();

uint16_t http200ok(void)
{
  return(es.ES_fill_tcp_data_p(buf, 0, PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n"
                                            "Pragma: no-cache\r\n\r\n")));
}

// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
{
  uint16_t plen;
  plen = http200ok();
  plen = es.ES_fill_tcp_data_p(buf, plen, PSTR("<html><head><title>Temperature sensor</title>"
                                               "</head><body><pre>"));
  plen = es.ES_fill_tcp_data(buf, plen, data);
  plen = es.ES_fill_tcp_data_p(buf, plen, PSTR("</pre></body></html>"));

  return(plen);
}

// Float support is hard on arduinos
// (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1164927646) with tweaks
char *ftoa(char *a, double f, int precision)
{
  long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
  char *ret = a;
  long heiltal = (long)f;

  itoa(heiltal, a, 10);
  while (*a != '\0') a++;
  *a++ = '.';
  long desimal = abs((long)((f - heiltal) * p[precision]));
  itoa(desimal, a, 10);
  return ret;
}

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int count_transitions(int ms)
{
     // configure Counter 1
     cbi(TCCR1A, WGM11);
     cbi(TCCR1A, WGM10);

     cbi(TCCR1B, WGM12);  // WGM12::WGM10 000 - Normal mode

     sbi(TCCR1B, CS12);   // CS12::CS10 111 - External clock, count on rising edge.
     sbi(TCCR1B, CS11);
     sbi(TCCR1B, CS10);

     TCNT1 = 0x0000;      // note that TCNT1 is 16-bits
     delay(ms);
     // not sure if should turn off the counter
     return(TCNT1);
}

void setup()   {
  // initialize the digital pin as an output:
  Serial.begin(9600);
  sensors.begin();

  es.ES_enc28j60Init(mymac);
  es.ES_init_ip_arp_udp_tcp(mymac, myip, MYWWWPORT);

  pinMode(HS1101POWER, OUTPUT);
}

void loop()
{
  int i, j, data_inset;
  char float_conv[10];
  float t;
  DeviceAddress addr;
  uint16_t plen, dat_p;
  float relhum_raw, relhum_corrected;
  int relhum_count;

  // Read temperatures, we dump the state to a buffer so we can serve it
  this_check = millis();
  if(this_check > last_checked + SLEEP_SEC * 1000)
  {
    data_inset = 0;
    sensors.requestTemperatures();
    sprintf(data + data_inset, "Sensor count: %d\n",
            sensors.getDeviceCount());
    data_inset = strlen(data);

    for(i = 0; i < sensors.getDeviceCount(); i++)
    {
      t = sensors.getTempCByIndex(i);
      sensors.getAddress(addr, i);

      data[data_inset++] = 't';
      for (j = 0; j < 8; j++)
      {
        sprintf(data + data_inset, "%02x", addr[j]);
        data_inset += 2;
      }

      sprintf(data + data_inset, ": %s\n", ftoa(float_conv, t, 2));
      data_inset = strlen(data);
    }

    // Power up the 555 / HS1101, and take a measurement. Power it down again afterwards.
    digitalWrite(HS1101POWER, HIGH);
    delay(500);
    relhum_count = count_transitions(1000);
    digitalWrite(HS1101POWER, LOW);
    sprintf(data + data_inset, "HS1101 cycles: %d\n", relhum_count);
    data_inset = strlen(data);

    relhum_raw = 557.7 - 0.0759 * relhum_count;
    sprintf(data + data_inset, "Raw humidity: %s\n", ftoa(float_conv, relhum_raw, 2));
    data_inset = strlen(data);

    relhum_corrected = (1.0 + 0.001 * (t - 25.00)) * relhum_raw;
    sprintf(data + data_inset, "Corrected humidity: %s\n",
            ftoa(float_conv, relhum_corrected, 2));

    Serial.println(data);

    last_checked = this_check;
  }

  // Handle network packets
  dat_p = es.ES_packetloop_icmp_tcp(buf, es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
  if(dat_p != 0)
  {
    if (strncmp("GET ", (char *)&(buf[dat_p]), 4) != 0){
      // head, post and other methods:
      dat_p = http200ok();
      dat_p = es.ES_fill_tcp_data_p(buf, dat_p, PSTR("<h1>200 OK</h1>"));
    }

    // just one web page in the "root directory" of the web server
    else if (strncmp("/ ", (char *)&(buf[dat_p+4]), 2) == 0){
      dat_p = print_webpage(buf);
      Serial.println("Served temperature web page");
    }

    else{
      dat_p = es.ES_fill_tcp_data_p(buf, 0, PSTR(ERROR_500));
    }

    es.ES_www_server_reply(buf, dat_p);
  }
}

As with previous circuits, I’m going to have to thank Doug for hints and tips along the way, as well as letting me steal his entire collection of 8 pin DIP sockets.

Share

The Beer Fridge saga continues

Share

Since the last update on the beer fridge, we’ve had to do some murdering of the original PCB to get it to fit in a case. In addition, we’d failed to take into account the startup power draw for the compressor (5 amps), and had to upgrade the relay we’re using from a 3 amp solid state relay. Luckily Doug had the beefier relay just sitting around in his shed. That means we’ve lost our opto-isolation because the new relay is a simple mechanical one, but we have a relay coil doing the same thing now. A new PCB will make the world a lot neater, which will be nice. Oh, we’ve also been mentioned on Hack a Day, which has generated some interesting comments on their site.

I’ve observed that sometimes the relay doesn’t turn on, even though the arduino thinks it has done so. An example can be seen here:

(Note that graph is a Google chart server image, generated by a simple visualization program I wrote in python. If you’re that way inclined, the visualization software is in my public SVN repository).

At first we thought this was a software problem with comparing ints to floats, but it continued to happen even after we fixed that bug. You can see in the graph above that during testing the compressor was “turned on” (i.e. the arduino thinks it has activated the relay), but the temperature continued to rise. A visual inspection showed that in fact the relay hadn’t turned the compressor on, and power cycling the controller (and therefore the relay) didn’t help. However, the simple expedient of hitting the relay with a screw driver handle fixed the problem, which made me think that Doug had given me a bodgy relay. This got me thinking about if it would be possible to unstick a relay in software though — its pretty easy to detect this case (temperature continues to rise despite the compressor being). I’m thinking that perhaps if you cycled the inputs over and over you might be able to get the relay to unstick.

Detecting this case in software might be generally useful anyway though… Ignoring stuck relays, it would also tell you when someone had left the door open for example. It would be nice to detect this case and then give up on the compressor for a few minutes before trying again. I wrote a quick implementation of this “door open detection” and gave it a try, but I’ve now given up on it as being too fiddly. I found problems such as when the outside world is heating up rapidly (summer mornings for example), the compressor can’t make a big enough difference to the internal temperature of the fridge, but you still really want the compressor on because something is better than nothing.

In the end it turned out the problem with the relay was that the arduino wasn’t providing enough current to pull the relay contact in reliably. This was fixed with the addition of a transistor to the board, which is yet another thing to add to the next PCB.

One of the big advantages of a microprocessor based custom thermostat is that I can implement new features that wouldn’t normally be present in a fridge. Some of these features might turn out to be bad ideas, but I view the beer fridge as a bit of an experimentation platform.

Since my extra Dallas 1820s have arrived from ebay, I also added a sensor inside the freezer. This is interesting because the freezer isn’t getting anywhere near the FDA recommended temperature (-17.7 Celsius). I tweaked the code yet again to turn on the compressor if either compartment is over temperature, but this resulted in the fridge running much too cold — it was close to freezing point in fact. I think this is probably a hardware problem with the freezer, and given its a beer fridge I’ve just written “this is not the freezer you are looking for” on the door and gone back to only monitoring the temperature of the fridge compartment. Here’s a graph of my experiments with the freezer yesterday:

Another recent software tweak is a start up delay for the compressor in order to reduce the risk of back pressure damage to the compressor. Thanks Murray! This comes with yet another LED which indicates that the compressor is currently disabled.

I think this project is nearly ready to start showing people the code. The code is also getting big enough that cutting and pasting it into blog posts is starting to get annoying. So, here are a few links:

  • The code for the arduino. This should be self explanatory, except for saying that we’re using a nuelectronics.com ethernet shield, not the standard one.
  • The visualization software. You want temperature.py to scrape the web server on the arduino and push stuff into a MySQL database, and then server.py is a simple python web server that provides the UI for visualization. The UI isn’t very good at the moment, but I shall improve it soon.
Share

Thinking about arduino as a prototyping platform

Share

So, I’ve mentioned in earlier posts about arduino projects that I consider the arduino to be a prototyping platform, and a damn good one at that. Hack a day seems to think of it in similar terms. It was really Doug who got be thinking in this direction with the initial PCB design for the fridge controller project, which includes space for an Atmega CPU right on the PCB, thus eliminating the need for a relatively expensive arduino board to be permanently consumed.

So I started to wonder how hard it would be to build a simple arduino replacement board. It wouldn’t need the complicated USB hardware, as you could program the Atmega on a full arduino board before installation. It would just need a time source, perhaps a LED, and a voltage regulator.

You can see in the picture above a version I quickly whipped up on a breadboard to prove this is possible. I didn’t bother with a voltage regulator in this version, and the wires off on the right go off to a power source. This quickly turned into a PCB prototype board design, which has a voltage regulator, and exposes all of the arduino digital pins except for pin 5 (which the 16MHz crystal gets in the way of). Pin 5 could be made to happen pretty easily though…

I think this was about $10 worth of parts, including the Atmega CPU, which makes it a pretty attractive option compared with the real arduino development boards. I expect to be doing a lot of my future development on a full arduino board, and then moving the finished products off onto boards like this. I expect Matt’s door bell will be exiled to one of these soon in order to free up a board. Doug and I have talked about doing a custom PCB layout which is similar, but that is yet to happen.

The best bit of this is I am really surprised by how easy it was. I’m not a hardware person, and it took only an hour or so with a schematic to come up with a working version. I’m much pleased.

Share

Arduino with the kids: Cricket Noise Door Bell

Share

When I was a child, I had a doorbell at my bedroom door to ward off uninvited guests. My six year old, Matthew, has always been pretty enthused about building things, and so he wanted to give an electronics project a try. I thought this would be a good project to start out with for the kids, because its relatively simple, and there is a tangible result at the end (you press a button and something happens). Matt liked the idea. Because this project involved a fair bit of soldering, it turns out that Matt spent most of his time taking photos of the work, although we talked about what was happening at each step. I need to think harder about how to get him involved in the construction process — I think that will be easier once the bread boarding stuff from ebay arrives.

The design is relatively simple. I took the sample debounce circuit (a button, 10k resistor) and software and ran that first. Then we put a peizo buzzer across pin 13 and ground. That meant that with the sample software we had both a light and a noise when you pressed the button. Unfortunately, the pin 13 LED also turns on when the arduino is booting, which means we got two beeps per boot, which was annoying. The peizo buzzer therefore got exiled to pin 12.

Finally, the screech from the peizo buzzer was getting a bit much, so I implemented a simple on-off cycle instead of it staying completely on. This produces a noise a bit more like a cricket’s chirp, which is much less annoying. Finally, we put the whole thing in a case, and I think it looks pretty good. At the same time as putting in the case, we also added a battery power supply and power switch, as Matthew is now keen to take his door bell to school for show and tell.

The pictures in this post were mostly taken by Matthew. The source code (which includes a list of the wiring needed) is in my source repository.

Share

Beer fridge controller 0.3

Share

Last night Doug made up the first cut of the PCB for the beer fridge controller mentioned in previous posts, and we fitted the arduino to it. There wasn’t much in the way of software changes, apart from changing the pin that the compressor runs on.

You can see here that we’ve mounted both the arduino and the Ethernet shield onto the PCB — this is just temporary until we get the PCB right. The black rectangle at the front right is a 240 volt capable relay, and the thing behind it is a 240 volt transformer which is capable of powering all the electronics on the boards. In the final PCB we wont need the arduino at all — just the Ethernet shield and the atmega 328 from the arduino. However, that didn’t work out this time around because of problems getting the Ethernet socket to fit nicely. Its clearer on this picture of the other side of the board:

See how we had to cut a hole in the PCB for the socket? That took out some of the pin holes for the atmega, and a few tracks. Its not a big problem because we’re going to iterate a little on the PCB design (and by “we”, I mean Doug). You can also see the perspex shield, which covers all the 240 volt rails, which is a nice touch. This version of the hardware is now sitting out on top of the beer fridge, and I wrote some simple scraping and visualization software for the temperature values I am seeing from the embedded hardware. You can see here the temperatures out the back of my house for this afternoon:

As I’ve mentioned before, the hardware and software can handle more than one temperature probe, so the ultimate plan is to take the opportunity to place a bunch of these probes around the house and see what interesting data we end up with.

Share

Beer fridge controller 0.2

Share

Further to yesterday’s post about the beer fridge thermostat replacement, I’ve been hacking on ethernet support for the controller. This is handy because I’d like to log the temperature and compressor state over the network, because I’m hoping that can be used to make calculations about the thermal mass of the contents of the fridge, and therefore derive how much beer is actually in the fridge at any given time.

Because the controller also supports more than one temperature probe, I’ll also add more 1-Wire temperature sensors around the house so I can determine important things like if its hot in the outside world.

The code is currently experiencing some bloat in the binary size, mainly because the ethernet library and the sprintf implementation are quite large. I’ll have to think more about that. Here’s the current code:

    #include <enc28j60.h>
    #include <etherShield.h>
    #include <ip_arp_udp_tcp.h>
    #include <ip_config.h>
    #include <net.h>
    #include <websrv_help_functions.h>
    
    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    // Temperature sensor and compressor setup
    #define COMPRESSOR 9
    #define ONEWIRE 3
    
    #define HIGHTEMP 4
    #define LOWTEMP 3.6
    
    // 220L Kelvinator is 85 watts
    #define COMPRESSOR_WATTAGE 85.0
    
    #define SLEEP_SEC 10
    
    OneWire oneWire(ONEWIRE);
    DallasTemperature sensors(&oneWire);
    
    unsigned long runtime = 0, chilltime = 0, last_checked = 0, this_check = 0;
    uint8_t compressor = LOW;
    
    // Web server setup
    #define MYWWWPORT 80
    #define BUFFER_SIZE 550
    #define ERROR_500 "HTTP/1.0 500 Error\r\nContent-Type: text/html\r\n\r\n<h1>500 Error</h1>"
    
    static uint8_t mymac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
    static uint8_t myip[4] = {192, 168, 1, 253};
    static uint8_t buf[BUFFER_SIZE + 1];
    char data[BUFFER_SIZE + 1];
    
    // The ethernet shield
    EtherShield es = EtherShield();
    
    uint16_t http200ok(void)
    {
      return(es.ES_fill_tcp_data_p(buf, 0, PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n"
                                                "Pragma: no-cache\r\n\r\n")));
    }
    
    // prepare the webpage by writing the data to the tcp send buffer
    uint16_t print_webpage(uint8_t *buf)
    {
      uint16_t plen;
      plen = http200ok();
      plen = es.ES_fill_tcp_data_p(buf, plen, PSTR("<html><head><title>Temperature sensor</title>"
                                                   "</head><body><pre>"));
      plen = es.ES_fill_tcp_data(buf, plen, data);
      plen = es.ES_fill_tcp_data_p(buf, plen, PSTR("</pre></body></html>"));
    
      return(plen);
    }
    
    // Float support is hard on arduinos
    // (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1164927646)
    char *ftoa(char *a, double f, int precision)
    {
      long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
    
      char *ret = a;
      long heiltal = (long)f;
      itoa(heiltal, a, 10);
      while (*a != '\0') a++;
      *a++ = '.';
      long desimal = abs((long)((f - heiltal) * p[precision]));
      itoa(desimal, a, 10);
      return ret;
    }
    
    void setup()   {
      // initialize the digital pin as an output:
      pinMode(COMPRESSOR, OUTPUT);
      Serial.begin(9600);
      sensors.begin();
    
      es.ES_enc28j60Init(mymac);
      es.ES_init_ip_arp_udp_tcp(mymac, myip, MYWWWPORT);
    }
    
    void loop()
    {
      int i, j, data_inset, delta;
      char float_conv[10];
      float t;
      DeviceAddress addr;
      uint16_t plen, dat_p;
    
      // Read temperatures, we dump the state to a buffer so we can serve it
      this_check = millis();
      if(this_check > last_checked + SLEEP_SEC * 1000)
      {
        delta = int((this_check - last_checked) / 1000);
        runtime += delta;
        if(compressor == HIGH) chilltime += delta;
    
        data_inset = 0;
        sensors.requestTemperatures();
        for(i = 0; i < sensors.getDeviceCount(); i++)
        {
          t = sensors.getTempCByIndex(i);
          sensors.getAddress(addr, i);
    
          for (j = 0; j < 8; j++)
          {
            sprintf(data + data_inset, "%02x", addr[j]);
            data_inset += 2;
          }
          sprintf(data + data_inset, ": %s\n", ftoa(float_conv, t, 2));
          data_inset = strlen(data);
        }
    
        // Control compressor
        if(t > HIGHTEMP) compressor = HIGH;
        else if(t < LOWTEMP) compressor = LOW;
        digitalWrite(COMPRESSOR, compressor);
    
        // Status dump
        sprintf(data + data_inset,
                "Compressor: %s\nRuntime: %lu\nChilltime: %lu\n%% chill: %d\nWatt hours: %d\n",
                compressor == HIGH ? "on" : "off", runtime, chilltime,
    	    int(chilltime * 100.0 / runtime),
                int(chilltime * COMPRESSOR_WATTAGE / 3600));
        Serial.println(data);
        last_checked = this_check;
      }
    
      // Handle network packets
      dat_p = es.ES_packetloop_icmp_tcp(buf, es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
      if(dat_p != 0)
      {
        if (strncmp("GET ", (char *)&(buf[dat_p]), 4) != 0){
          // head, post and other methods:
          dat_p = http200ok();
          dat_p = es.ES_fill_tcp_data_p(buf, dat_p, PSTR("<h1>200 OK</h1>"));
        }
    
        // just one web page in the "root directory" of the web server
        else if (strncmp("/ ", (char *)&(buf[dat_p+4]), 2) == 0){
          dat_p = print_webpage(buf);
          Serial.println("Served temperature web page");
        }
    
        else{
          dat_p = es.ES_fill_tcp_data_p(buf, 0, PSTR(ERROR_500));
        }
    
        es.ES_www_server_reply(buf, dat_p);
      }
    }
    
Share

Beer fridge controller 0.1

Share

On the weekend I picked up a 220 liter beer fridge for $20. Its in really good condition (ignoring some minor rust in the freezer section), and the only real problem with it is that the thermostat doesn’t work leaving the compressor on the whole time. Doug suggested that instead of just buying a new thermostat, we should build an arduino fridge controller.

I’m not really a hardware guy, but once Doug had pointed me at the Dallas 1820 1-Wire temperature sensor, and lent me some resistors, it was pretty easy to pull the software side together. Note that this version doesn’t actually do any of the compressor control — it simulates that by turning a LED on. The compressor stuff has been delegated to Doug and will be mentioned later.

You can see that the circuit is in fact really simple. There is a LED to simulate the compressor (with a resistor), and then the 1-Wire temperature sensor (with another resistor). The code is pretty simple too. Here’s my latest fancy version:

    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    #define COMPRESSOR 13
    #define ONEWIRE 2
    
    #define HIGHTEMP 4
    #define LOWTEMP 3
    
    #define SLEEP_SEC 10
    
    // 220L Kelvinator is 85 watts
    #define COMPRESSOR_WATTAGE 85.0
    
    OneWire oneWire(ONEWIRE);
    DallasTemperature sensors(&oneWire);
    
    unsigned long runtime = 0, chilltime = 0;
    boolean compressor = false;
    
    void setup()   {
      // initialize the digital pin as an output:
      pinMode(COMPRESSOR, OUTPUT);
      Serial.begin(9600);
      sensors.begin();
    }
    
    void loop()
    {
      int i;
      float temperature;
      DeviceAddress addr;
    
      sensors.requestTemperatures();
    
      for(i = 0; i < sensors.getDeviceCount(); i++)
      {
        temperature = sensors.getTempCByIndex(1);
        Serial.print("Current temperature at ");
        sensors.getAddress(addr, 1);
        printAddress(addr);
        Serial.print(" is: ");
        Serial.println(temperature);
      }
    
      if(temperature > HIGHTEMP)
      {
        digitalWrite(COMPRESSOR, HIGH);
        if(!compressor)
        {
          Serial.println("Compressor on");
          compressor = true;
        }
      }
      else if(temperature < LOWTEMP)
      {
        digitalWrite(COMPRESSOR, LOW);
        if(compressor)
        {
          Serial.println("Compressor off");
          compressor = false;
        }
      }
    
      delay(SLEEP_SEC * 1000);
      runtime += SLEEP_SEC;
      if(compressor) chilltime += SLEEP_SEC;
    
      Serial.print("Efficiency: Total runtime = ");
      Serial.print(runtime);
      Serial.print(", Chill time = ");
      Serial.print(chilltime);
      Serial.print(" (");
      Serial.print(chilltime * 100 / runtime);
      Serial.print("%, ");
    
      // The compressor wattage is consumption for an hour, so work
      // out how many hours we've been operating for. Then divide by
      // 1000 to get kWh.
      Serial.print(chilltime * COMPRESSOR_WATTAGE / 3600 / 1000);
      Serial.println("kWh)");
    
      Serial.println("");
    }
    
    // Function to print a one wire device address
    void printAddress(DeviceAddress deviceAddress)
    {
      for (uint8_t i = 0; i < 8; i++)
      {
        // zero pad the address if necessary
        if (deviceAddress[i] < 16) Serial.print("0");
        Serial.print(deviceAddress[i], HEX);
      }
    }
    

The code uses the Miles Burton 1-Wire library, which was easy to use once you figure out his example code has an impossible number for the pin. The code outputs information like this over serial:

    Current temperature at 10FA473500000037 is: 21.62
    Efficiency: Total runtime = 1780, Chill time = 1770 (99%, 0.04kWh)
    

That's with it on my desk where the "compressor" is permanently "on". I'll let you know how we go with further versions.

Share