Hive scale design

I’ve constructed a set-up with a wooden frame to hold two weight sensor (load cells) max. 40kg one one side. Linked up to the Autonomo and two HX-711 amplifiers.

Does anyone have a similar set-up? What is your experience with:

  1. best battery specs especially for the loadcells (required 10-15V)
  2. accuracy of the readings
  3. calibration; tips for approach/code
  4. correction for temperature influence (needed at all)?

Thanks!

I suggest you look at the Sparkfun HX711 hookup guide

https://learn.sparkfun.com/tutorials/load-cell-amplifier-hx711-breakout-hookup-guide?_ga=1.262093709.1832058581.1462535891

this will point you to the Bogde library and includes calibration and known zero startup sketches.

I haven’t noticed any particular temperature effects but I’m in the process of more formally testing reading stability.

I run a Seeeduino Stalker with a SODAQ GPRSbee and also some Arduino Pro Mini and ESP8266 (last two in prototyping state).

I have a Bosche H30A and the spec says from 5V on but I run the HX711 or ADS1231 and the load cell with 3.3 V with no downside (till now I see no!).

I have a accuracy of +/- 15 g in a stable environment on the work bench. Outside is it about +/- 25 g on a 200 kg load cell but also with rain outside and not so good controllable conditions. I don’t think that we need temperature control. As I see it on my data battery voltage has more influence.

As luck would have it I wrote yesterday a sketch to adjust the scale, it’s for the ADS1231 but I think you can easily modify it for the HX711:

/*
  Open Hive | Scale Adjustment
  ---------------------------- 
    | Scale 

  Copyright (C) 2016 by Clemens Gruber 
    
  2016-03 Clemens Gruber | initial version 


  GNU GPL v3 License 
  ------------------
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  Licence can be viewed at                               
  http://www.gnu.org/licenses/gpl-3.0.txt


  pins hard coded
  ---------------
  D14 D15 D16  Data, SCL, Power ADS1231
  D17          Power load cell and ADS1231
*/

// -------------------------+------
// variables you can modify | START
// -------------------------+------

// ** load cell characteristic
// --------------------------- 
// define here individual values for the used load cell
// this is not type specific! even load cells of the same type /
// model have individual characteristics 
//
// - ZeroOffset is the raw sensor value for "0 kg"
//   write down the sensor value of the scale with no load and 
//   adjust it here
// - KgDivider is the raw sensor value for a 1 kg weight load
//   add a load with known weight in kg to the scale, note the 
//   sesor value, calculate the value for a 1 kg load and adjust 
//   it here
// will be re-set in the adjustment part of this sketch
long loadCellZeroOffset = -3048064;
long loadCellKgDivider  = 5659648;

// wait between samples
// 3 sec is a good delay so that load cell did not warm up 
// too much and external random influences like wind has time 
// to go so that the next sample is more valid
const int waitTimeLoadSamples = 3; 

// ** median statistics (for weight)
// ---------------------------------
// number of readings for median samples
// 5 is a good compromise between time cost and stable output
int weightSamplesNumber = 10; 

// -------------------------+----
// variables you can modify | END
// -------------------------+----

// libraries
// load cell
#include <ADS1231.h>  
ADS1231 loadCell;  // create ADS1231 object
int adjustScale = true;  // flag for adjust vs. operation mode 
long weightSensorValue;
float weightKg;

// median statistics to eliminate outlier
#include <RunningMedian.h>
RunningMedian weightSamples = RunningMedian(weightSamplesNumber);  // create RunningMedian object

// power saving 
#include <LowPower.h>


