Controlling relay using load cell and display on lcd module 16 x 2

Hi there,

So right now i need to do a project that can control a relay using load cell and display all of the information on the lcd module 16 x 2.

I’ve done the coding for calibrating load cell and display but i’m having trouble to write a coding that can trigger the relay by reading a certain value from the load cell and display all the information on the lcd module.

So theorically, i want the relay to trigger by 3 value read by the load cell.

First trigger ; Relay will low if the weight is below 100 gram

Second ; relay will high for 15 second if the weight is more than 100 gram but below than 500 gram

Third ; relay will high for 30 second if the weight is more than 500 gram

Lastly all of the information displayed on the lcd module.

Thanks.

lcd_load_cell_code.ino (1.21 KB)

Does the sketch need to do anything other than read the cell every so often and control the relay?

If not, you could use delay() after doing the read, something like this (untested) snippet:

if (mass > 100 && mass < 500)
{
digitalWrite(relay, HIGH);
delay(15000);
digitalWrite(relay, LOW);
}

As you have it specified, btw, you left out the cases where the mass is exactly 100 or 500 :wink:

Question for you though: how often do you need to perform LoadCell.Update() and .getData().

Especially, can that overlap with the relay already being high from the previous read, and if so, if say the new read is under 100, does the relay stay high as already set by the previous read , or get made low due to the new read?

hi, thanks for the reply but when i uploaded the code it says 'mass was not declared in this scope'

the operation i wanted are;

1: relay low when load is below 100 gram

2: relay high 15 seconds when load is above 100 gram but below 500 gram

3: relay high 30 seconds when load is above 500 gram but below 900 gram

thanks again.

kira1996:
when i uploaded the code it says 'mass was not declared in this scope'

I hadn't opened your code when I called the mass, "mass"; I think that's what you called "i". And "relay" is of course whatever pin your relay is on.

if the read is under 100 relay will low.

i don't know actually how often but i want is when something is put on the scale it will trigger/not trigger the relay based on the reading

Try the following sketch: (your one slightly modified)

#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library

HX711_ADC LoadCell(4, 5); // parameters: dt pin, sck pin<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 is the i2c address of the LCM1602 IIC v1 module (might differ)

int Relay = 9;
int val;

void setup()
{
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(968.303); // calibration factor for load cell => strongly dependent on your individual setup
  lcd.init();//begin(); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
  pinMode(13, OUTPUT);
  pinMode(Relay, OUTPUT);   // it was missing in your sketch
}
void loop()
{
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value ; 
  int wt = (int)i;
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(i); // print out the retrieved value to the second row
  //---------------------------------------
  if (wt < 100)
  {
    digitalWrite(Relay, HIGH);
  }

  if (wt > 100 && wt < 500)
  {
    digitalWrite(Relay, HIGH);
    delay(15000);
    digitalWrite(Relay, LOW);
  }

  if (wt > 500)
  {
    digitalWrite(Relay, HIGH);
    delay(30000);
    digitalWrite(Relay, LOW);
  }
}

GolamMostafa posted basically what I was getting at.

kira1996:
i don't know actually how often but i want is when something is put on the scale it will trigger/not trigger the relay based on the reading

Ok now this is a new requirement, but it makes perfect practical sense. That means you need to continually read the scale, and note that it's at 0. Then if it's non-0 whereas it was 0 the last time you checked, that means there's a new load on it, and then you need to start the clock so to speak. This will need a millis() approach.

And you didn't answer this:

Especially, can [the new reading] overlap with the relay already being high from the previous read, and if so, if say the new read is under 100, does the relay stay high as already set by the previous read , or get made low due to the new read?

Does it need to sort of "lock out" a new read (or at least not do anything to the relay) if the relay is busy from the last one?

now i understand what lindsay trying to say when i try the golam code.

when the load reading is above 100 it did high the relay but the load reading didn't reset after 15 seconds instead the relay high all the time.

the first operation is excellent because if the reading is below 100 relay stay low

