Kegerator Flow Meter Test

The first step along the road to getting the kegerator monitor up and running

Flow meter used available from adafruit:

Based on the code from:



#define lcdPin 6

SoftwareSerial LCD = SoftwareSerial(0, lcdPin);
// since the LCD does not send data back to the Arduino, we should only define the txPin
const int LCDdelay = 10; // conservative, 2 actually works

// which pin to use for reading the sensor? can use any pin!

// count how many pulses!
volatile uint16_t pulsesLeft = 0;
volatile uint16_t pulsesRight = 0;

volatile uint16_t lastPulses = 0;

// track the state of the pulse pin
volatile uint8_t lastFlowPinStateLeft;
volatile uint8_t lastFlowPinStateRight;

volatile int32_t lastFlowTimer = 0;

float litersPerTank = 18.9;
float pricePerTank = 78;

bool clearNextTick = true;

// Interrupt is called once a millisecond, looks for any pulses from the sensor!
uint8_t left = digitalRead(FLOWSENSORPINLEFT);
uint8_t right = digitalRead(FLOWSENSORPINRIGHT);

if (left != lastFlowPinStateLeft && left == HIGH) {
//low to high transition!

if (right != lastFlowPinStateRight && right == HIGH) {
//low to high transition!

lastFlowPinStateLeft = left;
lastFlowPinStateRight = right;

uint16_t pulses = pulsesLeft = pulsesRight;

if (pulses == lastPulses)
if (lastFlowTimer > -1)
if (lastPulses == 0)
clearNextTick = true;
lastFlowTimer = 0;

lastPulses = pulses;

void useInterrupt(boolean v)
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
else {
// do not call the interrupt function COMPA anymore

void setup()
Serial.print("Flow sensor test!");

lastFlowPinStateLeft = digitalRead(FLOWSENSORPINLEFT);

lastFlowPinStateRight = digitalRead(FLOWSENSORPINRIGHT);


pinMode(lcdPin, OUTPUT);
lcdPosition(0, 0);
LCD.print("Starting Up");

lastFlowTimer = -1;
clearNextTick = true;
pulsesLeft = 0;
pulsesRight = 0;

void loop() // run over and over again
uint16_t pulses = pulsesLeft = pulsesRight;

if (clearNextTick)
clearNextTick = false;

if (pulses == 0)
if (lastPulses > 0)

lcdPosition(0, 4);
lcdPosition(1, 1);
LCD.print("Begin pouring!");
float liters = pulses;
liters /= 7.5;
liters /= 60.0;
liters /= 1.4; //weird const

float ounces = liters * 33.8;

float price = liters / litersPerTank * pricePerTank;

if (pulsesRight > 0)
lcdPosition(1, 0);
LCD.print("Oz: ");
lcdPosition(1, 9);
LCD.print(" $:");

// Reset
if (lastFlowTimer > 1000)
lastFlowTimer = -1;
clearNextTick = true;
pulsesLeft = 0;
pulsesRight = 0;


// wbp: goto with row & column
void lcdPosition(int row, int col) {
LCD.write(0xFE); //command flag
LCD.write((col + row * 64 + 128)); //position
void clearLCD(){
LCD.write(0xFE); //command flag
LCD.write(0x01); //clear command.

Arduino Powered X10+RFID Controlled Motorized Curtain Opener/Sliding Door Lock

This is a walkthrough of my motorized curtain opener I built using an arduino and some pieces from a robotics kit I had lying around. To controller the curtains or lock I can use X10 (wireless remotes, web interface, iphone app), RFID (cards given to all my roommates) and physical switch to lock it as I leave.

Here’s a little more detailed explanation of the mechanism that opens the curtains:

And here’s a terrible hand drawing laying out the components:
Hand drawing

Pandora One Desktop Client Controlled from iPhone

This is a demo of an iPhone app I’ve been working on to control the Pandora playing on your desktop.

Set the mood with some Barry White before you walk in the door.
Thumbs up/down a song from the couch or anywhere in the world.
See what song is playing without getting up and squinting at the monitor.
Blast the speakers off the deck and pause or turn it down with your iPhone when you hear the cops rolling up.

Using C# I wrote a socket server that coupled with the ASyncSocket library for the iPhone, allowed me to create the Pandora control part of my home-automation app. Here’s a demo video I made for a member of

This uses windows APIs to first focus and bring to the front the Pandora One Adobe Air standalone client, then it will grab an image of the screen and Pandora’s coordinates to crop it down to show me what’s going on in the window. Then I chop up the full screenshot and grab the album art send it to the phone and then strip out areas I know contain text and assemble them into a new image that only contains text. Then I run OCR on the image, using the Microsoft Office Document Imaging library, and viola, String objects for the song name, artist, song position, length, etc. I then use pixels colors to determine if it’s on the right screen (stations/playing) and if it’s playing or thumbed up. Note that this will stop working if Pandora changes their UI/colors and the app would need to be updated. I may release source if I can clean up my obj-c and there is interest.

It works great with Pandora v2.0.1 and I use it daily, but I still have lot’s more to do in other areas of the app. I’ll be posting more as it nears completion.

Install OSX86 on G31M3-F

I bought some barebones cases off newegg, and they work perfect with OSX once you load a DSDT modified BIOS.

This is just to record my steps for myself and others who need it!

1. Prepare and install special BIOS

1a. Get BIOS Updater (only exe) + BIOS File

1b. Copy onto bootable USB Flash drive loaded with win98 via HP USB Disk Storage Format Tool

1c. Install using “AFUD4310 A7258IMS.120” at the cmd prompt

2. Prepare HDD

2a. Create empty space on your disk. I use Gparted LiveCD to do my partitioning.

2b. Boot into windows (there may be a better way, but haven’t found it yet) and launch a cmd prompt.

2b1. Open DiskPart. Type DISKPART hit Enter

2b2. Type list disk

2b3. select disk <desired hdd #>

2b4. list part

2b5. create partition primary id=af

2b6. exit

3. Installing OSX86 iAtkos v7

3a. Boot with cd inserted, press F11 to enter boot menu and select dvd drive

3b. Select Default options + VGA driver you need (nVidia DVI/DVI for me)

4. Boot with chameleon. If using a quadcore, you need to boot with cpus=1. There may be a fix