Introduction: Accurate Beer Scale

Step 1: How to Build It.

First, you need a few things. Here is a list.

    1. Arduino Board
    2. AD620 In-Amp
    3. WH-B05 Scale from Amazon
    4. ICL7660 Voltage Converter
    5. Misc Electrolytic Caps
    6. Misc Resistors
    7. Hook-up Wire
    8. XBee Modules (Needed for wireless communication, but not required)
    9. Normaly Open Push Button (For taring, or zeroing out the scale)

I want to stay away from a wire by wire description of all of the connections. I will go into a bunch of detail and explain some of the less obvious connections. Feel free to contact me if you have any specific questions. I'd be happy to answer them. Ok, here we go...

Lets start left to right on the circuit board. For a bigger image, go to the pics page. The first chip is the AD620. Across pins one and eight are two 56 ohm resistors in parallel, giving us 28 ohms. If you look at the data sheet, that gives us close to a gain of 10,000. Seems to work for me, you may need to vary a bit. Pin 4 is -5V coming from the ICL7660. Look at the data sheet for cap values (10uF) and get your V(in) from the regulated 5V from the Arduino. Pin 7 of the AD620 is 5V. Pin 6, the output, the all IMPORTANT output! Notice the resistor and cap? This is our RC filter that smoothes the output. Without it the values jump all over the place. I you put the wire to the Arduino analog input in between the resistor and the cap, we get an ALMOST perfectly steady value. I used a 1K resistor and a 100uF cap. I played with the cap value a lot and 100uF seemed to work the best. If you find something better, please let me know. Now this only gave me a number. I needed to change that number into something meaningful, ounces. To do this I weighed a bunch of things with my wifes postal scale and also weighed them with my scale. After doing the math, I discovered that dividing the analog reading by 10.65 gave me almost perfect results. I was happy. The tie wrapped blue wire in the middle goes to the Arduino. We'll get to those. The green LED is very important. It tells me when the current measurement is done. Very important. So also is the blue pushbutton. Here's why.

As of this version, the procedure for getting the weight of beer is as follows:       

1. Press the blue button. This tares or zeros out the scale. Everytime a digital scale is turned on it takes a moment before it reads. It has to compensate for the load cell because temperature affects its readings. We do the same. It doesn't send a zero to the arduino. Mine is a value of about 120. I take 100 readings of the output once the button is pressed and the average of those become my "zero". When the green LED blinks rapidly 2 times, pauses and repeats, taring is done.

2 . Set the container, empty or partailly filled, on the scale and wait until the green LED blinks 2 times, slowly. This gets that weight of the container so we can subtract that from the weight of the container and the beer for a beer only value. The LED is now blinking 3 times rapidly, pausing, and repeating.

3. Pour your beer and set it on the scale. I programmed a 500ms delay before weighing to compensate for the jostling of the beer. Wait for the green LED blink 3 times slowly and go off and there you have it, a weight of only beer sent directly to your PC. If your PC is next to your keg, you don't need XBee. If not, you do or we could work on a WiFi version too!

*NOTE: The 2 rapid blinks means you are on step 2 (set container on scale), and 3 rapid blinks means step 3 (waiting for full glass or container).

Ok, back to the circuit. the green LED has its cathode going to a 220 ohm resistor and then to ground. The anode is the white wire going to the Arduino, pin 12. The push button has one point connected to 5V, and the other with a resistor (10k) going to ground. In between the resistor and the button is the red wire going to the Arduino, pin 2(NOW USING INTERRUPT!!!). The red and black wires leaving the bottom of the pic go to a 9VDC wall wort that powers the entire system including the Arduino. When I was experimenting with the load cell, I found that it worked best with 3.3V. The scale out ot the box used two AA bateries in series which is approximately 3.0V, so this made sense. This load cell had four wires, which is pretty common. It had /- excitation and /- signal. The negative excitation goes to ground. The black wire coming from the left is the negative excitation voltage. The green wire goes to the positive excitation, and is the 3.3V from the Arduino. The red and white wires coming from the left are signal for red and - signal for white. What was cool about the scale that I bought and had no idea of beforehand, was that all four wires were labeled on the circuit board that the load cell was connected to! Red and black to the /- voltage, and the blue to signal and white to - signal. I'm not sure what the "I" stands for, but it ended up being signal. Also, I'm not sure why I didn't use red and black for voltage on my board, I just didn't. Feel free to change it on yours.

The Arduino board is pretty simple. Moving from left to right. The blue wire which connects to the green wire is the analog input. Even though it is hard to see, the next wire, red, is the regulated 5V that feeds the breadboard. The next wire, also red, comes from the 3.3V on the Arduino and goes to the Aref and the white wire (again, hard to see, sorry!) back to the breadboard to power the load cell. The next wire, black, is ground. It is very important to "common" your grounds when using multiple power supplies and/or devices. Last, but not least, is the feed from the wall wort to power up the Arduino. That is it for connections! Shall we talk about code?

Step 2: Coding It All

