load cell value fluttering

Hi, I am doing an IOT weight scale using Mega and ESP-01 to measure weight of objects and identify whether it is within the acceptable range or not. I referred to this website Weighing Machine using Arduino Load Cell & HX711 Module for the code and tried to modify according to my needs. I tried out his code and the value of the load cell is quite consistent (-1 to 1) after calibration which is acceptable for me. However, when I uploaded my code to the device, the values flutter too much and is not consistent. Does someone have any idea why is it like this?

Here is my code:

#define BLYNK_PRINT Serial

#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

#include <LiquidCrystal.h>
#include <Keypad.h>

#define DT A0         
#define SCK A1        
#define sw 29         //input push button
#define buzzer 31     //output buzzer
#define led_red 30    //output led red
#define led_green 28  //output led green

LiquidCrystal lcd(7,6,5,4,3,2);

const byte numRows= 4;//Rows and columns of the keypad
const byte numCols= 4;
 
char keymap[numRows][numCols]=    //Keypad map
          {
          {'1', '2', '3', 'A'}, 
          {'4', '5', '6', 'B'}, 
          {'7', '8', '9', 'C'},
          {'*', '0', '#', 'D'}
          };

byte rowPins[numRows] = {38,39,40,41}; //Keypad 8 pins
byte colPins[numCols]= {42,43,44,45};

Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

//Authorization token, WiFi ID and password for Blynk
char auth[] = "xxx";
char ssid[] = "xxx";
char pass[] = "xxx";

#define EspSerial Serial1

#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

BlynkTimer timer;

int w;
float range;
long sample=0;
float val=0;
long count=0;
int reject=0;
int blinkTime = 500;
bool newWeight = false;


//reading data from HX711 module and return its output
unsigned long readCount(void)
{
  unsigned long Count;
  unsigned char i;
  pinMode(DT, OUTPUT);
  digitalWrite(DT,HIGH);
  digitalWrite(SCK,LOW);
  Count=0;
  pinMode(DT, INPUT);
  while(digitalRead(DT));
  for (i=0;i<24;i++)
  {
    digitalWrite(SCK,HIGH);
    Count=Count<<1;
    digitalWrite(SCK,LOW);
    if(digitalRead(DT)) 
    Count++;
  }
  digitalWrite(SCK,HIGH);
  Count=Count^0x800000;
  digitalWrite(SCK,LOW);
  return(Count);
}

//calibrate the load sensor with 100g load
void calibrate()
{
  lcd.clear();
  lcd.print("Calibrating...");
  lcd.setCursor(0,1);
  lcd.print("Please Wait...");
  for(int i=0;i<100;i++)
  {
    count=readCount();
    sample+=count;
  }
  sample/=100;
  lcd.clear();
  lcd.print("Put 100g & wait");
  count=0;
  while(count<1000)
  {
    count=readCount();
    count=sample-count;
  }
  lcd.clear();
  lcd.print("Please Wait....");
  delay(2000);
  for(int i=0;i<100;i++)
  {
    count=readCount();
    val+=sample-count;
  }
  val=val/100.0;
  val=val/100.0;        // put here your calibrating weight
  lcd.clear();
}


void setup()
{
  Serial.begin(9600);
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);
  pinMode(buzzer, OUTPUT);
  pinMode(led_red, OUTPUT);
  pinMode(led_green, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(sw, INPUT);
  lcd.begin(16, 2);
  lcd.print("    Weight ");
  lcd.setCursor(0,1);
  lcd.print(" Measurement ");
  delay(1000);
  lcd.clear();
  calibrate();
  
  //call selectType() function every second
  timer.setInterval(1000L, selectType); 
}

void sendSensor(){
  count= readCount();
  w=(((count-sample)/val)-2*((count-sample)/val));
  newWeight = true;
}

