• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
Resource icon

Building a Simple Weight Scale 2018-08-12

Building a Simple Weight Scale


Not that long ago an opportunity came to learn about strain gages (load cells) and Sparkfun’s OpenScale project. I decided to acquire one of each and for the sake of speed I ordered both from Amazon. I immediately started playing with the available information, after some research and tweaks got something working, and then decided to build a small weight scale just to finish it up. What follows is a brief summary of what I did. Hopefully this work helps others down the road.


OpenScale Evaluation

The OpenScale project from Sparfun Electronics (i.e. SFE) is pretty cool and the best part is that is open source. The basic information can be found in SFE’s OpenScale Applications and Hookup Guide, and the code repository can be found in github. The code in the Github’s repository is pretty elaborated as it includes temperature, logging, and other functions. I wanted something simpler so I decided to create the code using a different baseline. I researched a bit more and ended using a combination of the HX711 SFE library and the original HX711 library.


Using this code base I was able to get the OpenScale board talking to the load cell fairly quickly and with good repeatable results.

SFE OpenScale1.jpg SFE OpenScale2.jpg


Load Cell Calibration:

It is essential to calibrate the “response” of the load cell used. Every load cell has a slightly different response. If one thinks of the load cell as a simple linear equation (i.e. y = m*x + b), then one needs to find the slope (m) and intercept (b) of the equation through calibration. Once this is obtained the load cell can be re-used repeatedly without further calibration. The code currently does this every time OpenScale is powered up. It will ask to calibrate the load cell, which will be necessary the first time the load cell is connected to OpenScale. Once the calibration cycle is completed, the power-up calibration cycle can just be ignored as the value previously used will be stored in EEPROM memory and will be used until a new (different) value is stored.

load cell.jpg


Putting it all Together

After connecting everything together following the SFE guide and some debugging of the code I was able to calibrate the scale and get readings that were both repeatable and that seemed reasonably accurate. A small physical prototype of the proto weight scale (base and pan) was created in a 3D CAD tool, it was then printed and assembled.

load cell - platform.png

SFE OpenScale - prototype1.jpg SFE OpenScale - prototype2.jpg


Code

Code:
/*
  Example HX711 code using OpenScale
  @languer 2018

  This example demonstrates basic scale output. See the calibration sketch to get the calibration_factor for your
  specific load cell setup.

  Arduino pin
  3 -> HX711 CLK (modified to work with open scale, use pin 2 for HX711 breakout)
  2 -> DAT (modified to work with open scale, use pin 3 for HX711 breakout)
  5V -> VCC
  GND -> GND

    Board: Arduino/Genuino Uno
    Programmer: AVR ISP
*/

/************************* HX711 Setup *********************************/
#include "HX711.h"
#define RESOLUTION  6     //decimal places of HX711 reading
#define AVG_FACT 8        //averagin factor of HX711 reading
#define DOUT  2           //data IO of HX711
#define CLK  3            //clock input of HX711
HX711 scale(DOUT, CLK);

/************************* EEPROM Setup *********************************/
#include <EEPROM.h>
#define EEP_CAL_FLAG_ADDR  0      //eeprom calibration flag address, flag occupies 1 byte
#define EEP_CAL_DATA_ADDR  1      //eeprom calibration data address; data occupies 4 bytes
byte eepCalFlag = 0;
long calibrationFactor_l = 535; //initial guess (for 0-5kg uxcell cell)


/************************* SETUP *********************************/
void setup() {
  Serial.begin(9600);
  Serial.println("OpenScale demo");
  calibrateOpenScale();  // calibrate scale
  Serial.println("Take OpenScale Readings");  // read scale
  delay(2500);
}


/************************* MAIN *********************************/
void loop() {
  readOpenScale();
}


/************************* HX711 CALIBRATION *********************************/
void calibrateOpenScale() {
  Serial.println("OpenScale calibration sketch");
  Serial.println("Remove all weight from scale");
  delay(5000);
  Serial.println("After readings begin, place known weight on scale");
  Serial.println("Press a to increase calibration factor by 10");
  Serial.println("Press d to increase calibration factor by 100");
  Serial.println("Press g to increase calibration factor by 1000");
  Serial.println("Press z to decrease calibration factor by 10");
  Serial.println("Press c to decrease calibration factor by 100");
  Serial.println("Press b to decrease calibration factor by 1000");
  Serial.println("Press x to exit calibration");
  delay(5000);

  //initialize calibration
  eepCalFlag = EEPROM.read(EEP_CAL_FLAG_ADDR);
  //get cal value from eeprom if exists
  if (eepCalFlag == 128) {
    EEPROM.get(EEP_CAL_DATA_ADDR, calibrationFactor_l);
  }
  float calibrationFactor_f = calibrationFactor_l;

  scale.set_scale();  //reset scale to default (0)
  scale.tare();    //reset the scale to 0
  long zero_factor = scale.read_average(); //Get a baseline reading

  Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
  Serial.println(zero_factor);

  boolean calibrateFlag = true;
  while (calibrateFlag) {
    scale.set_scale(calibrationFactor_f);  //Adjust to this calibration factor
    Serial.print("Reading (grams, raw, cal factor): ");
    Serial.print(scale.get_units(4), 3);
    Serial.print(" , ");
    Serial.print(scale.read_average());
    Serial.print(" , ");
    Serial.print(calibrationFactor_f);
    Serial.println();

    if (Serial.available()) {
      char temp = Serial.read();
      if (temp == 'a') {
        calibrationFactor_f += 10;
      }
      else if (temp == 'd') {
        calibrationFactor_f += 100;
      }
      else if (temp == 'g') {
        calibrationFactor_f += 1000;
      }
      else if (temp == 'z') {
        calibrationFactor_f -= 10;
      }
      else if (temp == 'c') {
        calibrationFactor_f -= 100;
      }
      else if (temp == 'b') {
        calibrationFactor_f -= 1000;
      }
      else if (temp == 'x') {
        calibrateFlag = false;
      }
    }
  }

  //exit calibration and store calibration in EEPROM
  {
    eepCalFlag = 128;
    EEPROM.write(EEP_CAL_FLAG_ADDR, eepCalFlag);
    calibrationFactor_l = calibrationFactor_f;
    EEPROM.put(EEP_CAL_DATA_ADDR, calibrationFactor_l);
    Serial.println("Exiting calibration sequence");
  }
}


/************************* READ HX711 *********************************/
void readOpenScale() {
  Serial.print("Reading: ");
  Serial.print(scale.get_units(AVG_FACT), RESOLUTION); //scale.get_units() returns a float
  Serial.print(" grams");  //grams or kilograms depending on load cell
  Serial.println();
  delay(1000);
}
Author
languer
First release
Last update
Rating
0.00 star(s) 0 ratings

More resources from languer

Latest threads

EE World Online Articles

Loading

 
Top