so i think the golam code needed to be edit a bit so that it will reset the load reading after 15 seconds.

thank you

Hers is an uncompiled sketch (I don’t have the library installed) which (hopefully) does the whole thing with no delay.

#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library

HX711_ADC LoadCell(4, 5); // parameters: dt pin, sck pin<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 is the i2c address of the LCM1602 IIC v1 module (might differ)

int Relay = 9;
int val;

void setup() {
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(968.303); // calibration factor for load cell => strongly dependent on your individual setup
  lcd.begin(); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
  pinMode(13, OUTPUT);
}

bool scaleIsEmpty = false;
int timeShort = 15000;
int timeLong = 30000;
int stayOnFor;
unsigned long newLoadAppliedAt;
bool relayIsOn = false;

void loop()
{
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(i); // print out the retrieved value to the second row

  if (i == 0 && !relayIsOn) scaleIsEmpty = true;
  // that means if the load is removed while the relay is on, the relay will finish its previous business

  if (i != 0 and scaleIsEmpty) //means there's a new load
  {
    scaleIsEmpty = false; //'cos it's not anymore
    if (i < 100)
    {
      digitalWrite(Relay, LOW); //off
    }
    else
    {
      digitalWrite(Relay, HIGH); //on
      relayIsOn = true;
      newLoadAppliedAt = millis();
    }

    if (i > 100 && i < 500)
    {
      stayOnFor = timeShort;
    }

    if (i > 500)
    {
      stayOnFor = timeLong;
    }
  }//new load

  if (relayIsOn && millis() - newLoadAppliedAt >= stayOnFor) //see if it's time to turn off
  {
    relayIsOn = false;
    digitalWrite(Relay, LOW); //off
  }
}//loop

Try that for size.

i try lindsay code but unfortunately the relay somehow didn't trigger. maybe there's something missing in your code idk.

if (i == 0 && !relayIsOn) scaleIsEmpty = true;

i is typed as a float. Is it ever == 0?

Try

if (i < 1 && !relayIsOn) scaleIsEmpty = true;

kira1996:
so i think the golam code needed to be edit a bit so that it will reset the load reading after 15 seconds.

Try the following sketch where the the weight is being updated while there is waiting:

#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library

HX711_ADC LoadCell(4, 5); // parameters: dt pin, sck pin<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 is the i2c address of the LCM1602 IIC v1 module (might differ)
int wt;
int Relay = 9;
int val;
unsigned long prMillis;

void setup()
{
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(968.303); // calibration factor for load cell => strongly dependent on your individual setup
  lcd.init();//begin(); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
  pinMode(13, OUTPUT);
  pinMode(Relay, OUTPUT);   // it was missing in your sketch
}

void loop()
{
  updateWtandDisplay();
  //---------------------------------------
  if (wt < 100)
  {
    digitalWrite(Relay, HIGH);
  }

  if (wt > 100 && wt < 500)
  {
    digitalWrite(Relay, HIGH);
    prMillis = millis();
    while (millis() - prMillis<15000ul)
    {
      updateWtandDisplay();
    }
    digitalWrite(Relay, LOW);
  }

  if (wt > 500)
  {
    digitalWrite(Relay, HIGH);
    prMillis = millis();
    while (millis() - prMillis<30000ul)
    {
      updateWtandDisplay();
    }
    digitalWrite(Relay, LOW);
  }
  delay(1000);    //sampling interval
}

void updateWtandDisplay()
{
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value
  wt = (int)i;
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(wt); // print out the retrieved value to the second row
}

kira1996:
i try lindsay code but unfortunately the relay somehow didn't trigger. maybe there's something missing in your code idk.

Very possible, since I have no means to even compile it, let alone test.

I'm bowing out: two responders with different approaches is just going to confuse things. So I will leave you with GolamMostafa.

Do you want to achieve the following objective?

The relay becomes ON when the weight is greater than 100 and less than 500; as a result, a 15 sec time delay timer will be invoked; however, the relay will turn OFF if one of the following two conditions is met:

1. If the weight goes out of stated boundary values before the delay time has not yet exhausted.

2. The weight is within the stated boundary values; but, the delay time has expired.

Note: The LCD will keep showing the updated weight all the time at say 1 sec interval.

yes.

so the latest code that golam give worked but it mess with the reading on the lcd display. it did not show the exact weight.

This is the tentative solution to your problem in the form of Flow Chart which indicates that the coding is no so trivial or simple. Try to code it slowly, test it and report the progress/problems.

Coding of the above Flow Chart: (tested to some extent)

#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library

HX711_ADC LoadCell(4, 5); //
LiquidCrystal_I2C lcd(0x27, 16, 2); //
int wt;
int Relay = 9;
int val;
unsigned long prMillis;

void setup()
{
  Serial.begin(9600);
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(968.303); // calibration factor for load cell => strongly dependent on your individual setup
  lcd.init();//begin(); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
  pinMode(Relay, OUTPUT);
  // pinMode(Relay, OUTPUT);   // it was missing in your sketch
}

void loop()
{
  wt = wtDisplay();
  Serial.print(wt); //185
  //---------------------------------------
  if (wt > 100)
  {
    if (wt < 500)
    {
      processControl(15000, 15);
    }
    else
    {
      if (wt > 500)
      {
        processControl(30000, 30);
      }
    }
  }
  digitalWrite(Relay, LOW);
  delay(1000);
  //while (1);
}


int wtDisplay()
{
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value
  wt = (int)i;
  //wt = 615;//185;
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(wt); // print out the retrieved value to the second row
  //  wt = 90;
 //wt = analogRead(A0);
  return wt;
}

void processControl(unsigned long x, int value)
{
  while (1)
  {
    digitalWrite(Relay, HIGH);
    prMillis = millis();
    while (millis() - prMillis < x)
    {
      wt = wtDisplay();
      if (value == 15)
      {
        if (!(wt > 100 && wt < 500))
        {
          break;
        }
      }
      else
      {
        if (value == 30)
        {
          if ((!wt > 500))
          {
            break;
          }
        }
      }
    }
    break;
  }
}

#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library

HX711_ADC LoadCell(4, 5); // parameters: dt pin, sck pin<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 is the i2c address of the LCM1602 IIC v1 module (might differ)

int Relay = 9;
int val;

void setup()
{
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(968.303); // calibration factor for load cell => strongly dependent on your individual setup
  lcd.begin(); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
  pinMode(9, OUTPUT);
  pinMode(Relay, OUTPUT);   // it was missing in your sketch
}
void loop()
{
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value ;
  int wt = (int)i;
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(i); // print out the retrieved value to the second row
  //---------------------------------------
  if (wt < 100)
  {
    digitalWrite(Relay, LOW);
  }

  if (wt > 100 && wt < 500)
  {
    digitalWrite(Relay, HIGH);
    delay(15000);
    digitalWrite(Relay, LOW);
  }

  if (wt > 500)
  {
    digitalWrite(Relay, HIGH);
    delay(30000);
    digitalWrite(Relay, LOW);
  }
}

i think this code worked but it just have one problem only which is the load did not reset after 15 seconds even there is no load on the scale.

kira1996:
i think this code worked but it just have one problem only which is the load did not reset after 15 seconds even there is no load on the scale.

If load changes and becomes <100 before the expiry of the 15 sec delay, the relay should be OFF or not? If you expect that the relay should be OFF, then the the sketch should be re-written as per Flow Chart that I have proposed in Post#16.

GolamMostafa:
If load changes and becomes <100 before the expiry of the 15 sec delay, the relay should be OFF or not? If you expect that the relay should be OFF, then the the sketch should be re-written as per Flow Chart that I have proposed in Post#16.

if the load changes <100 before the expiry of the 15 sec delay, the relay should stay on until the 15 seconds ends and the reading will reset to the first state.