void selectType(){
  lcd.clear();
  lcd.print("Type:");
  char customKey = myKeypad.getKey();
  if(customKey!=NO_KEY){
   if(customKey=='1')
   {
    range=252; 
   }
   else if(customKey=='2')
   {
    range=319;
   }
    else if(customKey=='3')
    {
    range=272.5;
    }
    else if(customKey=='4')
    {
    range=310;
    }
    else if(customKey=='5')
    {
    range=285.5;
    }
    else if(customKey=='6')
    {
    range=280;
    }
    else if(customKey=='7')
    {
    range=280; 
    }
    else if(customKey=='8')
    {
    range=344;
    }
    else if(customKey=='9')
    {
    range=346;
    }
    else if(customKey=='0')
    {
    range=288.5;
    }
    else if(customKey=='A')
    {
    range=307.5;
    }
    else if(customKey=='B')
    {
    range=252;
    }
    else if(customKey=='C')
    {
    range=252;
    }
    else if(customKey=='D')
    {
    range=288;
    }
    else if(customKey=='*')
    {
    range=233;
    }
    else if(customKey=='#')
    {
    range=337;
    }
   }
   lcd.print(customKey);
   lcd.setCursor(10,0);
   lcd.print(range);
   lcd.setCursor(0,1);
   if(newWeight){
    lcd.print(w);
    newWeight = false;
   }
   
   //recalibrate the system and reset all value to 0  
  if(digitalRead(sw)==1)
  {
    val=0;
    sample=0;
    w=0;
    count=0;
    reject=0;
    calibrate();
    range=0;
  }
  //call the sendSensor() function after 1second
  int callFunction1 = timer.setTimeout(60000, detectWeight);
}


void detectWeight(){
  if(newWeight){
    delay(3000);
    Blynk.virtualWrite(V3,w); //write the weight to Virtual pin 3
  
  //check if the weight measured is more than 30g and out of the acceptable range 
  if((w > 30) && ((w < range*0.98)||(w> range*1.02))){
    lcd.clear();
    lcd.print("Weight");
    lcd.setCursor(8,0);
    lcd.print(w);
    lcd.setCursor(0,1);
    lcd.print("REJECTED!!");
    //saveWeight();
    blinkyBlinky(5, blinkTime);//trigger red LED
    blinkyBuzzer(5,300);//trigger buzzer
    noTone(buzzer);
    reject++;
    
  }
  //if weight measured is within acceptable range
  else if ((w>=range*0.98) && (w<=range*1.02)){
    digitalWrite(led_green, HIGH);
    delay(2000);
    reject=0;
    digitalWrite(led_green, LOW);
  }
   
    //if 10 consecutive objects measured are not within the range
    if(reject==10)
    {
      Blynk.notify("ESP8266 Alert - Insufficient Weight!");//send notification to phone
      Blynk.email("ESP8266 Alert", "Insufficient Weight!");//send alert email
      blinkyBuzzer(10,100);//trigger buzzer
      noTone(buzzer);
      reject=0;//reset the counter to 0
    }
    newWeight = false;
}
}

void loop()
{
  Blynk.run();
  timer.run();
  sendSensor();
}

//function to blink red LED for 5 times
void blinkyBlinky(int repeats, int t)
{
  for (int i = 0; i < repeats; i++)
  {
    digitalWrite(led_red, HIGH);
    delay(t);
    digitalWrite(led_red, LOW);
    delay(t);
  }
}

//function to trigger buzzer to buzz for 10 times
void blinkyBuzzer(int repeats, int t)
{
  for (int i = 0; i < repeats; i++)
  {
    tone(buzzer, 2000);
    delay(t);
    tone(buzzer, 1000);
    delay(t);
  }
}

Hi,
How have you got your project powered.
Have you got the input components to the controller away from the ESP-01 and its aerial.
Do you have bypass capacitors at the power input to the HX711 module.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom... :slight_smile:

Hi Tom, I powered it by supplying 5V adapter to the USB jack. For the ESP-01 I bought an adapter for it. And I do not have bypass capacitors at the power input to the HX711 module. Is it required? From what I see no capacitor is required for the HX711 load cell amplifier.

zack6912:
I referred to this website https://how2electronics.com/weighing-machine-arduino-load-cell-hx711/ for the code and tried to modify according to my needs. I tried out his code and the value of the load cell is quite consistent (-1 to 1) after calibration which is acceptable for me.

