Adrian Smith
Published © GPL3+

A digital weigh scale controller for HX711 load cell modules

A 5 digit digital weighing scale controller designed to be used with commonly available HX711 modules and a load cell.

IntermediateWork in progress4 hours162
A digital weigh scale controller for HX711 load cell modules

Things used in this project

Software apps and online services

Atmel START
Microchip Atmel START
Arduino IDE
Arduino IDE
KiCad
KiCad

Story

Read more

Custom parts and enclosures

Bill of materials

List of electronic components used

Schematics

hx711_weigh_scale_schematic_KmSdZUb265.jpg

Code

Prototype controller code

C/C++
The microcontroller firmware used to run the scale
// Weigh scale up 10KG

#include <avr/pgmspace.h> 
#include <avr/io.h>
#include <SPI.h>
#include <Wire.h>
#include <HX711_ADC.h>

const int tare_sw = 9; 
long int offset = 0;
long int calfactor = 0;
int digit = 0;

const int clk = 13; // SRCK
const int latch = 10; // RCK
const int data = 11; // DIN
const int OE = 14; // output enable
const int digit0 = 2;
const int digit1 = 3;
const int digit2 = 4;
const int digit3 = 5;
const int digit4 = 6;

HX711_ADC LoadCell(8, 7); // parameters: dt pin, sck pin

// 7-segment digits 0-9
// {Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7} --> {g, f, e, d, c, b, a, DP} 
byte ssddigits[10] = // array without decimal points on
{
  B01111110,  // 0
  B00001100,  // 1
  B10110110,  // 2
  B10011110,  // 3
  B11001100,  // 4
  B11011010,  // 5
  B11111010,  // 6
  B01001110,  // 7
  B11111110,  // 8
  B11011110,  // 9
};

byte ssddigitsDP[10] = // array with decimal points on
{
  B01111111,  // 0
  B00001101,  // 1
  B10110111,  // 2
  B10011111,  // 3
  B11001101,  // 4
  B11011011,  // 5
  B11111011,  // 6
  B01001111,  // 7
  B11111111,  // 8
  B11011111,  // 9
};

void setup()
{
    pinMode (tare_sw, INPUT_PULLUP);
    pinMode (clk, OUTPUT);
    pinMode (latch, OUTPUT);
    pinMode (data, OUTPUT);
    pinMode (OE, OUTPUT); // use external pull-up 
    pinMode (digit0, OUTPUT);
    pinMode (digit1, OUTPUT);
    pinMode (digit2, OUTPUT);
    pinMode (digit3, OUTPUT);
    pinMode (digit4, OUTPUT);
    //Serial.begin(9600); // for testing. Serial not connected in final version
    LoadCell.begin(); // start connection to HX711
    LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
    //calfactor = analogRead(1);
    //LoadCell.setCalFactor(calfactor);
    LoadCell.setCalFactor(201.4); // calibration factor for load cell => strongly dependent on your individual setup
    LoadCell.tareNoDelay(); // cancel out weight of the plate attached to the sensor
    digitalWrite(OE,LOW); // turn LED display on. OE / G is pulled up to +5V externally by 4.7K resistor.
    //This prevents LED burnout if at power on / bootup random segments are lit (multiplexing code will not be running)
}