void setup() {
  // serial communication
  Serial.begin(9600);
  
  Serial.println("Scale Adjustment for Open Hive / ADS1231");
  Serial.println("----------------------------------------");
  Serial.println();
  
  // load cell / ADS1231 pin definition: SCL 15, Data 14, Power 16
  loadCell.attach(15,14,16);

  // powers load cell and ADS1231: pin 17 
  pinMode(17, OUTPUT);


  // adjust scale 
  // ------------
  
  // Step 1: tare scale 
  Serial.println(">> Step 1: tare scale");
  Serial.println("   ------------------");
  Serial.println("   Remove all weight from the scale!");
  Serial.println("   (If done, input any character to continue ...)");
  Serial.println(); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  Serial.read();  // clear serial input d
  
 
  // get Weight n times and calculate median 
  Serial.println("Get raw values for tare: ");
  getWeight();
  Serial.println(); 
  outputStatisticRawValues(); 
  // set the median as zero offset value 
  loadCellZeroOffset = weightSamples.getMedian(); 

  // Step 2: weight lower limit
  Serial.println(">> Step 2: weight lower limit");
  Serial.println("   --------------------------");
  Serial.println("   Load at least 1 kg to the scale so that the raw values are > 0!");
  Serial.println("   (If done, input any character to continue ...)");
  Serial.println(); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  Serial.read();  // clear serial input 
  
  // get Weight n times and calculate median 
  Serial.println("Get raw values for lower limit: ");
  getWeight();
  Serial.println(); 
  outputStatisticRawValues(); 
  long lowerValue = weightSamples.getMedian(); 
  
  // Step 3: weight upper limit
  Serial.println(">> Step 3: weight upper limit");
  Serial.println("   --------------------------");
  Serial.println("   Put a know load on the scale! ...");
  Serial.println("   ... and input weight in gram ...");
  Serial.println(); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  long kgValue = Serial.parseInt();
  
  // get Weight n times and calculate median 
  Serial.print("Get raw values for upper limit - "); 
  Serial.print(kgValue); 
  Serial.print(" g: ");
  Serial.println();
  getWeight();
  Serial.println(); 
  outputStatisticRawValues(); 
  long upperValue = weightSamples.getMedian(); 
  
  // calculate loadCellKgDivider
  loadCellKgDivider = (upperValue - lowerValue) / (kgValue/1000); 

  // output calculated parameter
  Serial.println(">> Done! Your calculated parameters:");
  Serial.println("   ---------------------------------");
  Serial.println();
  Serial.print("   loadCellZeroOffset: ");
  Serial.print(loadCellZeroOffset);
  Serial.println();
  Serial.print("   loadCellKgDivider:  ");
  Serial.print(loadCellKgDivider);
  Serial.println();
  Serial.println("   ---------------------------------");
  Serial.println();
  
  Serial.println("You can test your calculated settings now!");
  Serial.println("(Input any character to continue ...)"); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  Serial.read();  // clear serial input 
  Serial.println();
}


void loop() {
  // test settings 
  // ------------
  adjustScale = false; 
  
  // re-set number of weight sample
// does not work 
//  weightSamplesNumber = 5; 
//  RunningMedian weightSamples = RunningMedian(weightSamplesNumber);  // create RunningMedian object

  getWeight();
  Serial.println(); 
  outputStatisticKgValues(); 
}


// functions
// ---------

// read raw data 
void getWeight() {
  // clear running median samples 
  weightSamples.clear();
  
  // read x times weight and take median 
  // do this till running median sample is full  
  do {

// wait between samples
Serial.flush();
for (int i=0; i<waitTimeLoadSamples; i++) {
// sleep for one second
LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // delay 60 ms
}

// power ADS1231 / load cell
digitalWrite(17, HIGH);
loadCell.power(HIGH);

delay(2); // wait for stabilizing

// ADS1231 ready?
while (!loadCell.check()) {
loadCell.check();
}

// read raw data input of ADS1231
weightSensorValue = loadCell.readData();

// switch off ADS1231 / load cell
loadCell.power(LOW);
digitalWrite(17, LOW);

// calculate weight in kg
weightKg = ((float)weightSensorValue - (float)loadCellZeroOffset) / (float)loadCellKgDivider;

// add single value to runnig median sample
if (adjustScale == true) {
// use raw values for median statistic
weightSamples.add(weightSensorValue);
// debug raw values
Serial.println(weightSensorValue);
}
else
{
// use calculated kg values for median statistic
weightSamples.add(weightKg);
Serial.print(".");
}
} while (weightSamples.getCount() < weightSamples.getSize());
}

// print statistics for raw values 
void outputStatisticRawValues() {
  // debug
  Serial.println("Low \t\tAvg \t\tMed \t\tHigh \t\tDiff");
  Serial.print(weightSamples.getLowest(),0);
  Serial.print("\t");
  Serial.print(weightSamples.getAverage(),0);
  Serial.print("\t");
  Serial.print(weightSamples.getMedian(),0);
  Serial.print("\t");
  Serial.print(weightSamples.getHighest(),0);
  Serial.print("\t");
  Serial.println(weightSamples.getLowest()-weightSamples.getHighest(),0);
  Serial.println(); 
}

// print statistics for kg values 
void outputStatisticKgValues() {
  // debug
  Serial.println("Low \tAvg \tMed \tHigh \tDiff");
  Serial.print(weightSamples.getLowest(),3);
  Serial.print("\t");
  Serial.print(weightSamples.getAverage(),3);
  Serial.print("\t");
  Serial.print(weightSamples.getMedian(),3);
  Serial.print("\t");
  Serial.print(weightSamples.getHighest(),3);
  Serial.print("\t");
  Serial.println(weightSamples.getLowest()-weightSamples.getHighest(),3);
  Serial.println(); 
}

There are updated sketches for adjustment / “calibration” on the “Hive scale code” thread:

1 Like