I tried out his code without the capacitor for the HX711 module and is working fine.
I attached a circuit diagram of my project below and the picture for the ESP-01 adapter.

Hi,
Thanks for the info.

However, when I uploaded my code to the device, the values flutter too much and is not consistent.

What were you running the code on before uploading it to the Mega?

Have you measured the 5V at the HX711?

Tom... :slight_smile:

TomGeorge:
What were you running the code on before uploading it to the Mega?

Have you measured the 5V at the HX711?

I am running the code on Mega. Sorry for confusing.
I measured the Vcc pins at the HX711 and it shows 5V.

Hi,
When were the readings stable?
I am confused?
What did you do when they became unstable?

Tom... :slight_smile:

The 8266 takes large current spikes when communicating and maybe causing spikes on the power supply .

I would power parts direct from 5v rather than via the Arduino 5v line, also something like 47uF across the 5v/0v line close to the 8266 would help.
Keep the load cell cables away from all the others

TomGeorge:
Hi,
When were the readings stable?
I am confused?
What did you do when they became unstable?

Tom... :slight_smile:

The readings is stable. I did not do anything when they are unstable. I am also confused why the values will flutter as I tried with the code provided by the website and it is working fine so I thought my modified coding has some errors.

hammy:
The 8266 takes large current spikes when communicating and maybe causing spikes on the power supply .

I would power parts direct from 5v rather than via the Arduino 5v line, also something like 47uF across the 5v/0v line close to the 8266 would help.
Keep the load cell cables away from all the others

Is that so? But I am using the adapter for the esp-01 and from what I saw online they are powering it using the 5V via the Arduino 5V line. I would prefer to have only one power supply for my project.
Maybe I will use a step down converter to step down my 12V 2A adapter to 5V and have the load cell connected to it directly and then supply it to the Vin pin of the Arduino separately?

The internal regulator in the Arduino can only supply a small amount of current and although you’ve seen it elsewhere it is not good practice and may well be the source of your problem - if that is how you’ve wired it .
It’s fine to have a 5v supply and power the Arduino and the other devices from that

I tried to supply the power to the load cell and esp-01 separately but the values still inconsistent and flutters from 0-2 sometimes to 4 after calibration. But better compared to have them powered together. What can I do to reduce the inconsistency? I would like to minimize the values to 0-1 if possible.

zack6912:
I tried to supply the power to the load cell and esp-01 separately but the values still inconsistent and flutters from 0-2 sometimes to 4 after calibration. But better compared to have them powered together. What can I do to reduce the inconsistency? I would like to minimize the values to 0-1 if possible.

  • From 0 to 2 sometimes 4, what mass does one digit represent?
  • What is the range of mass that your project is supposed to measure?

I find it hard to follow with all the Blynk stuff.

  • Do you have JUST code to read the mass?
  • If so does it flicker?
  • Are you averaging the readings, in particular using dynamic averaging?
  • Can you please post a picture of your project?

Thanks.. Tom... :slight_smile:

TomGeorge:

  • From 0 to 2 sometimes 4, what mass does one digit represent?
  • What is the range of mass that your project is supposed to measure?
  • The code I am using require user to place a 100g load to calibrate the system. The 0-2 I mean here is after I removed the 100g load after calibration and the system supposedly should have 0 gram.
  • The range of mass will be around 230-350g.

TomGeorge:
I find it hard to follow with all the Blynk stuff.

  • Do you have JUST code to read the mass?
  • If so does it flicker?
  • Are you averaging the readings, in particular using dynamic averaging?
  • Can you please post a picture of your project?
  • The code provided by the website (link in the first post) is meant to read the mass only.
  • I did mentioned in the first post the values are quite consistent (-1 to 1). But after I run it for a long period the value becomes inconsistent (-1g to 4g). I measured the Vcc of the HX711 and it shows a stable 5.1V.
  • Sorry I am not sure as I not really understand the code. I just modified it for my project.
  • I posted the circuit diagram of my project in the previous post. It basically just consists of load cell, esp8266, keypad and lcd.

