Load cells

Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum

Help Support Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

paledragon

Well-Known Member
Joined
Aug 19, 2008
Messages
136
Reaction score
11
Location
Bridgewater, MA
Hey everyone,

I'm working at a snail's pace converting my electric system over to Bru Control. First thing I decided to tackle was volume measurements. I decided to go with load cells, which did require me to learn how to solder headers onto circuit boards. I've still got some work to do, and maybe some of you guys will have pointers as well.

Overall, it's comprised of:
  • 0-50kg micro load cells from RobotShop ($7 each)
  • Load cell amplifier from Sparkfun ($10)
  • Arduino Mega2560 ($10 inland version)
I'll start with the finished setup. Two vessel system sitting on platforms sitting on load cells:
View media item 69340
Load cells are sandwiched between 1/2" sheets of plywood, with metal ties on the diagonally opposed load cells for support:
View media item 69349View media item 69342
HX711 (aka the load cell amplifier) has a standard Arduino package. I temporarily combined that with an LCD shield, since I haven't gotten to the Bru Control portion of the project yet:

View media item 69348
The plan is to have this Arduino read in multiple HX711s (HLT/BK, MLT, etc.), send PWM outputs to the Bru Control analog amplifier to convert to 0-5 VDC output, then have those signals go to a second Ardiuno Mega running Bru Control. The load cell Ardiuno will probably be tweaked to convert the PWM outputs from 8-bit resolution to something along the lines of 10- or 12-bit minimum.

Casual testing seems to indicate load cell creep is pretty insignificant. The spec sheet on these load cells seems to corroborate that.

Hopefully this plants the seed for other ideas where these can be used. Most of the components are pretty cheap, so destroying them in the process of exploring applications isn't too much of a concern :)

p.d.
 
Very cool. I've thought about doing load cells before in order to measure out my water more precisely and also tracking mass throw the process. I was warned that drift would be a major problem though so i never proceeded.

How accurate do they seem to be?
 
  • 0-50kg micro load cells from RobotShop ($7 each)
  • Load cell amplifier from Sparkfun ($10)


Links? I'm going to be following this thread closely. I'm torn between load cells (and calibration issues) and more holes in my kettles for pressure sensors.
 
Links are:

https://www.sparkfun.com/products/13879

https://www.robotshop.com/en/micro-load-cell-50-kg.html

Load cells are made by phidgets, so you could probably order directly from them as well. Robotshop has the data sheet on their website that gives specs.

At least for these load cells:
  • Calibration is a breeze. Put on a known weight, adjust the multiplication factor in the Arduino code, and you're done. The LCD shield has buttons on it, so you could modify the Arduino code to adjust calibration via buttons instead of manually in the serial window.
  • I plotted ~10 points from 0-100 lbs, and the R^2 was 1 when I fit a line in Excel for actual versus predicted.
  • Spec sheet has creep at 0.1% full scale per 30 minutes. Full scale is 440 lbs, or 53 gallons assuming 8.3 lbs per gallon. 53 * 0.001 is 0.053 gallons of drift per 30 minutes. Not too shabby!
I'd keep your expectations low for how fast I move this along, I've got little kids :D The other things I like about it:
  • I'm adding the misting nozzle/steam condenser to my boil kettle. I'll be able to monitor the level of condensate and the rate of collection.
  • I can throw my conical on one, as well as monitor the level of the glycol reservoir. More for alarming than control, but at some point I'm sure switching over to Bru Control for fermentation will be in the cards.
  • I think I should be able to really start measuring how much liquid is lost during mashing to grain absorbtion.
p.d.
 
Awesome sauce. Thanks for the info. I'm using BC, so no direct Arduino coding for me, thank you very much. I've heard rumors that the next iteration of BC will have progressive calibration slopes, which should take care of the Excel requirement pretty handily.

My rig has flat-bottomed kettles, so the physical install might be a little simpler than what you have. I'm still on the fence about punching a hole in the bottoms of my shiny kettles for pressure sensors, so I may give this a whirl. I just posted a separate thread about temp-rated flowmeters, which would be a critical part of the equation.
 
Might as well close the loop on this one...

There's a few options for getting load cell output into BruControl:
  1. The PWM to VDC (AA-1) converter sold by BruControl. Bought one, confirmed it worked, but found a better solution, for me anyway.
  2. Emulate the load cell value as a 1wire temperature probe. Confirmed it worked, but found it slightly more convoluted than #3, and the resolution wasn't as good either.
  3. Using the Timer1 or Timer3 library, use a second Arduino to read the load cells and generate a variable frequency PWM signal fed into the BruControl Mega.