Coding the Arduino was pretty simple. Here is the code. Just upload to the Arduino, make all connections, and you are ready to go. Here is my completed scale. Again, the packaging stinks, but I wanted to get it up and running. I'll work on a better package. If you come up with something, let me know. After powering up the system, the value of the variable "fullKeg" is stored and every weight is then continuously subtracted giving you the values of tare, glass weight, beer weight, and the weight of beer left along with the percenatge of the keg on your serial monitor. I'm working on the VB.Net code. To reset the system after a new keg has been installed either power the system down or press the reset button. Here's the Arduino code:

int dataInPin = 5;
int goPin = 12;
//int tarePin = 8;
volatile int Flag = 0;
int quickDelay = 100;
int smallDelay = 500;
int bigDelay = 1000;
int checkVal;
int tareVal;
int glassVal;
int beerVal;
long fullKeg;
float kegWeight;
float percentLeft;

void setup()
  {
    fullKeg = 2070;  //full keg = 2070 (weight) ounces approx.
    kegWeight = fullKeg;
    percentLeft = 100;
    //pinMode(tarePin, INPUT);
    pinMode(goPin, OUTPUT);
    digitalWrite(goPin, LOW);
    Serial.begin(9600);
    analogReference(EXTERNAL);
    attachInterrupt(0, StartUp, CHANGE);
  }

void loop()
  {
     //if (digitalRead(tarePin) == HIGH)
     if (Flag == 7)
      {
        digitalWrite(goPin, LOW);
        tareVal = 0;
        tareVal = Tare();
        Flag = 1;
        digitalWrite(goPin, HIGH);
        delay(bigDelay);
      }
    while (Flag == 1)
      {
        digitalWrite(goPin, LOW);
        delay(quickDelay);
        digitalWrite(goPin, HIGH);
        delay(quickDelay);
        digitalWrite(goPin, LOW);
        delay(quickDelay);
        digitalWrite(goPin, HIGH);
        delay(quickDelay);
        checkVal = 0;
        checkVal = Tare();
        if (checkVal > (tareVal 5))
          {
            delay(smallDelay);
            glassVal = 0;
            digitalWrite(goPin, LOW);
            glassVal = Glass(tareVal);
            Flag = 2;
            digitalWrite(goPin, HIGH);
            delay(smallDelay);
            digitalWrite(goPin, LOW);
            delay(smallDelay);
            digitalWrite(goPin, HIGH);
            delay(smallDelay);
          }
       }
     while (Flag == 2)
       {
         digitalWrite(goPin, LOW);
         delay(quickDelay);
         digitalWrite(goPin, HIGH);
         delay(quickDelay);
         digitalWrite(goPin, LOW);
         delay(quickDelay);
         digitalWrite(goPin, HIGH);
         delay(quickDelay);
         digitalWrite(goPin, LOW);
         delay(quickDelay);
         digitalWrite(goPin, HIGH);
         delay(quickDelay);
         checkVal = 0;
         checkVal = Tare();
         if (checkVal > (glassVal tareVal 5))
           {
             delay(smallDelay);
             beerVal = 0;
             digitalWrite(goPin, LOW);
             beerVal = Beer(glassVal, tareVal);
             Flag = 0;
             kegWeight = kegWeight - (beerVal / 10.65);
             percentLeft = ((kegWeight / fullKeg) * 100);
             Serial.print(beerVal / 10.65);
             Serial.print("\r");
             Serial.print(kegWeight);
             Serial.print("\r");
             Serial.print(percentLeft);
             Serial.print("\r");
             digitalWrite(goPin, HIGH);
             delay(smallDelay);
             digitalWrite(goPin, LOW);
             delay(smallDelay);
             digitalWrite(goPin, HIGH);
             delay(smallDelay);
             digitalWrite(goPin, LOW);
             delay(smallDelay);
             digitalWrite(goPin, HIGH);
             delay(smallDelay);
             digitalWrite(goPin, LOW);
           } 
       }
  }

void StartUp()
  {
    Flag = 7;
  }

int Tare()
  {
    long Total = 0;
    for (int i = 0; i < 100; i )
     {
       Total = Total analogRead(dataInPin);
       delay(10);
     }
    Total = (Total / 100);
    return Total;
  }

int Glass(int NewTare)
  {
    long GlassWeight = 0;
    for (int i = 0; i < 100; i )
      {
        GlassWeight = GlassWeight analogRead(dataInPin);
        delay(10);
      }
    GlassWeight = ((GlassWeight / 100) - NewTare);
    return GlassWeight;
  }

int Beer(int NewGlass, int NewTare2)
  {
    long BeerWeight = 0;
    for (int i = 0; i < 100; i )
      {
        BeerWeight = BeerWeight analogRead(dataInPin);
        delay(10);
      }
    BeerWeight = ((BeerWeight / 100) - (NewGlass NewTare2));
    return BeerWeight;
  }


Copy and paste into the Adrduino IDE. The code assumes you are using a 1/2 barrel, 2070 ounces. If it is a 1/4 barrel, change the value of "fullKeg" to 1035.

*EDIT* (11/10/13) The code now uses one of the interrupts (see wire connections) to reset and start a read over in case of an error. I noticed that sometimes the scale would skip a step and read nothing. This helps with that. Also, I changed the LED code to blink quickly the number of times equal to the step you were on. One blink didn't tell me if I had just tared the scale or read the glass weight. Oh, and I now have a Windows App!

Arduino Contest

Participated in the
Arduino Contest