Hi,
A picture of your project will let us see your component layout, a schematic doesn't.
I would say layout has lot to do with stability, as the voltage changes you are measuring at the load cell are very small.
What is the load rating of your loadcell?

If you are happy with 1 or 2 in 350= (2/350) x 100 = 0.57%

I would sat that is pretty good for a DIY set of scales.

If your power supply varied by 0.57% that would be 5V * 0.57/100 = 0.028V ???
This would not be readily measurable with a standard DMM.

What are you weighing and what tolerance do you need to measure them to?

Thanks.. Tom... :slight_smile:

I see. I am using a 5kg load cell. I am weighing helmets and my project is to detect whether the helmets measured is within the plus minus 2% range. If the measured helmet is below or above the range, then the system will indicate it as a rejected item. So I would like to have the initial values to as close to 0 as possible.
Here is the layout of my project:

Hi,
Thanks for the pic.
The DC-DC converter will be possibly radiating some RF, so keep the HX711 and load cell away from it.
In fact keep all the loadcell wires away from other electronic devices, any noise generated can get into the loadcell side of the HX711.

Tom... :slight_smile:

Hi Tom, thanks for the info. But I think it is not the problem here as I powered the system using the USB but the problem still occurs. Gladly I found a way to solve my problem. I used a HX711 library which can perform dynamic averaging (I think?). This library is quite useful and can save the trouble of calibrating using 100g load every time the system starts up. Just need to find the calibration factor before running the main program by placing a known weight.
Here is my code:

#define BLYNK_PRINT Serial

#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

#include "HX711.h"
#include <LiquidCrystal.h>
#include <Keypad.h>

#define sw 29         //input push button
#define buzzer 31     //output buzzer
#define led_red 30    //output led red
#define led_green 28  //output led green

LiquidCrystal lcd(7,6,5,4,3,2);
HX711 scale(A0, A1);

const byte numRows= 4;//Rows and columns of the keypad
const byte numCols= 4;
 
char keymap[numRows][numCols]=    //Keypad map
          {
          {'1', '2', '3', 'A'}, 
          {'4', '5', '6', 'B'}, 
          {'7', '8', '9', 'C'},
          {'*', '0', '#', 'D'}
          };

byte rowPins[numRows] = {35,37,39,41}; //Keypad 8 pins
byte colPins[numCols]= {43,45,47,49};

Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

//Authorization token, WiFi ID and password for Blynk
char auth[] = " ";
char ssid[] = " ";
char pass[] = " ";

#define EspSerial Serial1

#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

BlynkTimer timer;

float weight;
float range;
int reject=0;
int blinkTime = 500;
bool newWeight = false;
float calibration_factor= -370785;

void setup()
{
  Serial.begin(9600);
  scale.set_scale();
  scale.tare();
  long zero_factor = scale.read_average();
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);
  pinMode(buzzer, OUTPUT);
  pinMode(led_red, OUTPUT);
  pinMode(led_green, OUTPUT);
  pinMode(sw, INPUT);
  lcd.begin(16, 2);
  lcd.print("    Weight ");
  lcd.setCursor(0,1);
  lcd.print(" Measurement ");
  delay(1000);
  lcd.clear();
  
  //call selectType() function every second
  timer.setInterval(1000L, selectType); 
}

void sendSensor(){
  weight = scale.get_units(5);
  newWeight = true;
}