So I went with option 3. Got Timer1 up and running on an Uno, and Timer3 up and running on a Mega.

Example Uno code below, serial terminal stuff is optional:

/*
HX711 CLK > LoadCells Uno PWM 2
HX711 DAT > LoadCells Uno PWM 3
HX711 GND > LoadCells Uno GND
HX711 +5V > LoadCells Uno +5V
LoadCells Uno PWM 9 > BruControl Mega PWM 18
*/

#include <HX711_ADC.h>
#include "TimerOne.h";

//HX711 constructor (dout pin, sck pin)
HX711_ADC LoadCells(3,2);

// variable declaration

long t;
double LoadCellsCV;
long stabilisingtime = 2000;
int PeriodCV = 2000;
double FreqCV = 500;
double FreqMin = 500;
double FreqSpan = 25000;
double FreqMax = FreqMin + FreqSpan;
double MaxScaleWeight = 200;
double FreqSlope = (FreqMax - FreqMin)/MaxScaleWeight;
int PWMOutputPin = 9;
int PWMDutyCycle = 512;
double LoadCellCalFactor = 4818.0;

// setup loop

void setup(){
Serial.begin(9600);
Serial.println("Wait...");
LoadCells.begin();
LoadCells.start(stabilisingtime);
LoadCells.setCalFactor(LoadCellCalFactor);
Serial.println("Startup and tare complete.");
delay(2000);
Timer1.initialize(800);
Timer1.pwm(PWMOutputPin, PWMDutyCycle);
}

// load cell loop

void loop(){

LoadCells.update();

//receive from serial terminal

if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCells.tareNoDelay();
Serial.println("Scale tared.");
}

//get smoothed value from data set + current calibration factor

if (millis() > t + 1000){
LoadCellsCV = LoadCells.getData();
Serial.println(LoadCellsCV);
FreqCV = FreqMin + FreqSlope * LoadCellsCV;
if (FreqCV < FreqMin){
FreqCV = FreqMin;
}
if (FreqCV > FreqMax){
FreqCV = FreqMax;
}
PeriodCV = int(1000000 / FreqCV);
Timer1.pwm(PWMOutputPin,PWMDutyCycle, PeriodCV);
t = millis();
Serial.println(FreqCV);
}
}
 
Adding option number 4, which is relatively equivalent to option 3...

4. Add an MCP4725 12-bit DAC to enable a 0-5VDC output from the load cell arduino to send over to the arduino running BruControl.

SparkFun link to show how to solder the headers on so you can just plug it into an Uno:
https://learn.sparkfun.com/tutorials/mcp4725-digital-to-analog-converter-hookup-guide

Code to enable a 0-5VDC output from the load cell arduino:

Code:
/*
Arduino Uno code for reading load cells via an HX711 board
and generating a 0-5 VDC output with an MCP4725 board.
MCP4725 has 12-bit resolution and takes 0-4095 as an argument.

Wiring:
HX711 to Uno -
GND > GND
CLK > 2
DAT > 3
VDD and VCC > +5 VDC

Uno to MCP4725 -
A2 > GND
A3 > VCC
A4 > SDA
A5 > SCL

MCP4725 to BruControl (Mega) -
GND > GND
Out > Analog Input
*/

#include <HX711_ADC.h>
#include <Wire.h>
#include <Adafruit_MCP4725.h>

// Constructors
Adafruit_MCP4725 VDCOut;
HX711_ADC LoadCells(3,2);

// Variable declaration
long t;
long StabilizingTime = 2000;
double LoadCellsCV;
double VDC_CV;
double VDC_Slope;
double VDC_Min = 0.0;
double VDC_Max = 4095.0;
double MaxScaleWeight = 128.65; //15.5 gal * 8.3 lbs/gal
double LoadCellCalFactor = 4818.0;

// setup loop

void setup(){
 
  // power DAC board with pins A2 and A3
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  digitalWrite(A2, LOW);
  digitalWrite(A3, HIGH);
 
  // initialize DAC
  VDCOut.begin(0x60);
  VDC_Slope = (VDC_Max-VDC_Min)/MaxScaleWeight;
 
  // initialize HX711
  LoadCells.begin();
  LoadCells.start(StabilizingTime);
  LoadCells.setCalFactor(LoadCellCalFactor);
  delay(2000);
 
}

// load cell loop

