nickpegg.com
Intelligent Drink Dispenser - Software Design Posted on 2009-06-21 - Comment

The other major half of the Intelligent Drink Dispenser project was the software side of things. As with the hardware, there were some things we had to consider when beginning the design of things. What language should we use? Should this be a GUI application or web application? If we go with a GUI application, what operating system should we target?

We decided that since we only had a semester to get everything done, we needed a framework to take care of the more nitty-gritty stuff. We eventually decided to go with the Django web framework, which uses the Python programming language. Python is a language we all knew and Jon and I had used Django in the past. Also, since our 'final product' would be highly based on a client-server model, it makes sense to go with a web app since the server can be in a central location with many clients connecting to it.

The most important thing to us was the fact that Django abstracts the database into models for us. No having to mess around with raw SQL, we just run some queries and get our data from the models as if they're just plain ol' objects. After some thought, we came up with our models and their relationships:

Database layout

The development of the application was fairly straight-forward. It was just a standard Django app after all. The interesting part was interfacing with the hardware.

If you remember from my post talking about the hardware side, we used an FTDI UM232 USB-to-serial converter. Lucky for us, there's a Linux kernel module which represents this device as a virtual serial port, which made our jobs a whole lot easier since there's existing serial libraries for Python (like pyserial). We ended up just writing a couple of functions, one to read the RFID tag from the serial port, and one that takes in a Drink id and then communicates to the microcontroller to pour it. The microcontroller's fairly dumb, just taking a number and turning that pin on, or turning all of the pins off if a non-valid character is sent, as you can see in the pourDrink function:

    def pourDrink(id, serialPort=DEVICE):
      """Pours the drink given by the specified ID"""

      # Seconds per mL of the motors, found experimentally
      # These should be in the database or a config file instead of hardcoded...
      secondsPerML = []
      secondsPerML.append(9.858/350.0)  # Pump 0
      secondsPerML.append(9.858/350.0)  # Pump 1
      secondsPerML.append(6.385/210.0)  # Pump 2

      components = DrinkComponent.objects.filter(drink=id)

      for c in components:
        stock = IngredientStock.objects.filter(ingredient=c.ingredient)
        total = 0

        for s in stock:
          total += s.amount

        if total < c.amount:
          raise UnableToPour("Not enough " + c.ingredient.name + " to pour drink!")

      port = serial.Serial(serialPort, 2400)
      if not port.isOpen():
        raise UnableToPour("Unable to open serial port!")

      for c in components:
        stock = IngredientStock.objects.filter(ingredient=c.ingredient)
        leftToPour = c.amount

        startTime = time.time()

        for s in stock:
          port.write(str(s.slot))
          if leftToPour < s.amount:
            time.sleep(secondsPerML[s.slot]*leftToPour)
            s.amount = s.amount - leftToPour
            s.save()

            break
          else:
            time.sleep(secondsPerML[s.slot]*(s.amount - ))        
            leftToPour = leftToPour - s.amount - 30

            s.amount = 0
            s.save()

        print "Time to pour:" + str(time.time() - startTime)
      port.write("\n")
      port.close()

Not exactly the most precise in terms of pouring accuracy, but it gets the job done as a prototype. As for the rest of the code, there's not too much else that's very interesting. I may release the code at some point in the future.

Intelligent Drink Dispenser in the news! Posted on 2009-05-11 - Comment

So, I've been pretty quiet about my Intelligent Drink Dispenser project so far, mostly because there was going to be a competition between myself and Clint Rutkas and I didn't want to give the enemy any details.

Well, the cat's out of the bag: http://news.mst.edu/2009/05/studentscreatesmartwayto_m.html

The communications department of my university, Missouri S&T (formerly UMR), gets alerts from Google News whenever someone mentions the university's name and since Clint did just that, his post showed up in their email. After talking with the director of communications, he decided to run the story. I gotta say, it's a pretty great way for my Senior Design class to wind down.

For those interested in the details of the Intelligent Drink Dispenser, stay tuned! I'll be posting more information about it soon.

Side note: since the story got posted, my server's been chugging along to serve up my website, almost maxing out the upload on my poor cable internet connection. Here's the traffic graph from my router:

Traffic graph

PXE boot with DD-WRT and Ubuntu Posted on 2009-04-18 - Comment

After spending all afternoon fighting with my new server and my DD-WRT router, I finally figured out how to get my server to PXE boot and fire up an Ubuntu install. All it really involved was setting up TFTP on another box (my desktop, to be specific), adding a line to DD-WRT's DNSMasq options, and configuring the damn server to boot from PXE, which was the hardest part. Luckily, for those of you who are struggling with it, here's how I did it.

Setting up the PXE client