void selectType(){
  lcd.clear();
  lcd.print("Type:");
  //Get the type of helmets
  char customKey = myKeypad.getKey();
  if(customKey!=NO_KEY){
   if(customKey=='1')
   {
    range=0.252; 
   }
   else if(customKey=='2')
   {
    range=0.319;
   }
    else if(customKey=='3')
    {
    range=0.2725;
    }
    else if(customKey=='4')
    {
    range=0.310;
    }
    else if(customKey=='5')
    {
    range=0.2855;
    }
    else if(customKey=='6')
    {
    range=0.280;
    }
    else if(customKey=='7')
    {
    range=0.280; 
    }
    else if(customKey=='8')
    {
    range=0.344;
    }
    else if(customKey=='9')
    {
    range=0.346;
    }
    else if(customKey=='0')
    {
    range=0.2885;
    }
    else if(customKey=='A')
    {
    range=0.3075;
    }
    else if(customKey=='B')
    {
    range=0.252;
    }
    else if(customKey=='C')
    {
    range=0.252;
    }
    else if(customKey=='D')
    {
    range=0.288;
    }
    else if(customKey=='*')
    {
    range=0.233;
    }
    else if(customKey=='#')
    {
    range=0.337;
    }
   }
   lcd.print(customKey);
   lcd.setCursor(10,0);
   lcd.print(range);
   lcd.setCursor(0,1);
   if(newWeight){
    lcd.print(weight);
    newWeight = false;
   }
   
   //recalibrate the system and reset all value to 0  
  if(digitalRead(sw)==1)
  {
    scale.set_scale();
    scale.tare();
    reject=0;
    range=0;
  }
  //call the sendSensor() function after 1second
  int callFunction1 = timer.setTimeout(60000, detectWeight);
}


void detectWeight(){
  if(newWeight){
    delay(3000);
    Blynk.virtualWrite(V3,weight); //write the weight to Virtual pin 3
  
  //check if the weight measured is more than 30g and out of the acceptable range 
  if((weight > 0.03) && ((weight < range*0.98)||(weight> range*1.02))){
    lcd.clear();
    lcd.print("Weight");
    lcd.setCursor(8,0);
    lcd.print(weight);
    lcd.setCursor(0,1);
    lcd.print("REJECTED!!");
    //saveWeight();
    blinkyBlinky(5, blinkTime);//trigger red LED
    blinkyBuzzer(5,300);//trigger buzzer
    noTone(buzzer);
    reject++;
    
  }
  //if weight measured is within acceptable range
  else if ((weight>=range*0.98) && (weight<=range*1.02)){
    digitalWrite(led_green, HIGH);
    delay(2000);
    reject=0;
    digitalWrite(led_green, LOW);
  }
   
    //if 10 consecutive helmets measured are not within the range
    if(reject==10)
    {
      Blynk.notify("ESP8266 Alert - Insufficient Weight!");//send notification to phone
      Blynk.email("wewewe6969@outlook.com", "ESP8266 Alert", "Insufficient Weight!");//send alert email
      blinkyBuzzer(10,100);//trigger buzzer
      noTone(buzzer);
      reject=0;//reset the counter to 0
    }
    newWeight = false;
}
}

void loop()
{
  Blynk.run();
  timer.run();
  scale.set_scale(calibration_factor);
  sendSensor();
}

//function to blink red LED for 5 times
void blinkyBlinky(int repeats, int t)
{
  for (int i = 0; i < repeats; i++)
  {
    digitalWrite(led_red, HIGH);
    delay(t);
    digitalWrite(led_red, LOW);
    delay(t);
  }
}

//function to trigger buzzer to buzz for 10 times
void blinkyBuzzer(int repeats, int t)
{
  for (int i = 0; i < repeats; i++)
  {
    tone(buzzer, 2000);
    delay(t);
    tone(buzzer, 1000);
    delay(t);
  }
}

This library is good but only shows the weight in kg. I would like to display the weight in g but I tried to print the weight by multiplying it by 1000 but it does not work that way. The lcd just displays random values. If anyone knows please show me how to display the weight in g.

Hi,
Yes I was about to suggest that library, it seems strange that the original programmer made it so hard for himself.

Tom... :slight_smile:

But come to think of it this library can only show up to 2 decimal points. So maybe the fluttering problem is still there just I cannot see it. I noticed sometimes the initial value will become -0.00g so I suspect that the value is still fluctuating. Does somebody knows how to display the weight in unit gram instead of kilogram? It would be better to see whether the root problem (which is the value fluttering) is solved or not.

I managed to display the weight in 3decimal places and looks like my doubts are spot on. The values are still fluctuating. Is there no other way to stabilize the value?