void loop(){
 
  LoadCells.update();
 
  //get load cell current value, convert to VDC current value, and update DAC output
  if (millis() > t + 1000){
    LoadCellsCV = LoadCells.getData();
    VDC_CV = VDC_Min + VDC_Slope * LoadCellsCV;
 
    // ensure VDC is always between 0 and 4095
    if (VDC_CV < VDC_Min) VDC_CV = VDC_Min;
    if (VDC_CV > VDC_Max) VDC_CV = VDC_Max;
    t = millis();
    VDCOut.setVoltage(VDC_CV, false);
  }
}
 
Last edited:
I wonder how to account the drift. Say for keg monitoring.
If it is a linear kind of thing it would be easy to put into a script. If not. Hrmm
 
Would it be possible to post the code you used to drive the MEGA and the LCD display?

pretty sure this is what I was using...

Code:
#include <HX711_ADC.h>
#include <LiquidCrystal.h>

//HX711 constructor (dout pin, sck pin)
HX711_ADC HLT(A15, A14);

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// variable declaration

int lcd_key     = 0;
int adc_key_in  = 0;
long t;
char HLToutstr[15];
double HLTLoadCellCV;
long stabilisingtime = 2000;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
 
// read LCD buttons

int read_LCD_buttons()
{
 adc_key_in = analogRead(0);
 if (adc_key_in > 1000) return btnNONE;
 if (adc_key_in < 50)   return btnRIGHT;
 if (adc_key_in < 195)  return btnUP;
 if (adc_key_in < 380)  return btnDOWN;
 if (adc_key_in < 555)  return btnLEFT;
 if (adc_key_in < 790)  return btnSELECT;
 return btnNONE;
}

void setup(){
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.clear();
  lcd.print("Setting up...");
  delay(2000);
 
  HLT.begin();
  HLT.start(stabilisingtime);
  HLT.setCalFactor(4928.0);
  lcd.clear();
  lcd.print("Tare complete.");
  delay(2000);
}

void loop(){
  lcd_key = read_LCD_buttons();
  switch (lcd_key){
    case btnUP:{
      HLT.tareNoDelay();
      lcd.clear();
      lcd.print("Taring HLT...");
      delay(2000);
      break;
    }
  }
 
  HLT.update();

  //get smoothed value from data set + current calibration factor
 
  if (millis() > t + 1000){
    HLTLoadCellCV = HLT.getData();
    dtostrf(HLTLoadCellCV,8,2,HLToutstr);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("HLT:");
    lcd.print(HLToutstr);
    lcd.print(" Gal");
    t = millis();
  }
}
 
Anyone think of doing this with prebuilt scales by tying into the display? I have a 'NTEP 2500lb/0.5lb 3'x3' Heavy Duty Floor Scale w/ PS-IN202 Indicator' I would like to tie into it via the serial port (they gave a generic USB-serial adapter also)

Ideally, the end result would be having serial to wifi using a 8266/SonOff/feather to talk to BruControl or CBP3

(FYI - I have no problem with drift, and the scale is NTEP rated) The importer has specs on the datastream.. https://www.prime-scales.com/product/ps-in202-ntep-legal-trade-weight-indicator/
 
Yo @paledragon couple of questions if you don't mind.

1. Does your platform sit resting on those 4 bolts out of the load sensor or does it sit on the steel cross that you built?
2. I gather you just read all 4 sensors and add the values together to get the total load? Or is there more to it?
3. Could you explain the drift a little more please? 1.5oz / 45g every 2 hours. Do you need to tare the system before you start using it, so it's accurate for the course of the brewday?

Cheers, great to see someone else doing something similar to what I'm planning.
 
Yo @paledragon couple of questions if you don't mind.

1. Does your platform sit resting on those 4 bolts out of the load sensor or does it sit on the steel cross that you built?
2. I gather you just read all 4 sensors and add the values together to get the total load? Or is there more to it?
3. Could you explain the drift a little more please? 1.5oz / 45g every 2 hours. Do you need to tare the system before you start using it, so it's accurate for the course of the brewday?

Cheers, great to see someone else doing something similar to what I'm planning.

It sits on the bolts. The diagonally opposite load cells point away from each other, and the steel bar connecting them is meant to relieve the torque on the plywood.

All the same color wires coming off the load cells are just tied together as one. So instead of reading each individual load cell, they effectively act as one load cell. So there’s only 1 value to read.

Drift means over a certain amount of time, the load cell reading will change despite the weight on the scale being the same. Some load cells have horrible drift, but for brewing purposes, the drift on these is more than acceptable.

Taring is a software thing, so the Arduino code tares every time the power is turned on, but you can add code to manually tare as well. You can probably script the same thing into brucontrol as well.

p.d.
 
Back
Top