LCD ProgressBar (visible numbers instead of squares)

Hi

My project is to create a Water level for two tanks. For now, I’m making the test with
one sensor and the second sensor is not part of my problem.

One bug at the time :slight_smile: so lets look at my problem for one water tank.

I’m using ultrasonic sensor (Waterproof sensor JSN SR04T) Work nice.

I want one LCD 16X2 oriented vertical that will represent the water level in the tank with a
progress bar.

A second LCD but a 16X4, that will be use to tell me the mesured lengh by the sensor,
the percent of water in the tank and later the gallons per minute during the filling.

Problem One

I found a code for the progress Bar and it work well BUT the last square is my probleme.
While the mesured distance is changing slowly I can see a square then the number 3 appear
and decrease for 2, 1, 0 and then nothing. then it is the next square that change for 3, 2, 1, 0 etc…

See the picture attached.

It’s probably because there is 4 column in each square and those number 3 to 0 represent each column
and instead of removing one column at the time, the numbers are visible. I have two choices, making the number invisible until a full square disapear for the next, or find a way to make the column disapear one at the time until a full square is done.

Problem Two

I need to set a lower and a higher limit for the percent.

The day I will install that into my tank I want to be able to set the lower limit to 170cm and the top limit to 30cm. So 30cm will be 100% and 170 cm will be 0% of course the progress bar need to follow the percent value.

Any suggestion ?

Thanks

#include "Ultrasonic_1.h"
#include "Ultrasonic.h"
#include "Wire.h"
#include "LCD.h"
#include "LiquidCrystal_I2C.h"

Ultrasonic ultrasonic(2,3);
Ultrasonic_1 ultrasonic_1(4,5);
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7); 
LiquidCrystal_I2C lcd_1(0x26,2,1,0,4,5,6,7); 

#define lenght 16.0
double percent=100.0;
unsigned char b;
unsigned int peace;

byte p1[8] = {
  0x10,
  0x10,
  0x10,
  0x10,
  0x10,
  0x10,
  0x10,
  0x10};

byte p2[8] = {
  0x18,
  0x18,
  0x18,
  0x18,
  0x18,
  0x18,
  0x18,
  0x18};

byte p3[8] = {
  0x1C,
  0x1C,
  0x1C,
  0x1C,
  0x1C,
  0x1C,
  0x1C,
  0x1C};

byte p4[8] = {
  0x1E,
  0x1E,
  0x1E,
  0x1E,
  0x1E,
  0x1E,
  0x1E,
  0x1E};

byte p5[8] = {
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F};

void setup() {

   Serial.begin(9600),
   
   lcd.begin (16, 2); // 16 x 2 LCD module
   lcd.setBacklightPin(3,POSITIVE);

   lcd_1.begin (16,4); // 16 x 4 LCD module
   lcd_1.setBacklightPin(3,POSITIVE);
   lcd_1.setBacklight(HIGH);  

   lcd.createChar(0, p1);
   lcd.createChar(1, p2);
   lcd.createChar(2, p3);
   lcd.createChar(3, p4);
   lcd.createChar(4, p5);
   lcd.begin(16, 2);
}

void Sensor_0(){

  lcd.setCursor(0, 0);
  unsigned int value = ultrasonic.Ranging(CM);
  percent = value*100.0/200.0;

  lcd_1.setCursor(0, 0);
  lcd_1.print(value);
  lcd_1.print(" - ");
  lcd_1.print(percent);
  lcd_1.print(" %   ");

  double a=lenght/100*percent;

  if (a>=1) {
    for (int i=1;i<a;i++) {
    lcd.write(4);
    b=i;
    }
    a=a-b;
  }
  
  peace=a*5;
  switch (peace) {
  case 0:
    break;
  case 1:
    lcd.print(0);
    break;
  case 2:
    lcd.print(1);
    break;
  case 3:
    lcd.print(2);
    break;
  case 4:
    lcd.print(3);
    break;
  }

//clearing line
  for (int i =0;i<(lenght-b);i++) {
  lcd.print(" ");
  }
  ;
  Serial.print("Sensor_0:    ");
  Serial.println(ultrasonic.Ranging(CM));
}

void Sensor_1(){

  lcd.setCursor(0, 1);
  lcd.print(ultrasonic_1.Ranging(CM));
  lcd.setCursor(4, 1);
  lcd.print("cm");

  Serial.print("Sensor_1:    ");
  Serial.println(ultrasonic_1.Ranging(CM));
  Serial.println("    "); 
}

void loop(){

  Sensor_0();
  
  //Sensor_1();

  delay(500);
}

IMG_0442.jpg

LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);
LiquidCrystal_I2C lcd_1(0x26,2,1,0,4,5,6,7);

Do you count that way? When you feel the need to number variables in a set, number ALL of them.

#define lenght 16.0
Sppeling deos os matr.

In this case, though, use better names. One device displays a progress bar, so name the instance progressBar.

