Archive for the ‘Arduino’ Category

Arduino datalogger is up!

Tuesday, June 23rd, 2009

As previously noted, I decided to make a super-simple office temperature and humidity datalogger based on the Arduino, LM35CAZ and SC600. Today I finally added the resistor and cap for the lowpass filter on the SC600 and the data looks good:

picture-22

Yep, that web page is public. You too can see the ambient conditions in Calit2 room 6402! Temperature is Celsius, humidity is relative percent.

For some reason the temperature data is noisier than I’d expect, but the humidity data looks clean. I’ll have to see if I can pull the data into a graphing page – I’m experimenting with adding it to Cacti (thus the format of the web page, designed for machine consumption) but have not gotten it working yet.(see below)

Here’s an iPhone snap of the completed circuit – really quite minimal. The LM35 needs no external parts at all, and the SC600 just needs the 47uF cap and 100k resistor. Good sensors for this, and cheap too.

img_0005

(Yeah, I really covet the macro photo ability of the new iPhone.)

It turns out that the Arduino outputs 5VDC, so I don’t even need the power supply to run it – all via USB. Elegant, that.

Update 6/26/09: Data in Cacti! I had to prefix the HTML output with a space to get the data ingester to work, and fiddled with the graph settings to get it to display. Check out the page here (login is guest/guest) and admire the data.

Arduino and Twisted

Monday, June 15th, 2009

The datalogger progresses – now with carefully-soldered SC600 sensor online:
img_0191Still need to add the 47uF cap and 100k RC filter, though, so the humidity data is crap.

I cleaned up the code a bit. The Arduino now simply sends raw ADC counts, and lets the other side do the linearization and conversion. Much more sensible. To make it easy, I have the Arduino send

ADC ADC\n

In other words, value space value newline, which is the easiest possible thing to parse on the other end. Code is now simply:

void setup() {
// initialize the serial communication:
  Serial.begin(9600);
}

void loop() {
  Serial.print(analogRead(0));
  Serial.print(" ");
  Serial.print(analogRead(1));
  Serial.println();
}

Using the magnificent Twisted framework, this is a ‘LineReceiver‘ protocol on top of a serial port, so the code to read it is quite compact. I won’t paste it here, as its 85 lines with all the comments, command line parsing, error handling and such, but here are the key bits:

class Echo(LineReceiver):
    def processData(self, data):
        """Convert raw ADC counts into SI units as per datasheets"""
        if len(data) != 2:
            return

        tempCts = int(data[0])
        rhCts = int(data[1])

        rhVolts = rhCts * 0.0048828125
        # 10mV/degree, 1024 count/5V
        temp = tempCts * 0.48828125
        # TODO need to rewrite this to include thermal compensation as per SC600 datasheet!
        humidity = (rhVolts * 45.25) - 42.76
        logging.info('Temp: %f C Relative humidity: %f %%' % (temp, humidity))

    def lineReceived(self, line):
        try:
            data = line.split()
            logging.debug(data)
            self.processData(data)
        except ValueError:
            logging.error('Unable to parse data %s' % line)
            return
if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO, \
                format='%(asctime)s %(levelname)s [%(funcName)s] %(message)s')

    o = THOptions()
    try:
        o.parseOptions()
    except usage.UsageError, errortext:
        logging.error('%s %s' % (sys.argv[0], errortext))
        logging.info('Try %s --help for usage details' % sys.argv[0])
        raise SystemExit, 1

    if o.opts['baudrate']:
        baudrate = int(o.opts['baudrate'])

    port = o.opts['port']

    logging.debug('About to open port %s' % port)
    s = SerialPort(Echo(), port, reactor, baudrate=baudrate)
    reactor.run()

Gotta love Python! (And Arduino.) Next up is trying to get the data into Cacti or RRDtool…

Update 6/17: Adding a web interface took just a few more lines of code:

class indexPage(resource.Resource):
    isLeaf = True

    def render_GET(self, request):
        ccStr = 'Temp:%f Humidity:%f\n' % (lastTemp, lastRH)
        return ccStr

    root = indexPage()
    site = server.Site(root)
    reactor.listenTCP(2000, site)

Now trying to get Cacti to parse the data it returns.

Progress on the Arduino

Wednesday, June 10th, 2009

I was having a bad karma day (OSX install failing, RabbitMQ borked, Debian server freezing, apt failures, etc, etc.) and worked a bit on the Arduino project as a break. Here’s the LM35 wired up and working:

img_0189

(That’s my ancient self-designed linear power supply with 5/6/12 and LM7805)

Temp out goes to ADC0. Arduino runs

void setup() {
// initialize the serial communication:
  Serial.begin(9600);
}

void loop() {
  // send the value of analog input 0:
  int val = analogRead(0);
  float fVal = map(val, 0, 1023, 0, 500);
  Serial.println(fVal);
  // wait a bit for the analog-to-digital converter
  // to stabilize after the last reading:
  delay(100);
}

and, on the mac, Processing runs

// Graphing sketch

// This program takes ASCII-encoded strings
// from the serial port at 9600 baud and graphs them. It expects values in the
// range 0 to 1023, followed by a newline, or newline and carriage return

// Created 20 Apr 2005
// Updated 18 Jan 2008
// by Tom Igoe

import processing.serial.*;

Serial myPort;        // The serial port
int xPos = 1;         // horizontal position of the graph

void setup () {
  // List all the available serial ports
  println(Serial.list());
  // I know that the first port in the serial list on my mac
  // is always my  Arduino, so I open Serial.list()[0].
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[0], 9600);
  // don't generate a serialEvent() unless you get a newline character:
  myPort.bufferUntil('\n');
}
void draw () {
  // everything happens in the serialEvent()
}

void serialEvent (Serial myPort) {
  // get the ASCII string:
  String inString = myPort.readStringUntil('\n');

  println(trim(inString));
}

Notes so far:

  1. On OSX 10.5, Processing fails with RXTX errors. The solution, found here, was a new version of librxtxSerial.jnilib, which I copied into /Library/Java/Extensions along with the RXTXcomm.jar
  2. Code has a truncation bug – no fractional degrees.
  3. Arduino is pretty easy to code and use; I’m impressed.
Up next is the more complex SC600 humidity sensor, for which I need capacitors and a bit of wirewrap. Wondering how to plot the captured data on a web page…

Arduino!

Monday, June 8th, 2009

Yep, I finally had a project where I needed a cheap OSX-compatible analog input (gonna build a temp & humidity monitor using LM35CAZ and Ohmic SC-600), and finally had the forehead-slapping moment of

I don’t need an ADC per se; I need a board with ADCs on it.

Yep, for example an Arduino. So I’ve got one, $34, working already. One trick on OSX that tripped me up – you have to open the Arduino.app/Contents/Info.plist file and set the java version from 1.4+ to 1.5 – OSX bug. Otherwise you get RXTX errors, which are a red herring. Here it is, blink code and all:
picture-2
Nice board. I got mine from Sparkfun, and it was here in a few days. Should be easy to hack on, there sure is a lotta chatter around this board. I suspect that the Arduino, just like my beloved mechanical watches, are fun because they’re hackable and comprehensible, two things that modern computers are increasingly lacking.