Problem with if ... else statement

Hi,

I need to make for a school project a scale to weigh ingredients for people with disabilities. Instead of a display with the corresponding number to the mass of an object, I work with 3 leds and a adjustable weight setting with a rotary knob and a display. The worker who helps the people that are disabled can set the desired weight, and then the disabled person can add or substract the amount according to 3 leds. This is needed because they can’t read or understand value…

I got all the hardware right (load cell, hx711 amp, i2c lcd, arduino nano,…), except there is a problem in the code with the 3 conditions for the leds to light up… I’m working with the if … else statement,
if the value measured by the scale is lower than the one on the display the green led should light up,
if the amount is equal the blue one should light up,
if the amount is greater the red one should light up.

I’ll share my code wich is an adaption of the example in the hx711 library:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <HX711_ADC.h>

HX711_ADC LoadCell(3, 2); // parameters: dt pin, sck pin

int pMin = 0;  //the lowest value that comes out of the potentiometer
int pMax = 1023; //the highest value that comes out of the potentiometer.

int x = 0;  //we will use this value to store the readings of the potentiometer




LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
  Serial.begin(9600);//Serial monitor can be used to check the values

  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(481.0); // calibration factor for load cell => strongly dependent on your individual setup

  lcd.begin(16, 2);
  lcd.backlight(); // turns on the backlight
}

void loop() {


  LoadCell.update(); // retrieves data from the load cell
  int i = LoadCell.getData(); // get output value

  x = analogRead(A0); //connect the potentiometer to the A0 pin of the Arduino
  Serial.print(x);  //prints the original reading
  Serial.print("\t");
  Serial.println(i);

  x = map(x, pMin, pMax, 0, 1000); //take the value of x, compared it to the scale of the potentiometer pMin to pMax, and translate that value to the scale of 0 to 100
  x = constrain(x, 0, 1000);
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Set weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(x); // print out the retrieved value to the second row

  if (i < x)
  {
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
  }
  else if (i == x)
  {
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
  }
  else
  {
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);

So, we know what you want the code to do. If only we knew what it actually did, we could explain why what it does is different from what you want, and how to fix your expectations (or the code).

 int i = LoadCell.getData(); // get output value

This returns a float. Why are you casting it to an int? If your units are kilograms, then it won't be very useful to only use whole kilograms.

Don't test for exact equality. Allow a range, maybe 10 grams each side of the target, to light the green LED.

I'm working with the if ... else statement,
if the value measured by the scale is lower than the one on the display the green led should light up,
if the amount is equal the blue one should light up,
if the amount is greater the red one should light up.

What is actually happening? What are your serial prints telling you?

Yes,

the led that stands for the equality doesn’t light up i’ve already tried it with

if (i < 10) and else if (i <= x-10 && i >=x+10) but that did not change anything…

If i come close to the desired weight the green and red led are flickering rapidly.

And yeah i should change it back to float.

You need better variable names.

  int i = LoadCell.getData(); // get output value

i? Why not something meaningful like actualWeight?

  x = analogRead(A0); //connect the potentiometer to the A0 pin of the Arduino

x? Why not something meaningful, like targetWeight?

Use Serial.begin() and Serial.print() to debug your program. That way, you can share the output, so we get some idea what the code is actually doing, not just your hand-waving.

So the first column is the targetweight and the second one is the measured weight.

When i achieve close to an equality because of the flickering leds…

I just LOVE pictures of text. NOT.

Why are you wasting time posting PICTURES of TEXT, when copying and pasting the damned text is orders of magnitude faster for everyone?

Google hysteresis.

Hey,

thanks for all the feedback on my code but this line actually solved the problem…

else if ((actualWeight >= (targetWeight-3)) && ((actualWeight <= (targetWeight+3))))

but this line actually solved the problem

Well, that's hysteresis, so of course it solved the problem.

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

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

Now you have it functioning can you share the results please.

Code and Schematic.

Tom… :slight_smile:

Hey, here is the code, there are still some things that need to be added… The schematic is going to be posted on instructables with the whole built of the scale.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <HX711_ADC.h>

HX711_ADC LoadCell(3, 2); // parameters: dt pin, sck pin

int pMin = 0;  //the lowest value that comes out of the potentiometer
int pMax = 1023; //the highest value that comes out of the potentiometer.

int targetWeight = 0;  //we will use this value to store the readings of the potentiometer

int tareButton = 9; // pushbutton for tare reset
int tareVal = LOW;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
  Serial.begin(9600);//Serial monitor can be used to check the values
 
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  pinMode(tareButton, INPUT);
  
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(481.0); // calibration factor for load cell => strongly dependent on your individual setup

  lcd.begin(16, 2);
  lcd.backlight(); // turns on the backlight
}

