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

Colony

Share

The Times is wrong about this book. Its not “cruel, cynical and very funny”, its cruel and cynical for sure, but it lacks hope and is overall just depressing. I certainly didn’t feel it was funny. Its strange, I loved the Red Dwarf series, and this book is very similar. I think the problem is that this book lacks all the hope and charm of the Red Dwarf books and TV show. Its a book entirely comprised of Rimmers, and that’s hard to take.

[isbn: 0140289755]

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

The Robot City, Robots and Aliens Series

Share

This series follows on from the Robot City series set in Asimov’s Foundation Universe but written by other authors. Overall that first series was weak, and I think the same is true for this series as well. There are a few here that are better than the others, but I’d only recommend this series for those who are obsessed with Foundation universe completeness.

Share

Isaac Asimov’s Robot City: Robots and Aliens: Humanity

Share

This book is actually the best one of the two robot city series (Robot City and Robots and Aliens). Unfortunately I had to wade through 12 not very good books to find it, and its still not stellar. I’d recommend giving both these series a miss unless you’re obsessed with completeness in Asimov’s Robot universe.

[isbn: 0441373860]

Share

The Robot City Series

Share

These are books written in Isaac Asimov’s Foundation Universe by other authors. They don’t progress the overall plot of the Foundation series, they just use some of the concepts and characters to tell similar stories. The books in the series are:

To be honest these books aren’t fantastic and I wouldn’t recommend them unless you’re trying to get exhaustive coverage of Asimov’s Foundation universe.

Share

Foundation’s Friends

Share

I was excited when I found Foundation’s Friends the other day, because I thought I’d read all the Foundation books and did not know that this one existed. It is an anthology which celebrates Asimov’s 50 years as a science fiction author, and each author takes their own approach to the Foundation universe.

The stories are:

  • The Nonmetallic Isaac or It’s a Wonderful Life (Ben Bova): not really a short story, more of an inspection of the impact that Asimov’s non-fiction writing has had on the world.
  • Strip-Runner (Pamela Sargent): set after The Naked Sun, a young female strip runner meets Elijah Bailey.
  • The Asenion Solution (Robert Silverberg): a pretty standard science fiction short story.
  • Murder in the Urth Degree (Edward Wellen): I haven’t read any of the Doctor Urth mysteries, so to be honest this story seemed pretty weird.
  • Trantor Falls (Harry Turtledove): covers the fall and sack of Trantor at the end of the first Galactic Empire. This one is pretty good, and in keeping with the overall Foundation universe.
  • Dilemma (Connie Willis): Asimov deals with some three law robots.
  • Maureen Birnbaum After Dark (George Alec Effinger): I find Maureen’s character to be superficial and annoying. This story didn’t really do it for me.
  • Balance (Mike Resnik): Susan Calvin wonders if robots are a better date than men.
  • The Present Eternal (Barry N Malzberg): is it good to be able to see with 100% accuracy into the past? This story was a bit disjointed, and not the best in the book.
  • PAPPI (Sheila Finch): a colleague of Susan Calvin brings home a robot companion for her son.
  • The Reunion at the Mile-High (Frederik Pohl): what if a biological weapon had been pursued instead of a nuclear one at the end of world war 2? What if Isaac Asimov hadn’t been a science fiction author because he was drafted into the effort?
  • Plato’s Cave (Poul Anderson): the robot debuggers Donovan and Powell return to help with a confused robot on Io. This story was pretty in keeping with the original Donovan and Powell stories, which was nice as those stories are classics.
  • Foundation’s Conscience (George Zebrowski): a researcher looks for records of missing Seldon appearances.
  • Carhunters of the Concrete Prairie (Robert Sheckley): this story was written by one of the guys who did the Bill the Galactic Hero spinoffs — specifically Bill the Galactic Hero on the Planet of Bottled Brains. This story seems to suffer from similar problems — as best as I can tell its trying to be funny, but it doesn’t do it very well.
  • The Overheard Conversation (Edward D. Hoch): the Black Widowers meet for a dinner discussion. I haven’t read any other Black Widower stories, so I don’t have much of an opinion on this one, although it did seem like a pretty traditional pithy short story.
  • Blot (Hal Clement): explorers on icy Miranda interact with some cubes of unknown origin that appear to be communicating with each other.
  • The Fourth Law of Robotics (Harry Harrison): the Stainless Steel Rat meets Susan Calvin.
  • The Originist (Orson Scott Card): a scientist trying to determine the origin of the human race in the declining days of the Galactic Empire interacts with Hari Seldon and his Foundations.
  • A Word or Two from Janet (Janet Asimov): what is it like being married to Isaac Asimov?
  • Fifty Years (Isaac Asimov): Asimov reflects on 50 years of writing.

Obviously, being an anthology, some of these stories are better than others. However, this is a good collection with only a couple of stories I didn’t really like. I’m glad I found it.

[isbn: 0812509803]

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