void loop()
{
    LoadCell.update(); // retrieves data from the load cell
    long int grams = LoadCell.getData() -offset; // get output value
    //long int grams = 12345; // for testing
    //Serial.println(grams);
       
    static uint16_t btndbc = 0;
    btndbc=(btndbc<<1) | digitalRead(tare_sw) | 0xe000; // debounce button
     if (btndbc==0xf000)  
          
     {
        delay(1); // wait 1 millisecond
        offset = LoadCell.getData(); // read initial HX711 value and store it as offset  
     } 

    // get digit data. Digit 0 is leftmost
    int dig4 = (grams % 10); // ones 
    int dig3 = (grams / 10) % 10; // tens     
    int dig2 = (grams / 100) % 10; // hundreds  
    int dig1 = (grams / 1000) % 10; // thousands
    int dig0 = (grams / 10000) %10; // ten thousands
   
    delay(1);

    // turn all digits off by setting digit pin high on each loop through. 
    PORTD |= (1<<PORTD2);
    PORTD |= (1<<PORTD3);
    PORTD |= (1<<PORTD4);
    PORTD |= (1<<PORTD5);
    PORTD |= (1<<PORTD6);

   if (grams <-9 || grams >10010) // show error if minus figure or scale is overloaded

    {
     switch (digit)
     {
      case 0:
        SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
        PORTB &= ~(1<<PORTB2); // set latch LOW 
        SPI.transfer(B11110010); //E
        PORTB |= (1<<PORTB2); // set latch HIGH
        SPI.endTransaction();
        PORTD &= ~(1<<PORTD2); // set digit pin 0 LOW
        delay(2);
        break;
 
      case 1:
        SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
        PORTB &= ~(1<<PORTB2); // set latch LOW 
        SPI.transfer(B10100000); // r
        PORTB |= (1<<PORTB2); // set latch HIGH
        SPI.endTransaction();
        PORTD &= ~(1<<PORTD3);
        delay(2);
        break;    
 
      case 2:
        SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
        PORTB &= ~(1<<PORTB2); // set latch LOW 
        SPI.transfer(B10100000); //r
        PORTB |= (1<<PORTB2); // set latch HIGH
        SPI.endTransaction();
        PORTD &= ~(1<<PORTD4);
        delay(2);
        break; 
 
      case 3:
        SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
        PORTB &= ~(1<<PORTB2); // set latch LOW 
        SPI.transfer(B10111000); // o
        PORTB |= (1<<PORTB2); // set latch HIGH
        SPI.endTransaction();
        PORTD &= ~(1<<PORTD5);
        delay(2);
        break; 

      case 4:
        SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
        PORTB &= ~(1<<PORTB2); // set latch LOW 
        SPI.transfer(B10100000); //r
        PORTB |= (1<<PORTB2); // set latch HIGH
        SPI.endTransaction();
        PORTD &= ~(1<<PORTD6);
        delay(2);
        break;
      }
 
        digit++;
    
    if (digit == 5)
      {
        digit = 0;
      }
   }
    
    else // display normally
    {
      switch (digit)
      {
        case 0:
          SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
          PORTB &= ~(1<<PORTB2); // set latch LOW 
          SPI.transfer(ssddigits[dig0]);
          PORTB |= (1<<PORTB2); // set latch HIGH
          SPI.endTransaction();
          PORTD &= ~(1<<PORTD2); // set digit pin 0 LOW
          delay(2);
          break;
 
        case 1:
          SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
          PORTB &= ~(1<<PORTB2); // set latch LOW 
          SPI.transfer(ssddigitsDP[dig1]); // put a decimal point here. HX711 output is in grams and display will show in KG.
          PORTB |= (1<<PORTB2); // set latch HIGH
          SPI.endTransaction();
          PORTD &= ~(1<<PORTD3);
          delay(2);
          break;    
 
        case 2:
          SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
          PORTB &= ~(1<<PORTB2); // set latch LOW 
          SPI.transfer(ssddigits[dig2]);
          PORTB |= (1<<PORTB2); // set latch HIGH
          SPI.endTransaction();
          PORTD &= ~(1<<PORTD4);
          delay(2);
          break; 
 
        case 3:
          SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
          PORTB &= ~(1<<PORTB2); // set latch LOW 
          SPI.transfer(ssddigits[dig3]);
          PORTB |= (1<<PORTB2); // set latch HIGH
          SPI.endTransaction();
          PORTD &= ~(1<<PORTD5);
          delay(2);
          break; 

          case 4:
          SPI.beginTransaction(SPISettings(8000000, LSBFIRST, SPI_MODE0));
          PORTB &= ~(1<<PORTB2); // set latch LOW 
          SPI.transfer(ssddigits[dig4]);
          PORTB |= (1<<PORTB2); // set latch HIGH
          SPI.endTransaction();
          PORTD &= ~(1<<PORTD6);
          delay(2);
          break;
      }
 
     digit++;
    
    if (digit == 5)
      {
        digit = 0;
      }
   }
}

Credits

Adrian Smith

Adrian Smith

6 projects • 2 followers
Electronics engineer for around 10 years, repair electronic LED signs and other old electronics from the 1980 / 1990's.

Comments