void loop() {


  LoadCell.update(); // retrieves data from the load cell
  float actualWeight = LoadCell.getData(); // get output value

  targetWeight = analogRead(A0); //connect the potentiometer to the A0 pin of the Arduino
  
  Serial.print(targetWeight);  //prints the original reading
  Serial.print("\t");
  Serial.println(actualWeight);

  targetWeight = map(targetWeight, pMin, pMax, 0, 1000); //take the value of x, compared it to the scale of the potentiometer pMin to pMax, and translate that value to the scale of 0 to 1000
  targetWeight = constrain(targetWeight, 0, 1000);
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Set weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(targetWeight); // print out the retrieved value to the second row

  if (actualWeight < targetWeight)
  {
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
  }
  else if ((actualWeight >= (targetWeight-3)) && ((actualWeight <= (targetWeight+3))))
  {
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
  }
  else
  {
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }
  

  tareVal = digitalRead(tareButton);
  if (tareVal == HIGH)
  { 
    LoadCell.tare();
    tareVal = LOW;   
  }
}

I am glad that you got it working

Some comments on the code as it is :

The code would be easier to read if you gave all of the pins names instead of using anonymous numbers. I assume that they are LEDs but it is not obvious from the code.

Why is tareButton an int and not const byte when its value will always be less than 255 and will never change ?

Some of the comments, such as this one

  targetWeight = analogRead(A0); //connect the potentiometer to the A0 pin of the Arduino

and this one

  targetWeight = map(targetWeight, pMin, pMax, 0, 1000); //take the value of x, compared it to the scale of the potentiometer pMin to pMax, and translate that value to the scale of 0 to 1000

do not match what the code does

When you Serial.print() targetWeight and actualWeight it would help debugging if you printed text labels for the values

How is the tare button wired ? Have you got a pulldown resistor on pin 9 ?

Yes indeed sorry for the comments, I’ve updated them.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <HX711_ADC.h>

HX711_ADC LoadCell(3, 2); // parameters: dt pin, sck pin

int pMin = 0;  //the lowest value that comes out of the potentiometer
int pMax = 1023; //the highest value that comes out of the potentiometer.

int targetWeight = 0;  //we will use this value to store the readings of the potentiometer

int tareButton = 9; // pushbutton for tare reset on digital pin 9 with 10k pullup resistor
int tareVal = LOW; // state of the tare button

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //initialization of lcd display

void setup() {
  Serial.begin(9600);//Serial monitor can be used to check the values
 
  pinMode(5, OUTPUT); // green led (led turns on when there must be weight added according to the reference weight)
  pinMode(6, OUTPUT); //  blue led (led turns on when the weight is equal to the reference weight)
  pinMode(7, OUTPUT); //   red led (led turns on when there must be weight substracted according to the reference weight)

  pinMode(tareButton, INPUT); // defining the tare button as an input
  
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(481.0); // calibration factor for load cell => strongly dependent on your individual setup

  lcd.begin(16, 2); // starts the lcd
  lcd.backlight(); // turns on the backlight
}