I had to get my server to boot PXE in the first place. For most people, this just means poking around in the BIOS. Not for me though.

After poking around the HP site, I've found out that my server is a first generation Proliant DL360. Since it's an older machine, this means that it doesn't have a built-in BIOS config, but I had to actually download the old Compaq SmartStart 5.5 CD. I had to hunt around the HP website, but to save you the trouble, you can snag it here:

http://ftp.hp.com/pub/products/servers/supportsoftware/ZIP/smartstart-5.50-0.zip

Once you boot from the CD, you'll want to go into the System Configuration Utility when prompted. From there, it's just like a giant BIOS. Just turn PXE on for whatever ethernet port you're using and it's rarin' to go.

Setting up the TFTP server

Once my server was setup for PXE booting, I had to set up a tftp server for it to grab the boot image from. Since I was using my desktop, which runs Ubuntu, as a host, setup was pretty easy. I just used tftpd-hpa per the Ubuntu wiki's recommendation.

    # sudo aptitude install tftpd-hpa

I had to also edit the configuration file at /etc/default/tftpd-hpa. Mine looks like this:

    #Defaults for tftpd-hpa
    RUN_DAEMON="yes"
    OPTIONS="-l -s /var/lib/tftpboot"

Since I was wanting to PXE boot into an Ubuntu install, I had to extract the install files into /var/lib/tftpboot as I put in the config file. For example, the netboot image files for Ubuntu 9.04 can be found here:

http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-i386/current/images/netboot/netboot.tar.gz

Setting up the the DHCP server

DD-WRT uses dnsmasq for DHCP, so if you have a system which uses it too it shouldn't be too much different to setup. Watch out, though! I initially screwed up my configuration which really messed with my router.

All you have to do is add a line to the Additional DNSMasq Options found under the Services tab. If you're running plain dnsmasq, just add the line to your dnsmasq.conf file. The line goes a little something like this:

    dhcp-boot=pxelinux.0,mybox,10.0.0.100

where pxelinux.0 is the file to boot, mybox is the hostname of the tftp server, and 10.0.0.100 is the IP address of the tftp server. You could probably get away with only specifying the hostname or just leaving it blank and supplying the IP address. You can also get more fancy and send certain boot images to certain machines, etc. This way works just fine on a home network like mine.

Once you get this all setup, any machines that try to PXE boot will receive the image and boot to it. If you used the Ubuntu install image like I did, you'll be able to install Ubuntu on any PXE-capable machine or even boot into a rescue shell! Just remember that if you can't setup a boot order (like my Proliant) make sure to disable the PXE boot in dnsmasq before rebooting.

New Server Posted on 2009-04-17 - Comment

Thanks to a generous donation from Richard Allen, I now have a new server.

Compaq Proliant DL360

It's a Compaq Proliant DL360. From what I can tell of it's past, a place where another friend of mine was working was getting rid of their old hardware and he snagged a bunch. Richard got some of the servers, had no use for this one, and then gave it to me a couple of days ago.

It's probably a first generation DL360, but that doesn't mean it sucks. It's got dual Pentium IIIs running at 1.266 GHz each, 512 MB of RAM, and two 18.3 GB SCSI drives running in RAID1. It's quite an upgrade from my current server, which is dual P3 450 MHz with a little less than 512 MB of RAM. The best part of the whole thing, though, is the Remote Insight Lights-Out Edition II card that came with it. It's a PCI-X card that redirects video, keyboard, and mouse from the system and supplies it to a web interface. This means that no matter where I am, I can get a physical terminal to my server. Plus, if I plug an external power supply to it, I can even turn on my server remotely!

I'll probably be moving everything from my current server over to the new one. Since I'm mirroring and then cutting over, there shouldn't be any problems with any of the services that my box supplies.

New Website Posted on 2009-04-15 - Comment

So, I've decided to redo my website again. My old one was pretty bland and updating stuff was a relatively a pain. Plus, I seem to be doing more interesting things and having more interesting thoughts (hopefully) than I have in the past couple of years. Of course, I am a Computer Engineer (aka nerd), so don't expect to see anything like me pondering the wonders of the cosmos here. I'll probably mostly post updates on projects I'm fiddling with, my struggles with technology, and what I've been up to.

As you can see, I decided to go with WordPress. I used it a long time ago, but after seeing my roommate Ben Murrell use it on the Missouri S&T ACM site and seeing what it was capable of, I went for it. Probably the most important thing for me was the ability to have static pages and link to them in a reasonable fashion (as you can see along the top and right sidebar). It just does everything I want to do without too much fuss, and it looks pretty while it does it.

I'm still moving stuff from my old website and updating information, but feel free to poke around in the meantime.