Analog Bar Graph on Character LCD - howto

I wanted to display vertical bar graphs on a 2 line LCD display. I hope the following code fragments will help and inspire others.

I'm using a Boarduino, Ardunio 0011 Alpha, the stock LCD4bit library and a 2x16 display from the UK's Maplin Electronics (N27AZ – DEM16217).

I used the "user defined characters" to define eight new characters: one with one full row of dots at the bottom, one with two rows, one with three etc, up to all eight rows. Doing this looks a bit scary reading the display data sheet but the Everyday Practical Electronics PDF articles online at Web Hosting, Reseller Hosting & Domain Names from Heart Internet are very helpful.

Basically you do an lcd.commandWrite (0x40) to set the display to accept writes to the character generator RAM instead of the screen, and then send the character definitions, eight bytes at a time. The first one is character 0, then 1, etc. Afterwards you use an lcd.clear to get back to normal operations.

The characters get defined in the setup () procedure. I worked out that I didn't need to spell out all the characters and used two nested for loops:

lcd.init ();
lcd.commandWrite (0x40); //define bar code chars
for (int i=0; i<8; i++)
{
for (int j=0; j<8; j++)
{
if (i+j>6)
{
lcd.print (0x1F);
}
else
{
lcd.print (0x00);
}
}
}
lcd.clear ();
[/color]
That's not the most easily understood code in the world but if you work through you'll find it defines exactly the right characters in character slots 0 to 7.

0:
........
........
........
........
........
........
........
XXXXXXXX

1:
........
........
........
........
........
........
XXXXXXXX
XXXXXXXX

etc.

None of the these characters is blank – that character already exists (“space”) at 0x20.

In my case I wanted eight dynamic bar graphs in the left hand columns. These get written in two phases – the first row for the top of the bars and the second row for the bottoms. Clearly if the bar does not extend into the top row then the space character is used. I always wanted a baseline on the bottom row so this never really shows “zero”.

The code for loop () looks like this. Array c[8] contains the values, scaled to the range 0-15.

lcd.cursorTo(1, 0); //top row
for (int k=0; k<8; k++)
{
if (c[k] < 8)
{
lcd.print (0x20);//space if bar does not reach top row
}
else
{
lcd.print (c[k]-8);
};
};
lcd.cursorTo(2, 0);//bottom row
for (int k=0; k<8; k++)
{
if (c[k] < 8)
{
lcd.print (c[k]);
}
else
{
lcd.print (7); //full block if bar extends to top row
};
};

I've taken this out of my code which had various scaling factors in it. I'll try to post a full working sketch shortly. I may have worked out how to quote code fragments by then!

Enjoy!

Bargraph für Text-LCD - Mikrocontroller.net ------ in German :slight_smile: :slight_smile:

Here's a different method that I made. This uses sketch was written for a 16x2 LCD display, it shows the input number (in this case, an analog pin) in the top row with a caption, and uses blocks to form a horizontal graph across the bottom row.

It works great for sensors, but can easily be modified for a progress bar.

I tried to make it as simple as I could, this way I can use it as a template and customize each view I use it for.

#include <LiquidCrystal.h>  // LiquidCrystal Library

int analogPin = 0; // The main input

float d = 0;
float oldit = 0;

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

void setup() {
  lcd.begin(16, 2); 
  lcd.setCursor(8, 0); // show what pin we're using for input
  lcd.println("Analog "); // delete this and use whatever you want
  lcd.setCursor(15, 0); // for the top row caption
  lcd.print(analogPin);
}

void loop() {
  float num = analogRead(analogPin); // get our input
  float it = map(num, 0, 1023, 0, 16);  // take our input and break it down to 16
  lcd.setCursor(0, 0); // print the actual number we're using.
  lcd.print(num);

  if (it > oldit) { // check if the number changes to a higher number
    for (d = 0; it >= d; d++) { // count up from 0 to 15
      lcd.setCursor(d, 1); // start at the bottom left and work forward
      lcd.write(1023); // show a block
    }
  }

  if (it <= oldit) { // check if the number changed to a smaller number
    for (d = 15; it <= d; d--) { //count down from 15 to 0
      lcd.setCursor(d, 1); // start at the bottom right and work back
      lcd.write(1022); // show blank
    }
  }

  oldit = it;  
}

enjoy