void loop() {


  LoadCell.update(); // retrieves data from the load cell
  float actualWeight = LoadCell.getData(); // get output value

  targetWeight = analogRead(A0); // reads the value of the potentiometer on pin A0 
  
  Serial.print("target weight (g):");
  Serial.print("\t");
  Serial.print(targetWeight); //prints the reference weight
  Serial.print("\t");
  Serial.print("actual weight (g):");
  Serial.print("\t");
  Serial.println(actualWeight); // prints the actual weight

  targetWeight = map(targetWeight, pMin, pMax, 0, 1000); //take the value of target weight, compared it to the scale of the potentiometer pMin to pMax, and translate that value to the scale of 0 to 1000 defined in grams
  targetWeight = constrain(targetWeight, 0, 1000);
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Set weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(targetWeight); // print out the retrieved value to the second row
  

  // if ... else is used to compare the actual and target weight and triggers the corresponding led for each state
  
  if (actualWeight < targetWeight)
  {
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
  }
  else if ((actualWeight >= (targetWeight-3)) && ((actualWeight <= (targetWeight+3))))
  {
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
  }
  else
  {
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }
  
  tareVal = digitalRead(tareButton); // tare button triggers reset of the loadcell
  if (tareVal == HIGH)
  { 
    LoadCell.tare();
    tareVal = LOW;   
  }
}

I still have to add led strips instead of simple leds and this will be changed in the code eventually and i’m experiencing extreme lag on my 16x2 lcd display. I’m also thinking about changing the potentio to a rotary encoder to make it more precise and in increments of 10 grams or so

    tareVal = LOW;

It's rather silly to set this to LOW when, next iteration of loop(), you are going to overwrite it before you care what is in the variable.

i'm experiencing extreme lag on my 16x2 lcd display

There's nothing obvious in the code which would explain this.

If you're using this library here: https://github.com/olkal/HX711_ADC then that doesn't seem to have any obvious performance problems.

You are printing to Serial on every loop and that will be the major bottleneck. It will fill up the Serial buffer and slow down to the rate that the Serial characters are actually being sent. However for this program, this should not be a big deal - you should still be getting more than 5 updates per second.

Perhaps the LCD is slow in itself? If you've set the contrast incorrectly then the LCD can be very slow changing the crystals in the display.

I'd start investigating this by recording the micros() at the start and end of each major operation, the printing that to Serial. Then you will see if the load cell code is slow or something else is doing it.

i'm experiencing extreme lag on my 16x2 lcd display

lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Set weight[g]:"); // print out to LCD

Write the unchanging information only once in setup(). While this is good practice, it is probably not causing "extreme lag".

Set Serial.begin(115200) for faster serial printout.

Hi,

Thanks to everyone for all the help i'm getting. I've noticed the lag has something to do with the tare function at the end of the void loop perhaps...

I'm going to try to comment everything from the serial commands to check if this has something to do with it.

tareVal = digitalRead(tareButton); // tare button triggers reset of the loadcell
  if (tareVal == HIGH)
  { 
    LoadCell.tare();
    tareVal = LOW;   
  }

Also anyone got any tips on debouncing digitally a rotary encoder? And I've got like from the beginning onwards always strange stuff happening with the lay out of the numbers on the lcd (not being on the right character) sometimes a hard reset solved the problem...

Okay the serial monitoring was the main cause of the lag...
the only problem left is when incrementing over 3 digits for example 100 grams and you return back to a two digit number it stays a 3 digit number which skips a character and shows a zero for the last digit...

Okay the serial monitoring was the main cause of the lag...
the only problem left is when incrementing over 3 digits for example 100 grams and you return back to a two digit number it stays a 3 digit number which skips a character and shows a zero for the last digit...

It's very simple to clear the three spaces before writing.

lcd.setCursor(0, 1); // set cursor to second row
lcd.print("   "); //clear three spaces
lcd.setCursor(0, 1); //reset cursor
lcd.print(targetWeight); // print out the retrieved value to the second row