Sketching In Hardware (2)

05 Jan 2010
Tagged: Arduino, AVR, HCI, Projects, Ubiquitous Computing
I've had an urge lately to post some of the nifty projects I've done over the last few months. Hopefully it will help me put some of my experiences in context. Not to mention actually taking notes lets me find them later. As long as computers have existed, we've tried to represent the physical world in the virtual one.  This trend goes as far back as the punched cards and tabulating machines used in the 1890 United States Census, but it doesn't end there.  When computers became common enough that regular people -- without specialized training -- may use them, interface designers went straight for spacial metaphors.  We pulled more of the physical world into the machine. What I find fascinating about hardware hacking and platforms like the Arduino is that we can reverse that trend.  We can interact with computers through the physical world, rather than interpreting the physical world through a virtual one.  And we can do it trivially. Here's my own humble first effort: This is a bot that monitors an IRC channel. When I announce a mood, it moves the needle accordingly. It's not very complicated at all -- some cardboard, marker, sticky tape, a ~$10 hobby servo, and two pieces of code. The first, runs on a host computer, monitors the IRC channel, and tells the arduino where to point the needle. Ruby is very terse -- but it's also very expressive. It is easy to make very functional object oriented programs in very little space.
#!/usr/bin/env ruby
          
          require 'rubygems'
          require 'net/irc'
          require 'serialport'
          
          # This is an IRC Bot that also
          # talks to an arduino microcontroller.
          class ToneOMeter < Net::IRC::Client
            # What emotions should this bot respond to?
            # These are passed directly to the arduino.
            @@emotions = {
              'sarcastic' => '20s',
              'sardonic' => '60s',
              'acerbic' => '135s',
              'cynical' => '180s'
            }
          
            def self.emotions
              @@emotions
            end
          
            def initialize(*args)
              super
          
              # Connect to the arduino.  This will work on linux, other
              # platforms may require some adjustment.
              @sp = SerialPort.new "/dev/ttyUSB0", 19200
            end
          
            def on_rpl_welcome(m)
              # We've connected to the server, join a channel.
              post JOIN, "#tone-o-test"
            end
          
            def on_privmsg(m)
              # Someone has entered text into the channel.  Who was it?
              name = /^(.+)!/.match( m.prefix )[1]
          
              # If it was my owner (tony), and it's an action...
              if name =~ /tony/ && m[1] =~ /ACTION/
                # Extract the action, and send the canned result to the arduino.
                action = /\01ACTION is (.+)\01/.match( m[1] )[1].strip.downcase
                @sp.write( ToneOMeter.emotions[ action ] )
              end
            end
          end
          
          # Instantiate a new bot, and start it.
          ToneOMeter.new("test.server", "6667", {
                  :nick => "Tone-O-Meter",
                  :user => "Tone-O-Meter",
                  :real => "Tone-O-Meter",
          }).start
          
The second set of software is taken from the Arduino Playground and runs on the microcontroller itself. It uses Arduino's servo library to set the servo to a given angle. This isn't my code, but it's trivial enough (and useful enough) to repeat here.
#include 
          
          Servo servo1;
          
          void setup() {
            pinMode(1,OUTPUT);
            servo1.attach(14); //analog pin 0
            //servo1.setMaximumPulse(2000);
            //servo1.setMinimumPulse(700);
          
            Serial.begin(19200);
            Serial.println("Ready");
          }
          
          void loop() {
            static int v = 0;
          
            if ( Serial.available() ) {
              char ch = Serial.read();
          
              switch(ch) {
                case '0'...'9':
                  v = v * 10 + ch - '0';
                  break;
                case 's':
                  servo1.write(v);
                  v = 0;
                  break;
               }
            }
            Servo::refresh();
          }
          
So there you have it: Physical computing done with little electronics skill, for less than $40, and in less than a hundred lines of code. This is a pretty trivial example, but even just given the context of IRC it suggests some nifty projects. For example, a physical representation of how many users are in a channel? Or how active the conversation is? With physical interfaces now trivial to prototype, interface designers have yet another tool: Physical, tangible interfaces. Update: This article was featured on Make: Online.