void Sensor_0(){

What a dumb name for a function. There is NOT a clue as to what kind of sensor or what this function does.

    for (int i=1;i<a;i++) {
    lcd.write(4);
    b=i;
    }

At the end of this loop, won’t b have a fixed value (at least relative to a)?

    a=a-b;

And what will a now be?

Convoluted logic to achieve a simple result is NOT a good thing.

  peace=a*5;
  switch (peace) {
  case 0:
    break;
  case 1:
    lcd.print(0);
    break;
  case 2:
    lcd.print(1);
    break;
  case 3:
    lcd.print(2);
    break;
  case 4:
    lcd.print(3);
    break;
  }

Well, now we know where the 0, 1, 2, and 3 are coming from. Perhaps you meant to write() the special characters 0, 1, 2, and 3.

hddforensic,
print() and write() perform very different functions.

The documentation on the LiquidCrystal page for print() is not very clear:
https://www.arduino.cc/en/Reference/LiquidCrystalPrint
The documentation on the LiquidCrystal page for write() is better:
https://www.arduino.cc/en/Reference/LiquidCrystalWrite

Bottom line is

  • print() displays the characters for the number represented by the value
  • write() displays the character represented by the value

To display a custom character you need to use write() not print()

--- bill

Hi Bill,

When I found the code it was written with "write" but I got an error message
saying, call of overloaded 'write(int)' is ambiguous

I check for that error message on Google and someone suggest to replace "write"
for "print" and it work for the error message.

I will look further to fix that error message and keeping "write" instead of "print".

Thanks,

I will look further to fix that error message and keeping “write” instead of “print”.

Post the exact, complete error message. A simple cast may be all that is needed:

   lcd.write((byte)1);

hddforensic:
Hi Bill,

When I found the code it was written with "write" but I got an error message
saying, call of overloaded 'write(int)' is ambiguous

Yes, I thought you might run into that issue.

I should have mentioned that the way the Arduino boys created the Print class there is an issue when you use

write(0);

(They have been asked to fix this but have so far have refused)

zero is special in C/C++ due to some historical reasons. zero is an int and because of this, the compiler wants to use a function that accepts an int. There is no write() function in the Print class that accepts an int.
As a result, you get this error.

The solution is to cast the argument like this.

lcd.write((uint8_t) 0);

That will tell the compiler to treat the 0 as a uint8_t and then it can find the appropriate function.
This is only an issue for zero not other values.

Also, if you use a variable of uint8_t and assign it zero, it isn't an issue.

i.e.

uint8_t val;

    val = 0;
    lcd.write(val);

The arduino boys could fix this issue in their code, why they have refused to fix this over the years makes no sense to me.
They have spent more time and effort explaining and documenting how to work around the issue rather than just adding 1 line of code to their Print class to fix it once and for all.
There is a mention of this on the LiquidCrystal library createChar page:
https://www.arduino.cc/en/Reference/LiquidCrystalCreateChar

I am so sick of this issue that I have added a work around my hd44780 library and the next release, which should be available in a few days, will not have this issue.
So with the next release of my hd44780 library you will be able to use

lcd.write(0);

with no issue.

--- bill

Hi

Yes Bill,

A few minutes ago I found what PaulS is suggesting
and I changed lcd.write(0); for lcd.write(byte(0));
and it worked.

I only had to change the first line an it's ok now.

Alternatively, you could use 8 instead of 0
This is because the hd44780 chip has 8 custom character but uses the lower 16 character codes.
Because of this, 0-7 is the same as 8-15
i.e. 8 is the same as 0, 9 is the same as 1 etc...

From a larger perspective you could really simplify your code if you made your p{n} variables use the corresponding custom character code.
That way you wouldn't have to remap the values to use them.
But even if you do want to re-map them, since they are always 1 higher you could just do a simple -1 to get to the code point from your peace value.

--- bill

Hi Bill,

I'm not experienced enough to modify a code that much.
I only started with Arduino and coding a few months ago.

Right now I find a code that does what I want (or almost)
and then I try to modify it for my needs.

The code I have now. The percent and the progress bar
are increasing with the distance between the sensor and
the object.

Since my project is to show the level of water in a tank,
bigger the distance mean lower the water so I need to
reverse the value so the percent and progress bar will
decrease while the distance increase.

I started that project two days ago so I'm still looking.

I started that project two days ago so I'm still looking.

What are you looking for? If a glass is half full, it's also half empty. If it's 3/4 full, it's 1/4 empty. There's a clue in the fact that the percentages add up to 100.

Hi PaulS,

I understand what you mean but I don’t know how to apply it.

I understand what you mean but I don't know how to apply it.

Really?

percentFull = 28;
percentEmpty = 100 - percentFull;

Should have paid attention in math class.

That's your reply... Paid attention to Math class ?
That kind of answer goes with the one you gave me earlier today when you said
"What a dumb name for a function"

Hey I'm 55 years old and when I finished school, computers where so basic
that they didn't interest me. At that time electronics was between lamps and
transistor.

Math class are very far for me but I remember something about my education
from that old time... That something is

When someone is asking for help, I give him help not sarcasm.

Now please, don't answer me that way anymore.

Anyway the original topic is solved since I fix the numbers at the end of the
progress bar.

Thanks for the help.

Hey I'm 55 years old and when I finished school, computers where so basic
that they didn't interest me.

You are 6 years younger than me. When I finished school computers were so fascinating that programming them is all I've wanted to do, or done, since then.