Pages: [1] 2   Go Down
Author Topic: LCD bargraph not displaying correctly  (Read 1230 times)
0 Members and 1 Guest are viewing this topic.
Left Coast
Offline Offline
Newbie
*
Karma: 1
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I'm trying to use the code from this blog post:
http://www.electronicsblog.net/arduino-lcd-horizontal-progress-bar-using-custom-characters/

...with an I2C LCD, using the LiquidCrystal_I2C library.  I've updated the sketch to use the newer library, and have a 5K pot attached.  The vertical bars display incorrectly - compare the image on the blog to mine, attached here.

What is different about the Liquid Crystal I2C library vs. the original Liquid Crystal library, that would cause this?  And how do I fix it?

Jeff

Code:
//http://www.electronicsblog.net
//Arduino LCD horizontal progress bar using custom characters

//#include <LiquidCrystal.h>

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

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

#define length 16.0

double percent=100.0;
unsigned char b;
unsigned int peace;

// custom characters

// LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte p1[8] = {
  B0001,
  B0001,
  B0001,
  B0001,
  B0001,
  B0001,
  B0001,
  B0001};

byte p2[8] = {
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000};

byte p3[8] = {
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100};

byte p4[8] = {
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110};

byte p5[8] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111};

void setup()   {

  delay(100);
  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 loop()
{
  lcd.setCursor(0,0);

  //ADC conversion

  unsigned int value = analogRead(0);

  percent = value/1024.0*100.0;

  lcd.print(value);

  lcd.print(" - ");

  lcd.print(percent);
  lcd.print(" %   ");

  lcd.setCursor(0,1);

  double a=length/100*percent;

  // drawing black rectangles on LCD

  if (a>=1) {

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

    a=a-b;

  }

  peace=a*5;

  // drawing character's colums

  switch (peace) {

  case 0:

    break;

  case 1:
    lcd.print((char)0);
    break;

  case 2:
    lcd.write(1);
    break;

  case 3:
    lcd.write(2);
    break;

  case 4:
    lcd.write(3);
    break;

  }

  //clearing line
  for (int i =0;i<(length-b);i++) {
    lcd.print(" ");
  }
  ;
}


* LCD bars.png (105.69 KB, 408x230 - viewed 85 times.)
Logged

Offline Offline
Sr. Member
****
Karma: 12
Posts: 380
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is your LCD model number?
Logged

Do not IM me. I will not respond. Ask questions in the forum.

Left Coast
Offline Offline
Newbie
*
Karma: 1
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's version 1 on this page:
http://arduino-info.wikispaces.com/LCD-Blue-I2C
Logged

Western New York, USA
Offline Offline
Faraday Member
**
Karma: 32
Posts: 4243
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The model number of your LCD is irrelevant.

B0001 is not the same as 0x10.  Try B10000.


Don
Logged

Left Coast
Offline Offline
Newbie
*
Karma: 1
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Don - Thanks for catching that typo with the binary number; I had converted the original code from hex to binary to make it easier to visualize the images used in the custom characters.

However, fixing the typo has no effect on the missing lines in the bargraph display.

When I turn up the contrast on the display, and look closer, I can see that only every other line is being drawn.  It's the odd-numbered ones...lines 1,3,5, and 7.
« Last Edit: November 06, 2013, 02:33:51 pm by Jeff Haas » Logged

Offline Offline
Sr. Member
****
Karma: 12
Posts: 380
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It's the odd-numbered ones...lines 1,3,5, and 7.

Yeah, that's why I wanted the model number, so I could look at the datasheet.
Logged

Do not IM me. I will not respond. Ask questions in the forum.

Leicester UK
Offline Offline
Full Member
***
Karma: 4
Posts: 136
Half intelligent old fart.....
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Jeff,
                I've just tried that code and go the same result, but there again I only got my i2c LCD working yesterday, thank's to bparrybab's i2cLCDguesser sketch. The barograph looks quite smart, Can't see much wrong in your code, but again I'm only a learner at C, used picaxe and basic in the past. Here's a picture of my LCD and the result from Bill's guesser sketch!! same as your's....

Hi  arduinodlb,
                            I don't think it has much to do with the LCD itself, as most HD477.. based LCD's have the same pinout/function, but there are at least 2 or 3 versions of the small i2c expander backpack that fits on the back of the LCD. In fact I have another one winging it way from China right now, and it looks slightly different to the one I have now. There's a good chance that the LCD pins will be mapped to the chip differently??
I'll keep an eye on this one, best of luck.
Regards

Mel.

PS. Take a look here: http://arduino-info.wikispaces.com/LCD-Blue-I2C





* LCDmapping.JPG (235.55 KB, 1024x768 - viewed 63 times.)

* LCDbp-1.jpg (241.55 KB, 1024x768 - viewed 39 times.)
« Last Edit: November 06, 2013, 03:26:22 pm by Cactusface » Logged

Open your mind, but not too far, your brain might fall out!!

Also like model building, photography and keeping an eye on my 294? Cacti & Succs...

Take a look at http://melsaunders.x10.bz

Offline Offline
Sr. Member
****
Karma: 12
Posts: 380
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Cactus,

No, I'm not saying it has anything necessarily to do with the LCD model. But, the code in general looks fine, and it was obvious that it's missing rows in the User Generated Characters, so I needed a datasheet as a starting point to see how Character Generation works on these LCDs in order to start looking into what the problem is. I don't use LCDs myself, so I just wanted a datasheet as a starting point for looking into this problem.
Logged

Do not IM me. I will not respond. Ask questions in the forum.

Offline Offline
Sr. Member
****
Karma: 12
Posts: 380
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So, a couple of things:

1. Can you please provide a link to the exact library you are using?
I had a quick look at this one https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/LiquidCrystal_V1.2.1.zip, but I'm not sure that's the one you're actually using.

2. I know the demo does it this way

Code:
 lcd.createChar(0, p1);
  lcd.createChar(1, p2);
  lcd.createChar(2, p3);
  lcd.createChar(3, p4);
  lcd.createChar(4, p5);

  lcd.begin(16, 2);

but looking at the library above, it seems to me that  the begin() should come before the createChar() lines. That probably isn't your problem though.

Code:
 lcd.begin(16, 2);

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

In the library I looked at, here's the CreateChar function

Code:
void LCD::createChar(uint8_t location, uint8_t charmap[])
{
   location &= 0x7;            // we only have 8 locations 0-7
  
   command(LCD_SETCGRAMADDR | (location << 3));
   delayMicroseconds(30);
  
   for (int i=0; i<8; i++)
   {
      write(charmap[i]);      // call the virtual write method
      delayMicroseconds(40);
   }
}

It's possible that the  delayMicroseconds(40); is too short, thus skipping every second line. I would try increasing that to 100 to see if that has any effect.

That being said, as I say, I don't know what library you're using, and I don't have an LCD myself.
« Last Edit: November 06, 2013, 05:35:13 pm by arduinodlb » Logged

Do not IM me. I will not respond. Ask questions in the forum.

Left Coast
Offline Offline
Newbie
*
Karma: 1
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think I found it.  Seems to be a difference between the old LiquidCrystal and LiquidCrystal_I2C.

Original code from blog:

Code:
void setup()   {

  delay(100);
  lcd.createChar(0, p1);
  lcd.createChar(1, p2);
  lcd.createChar(2, p3);
  lcd.createChar(3, p4);
  lcd.createChar(4, p5);

  lcd.begin(16, 2);

}

I moved lcd.begin(16,2); up so it is executed before lcd.createChar set of commands, like so:

Code:
void setup()   {

  delay(100);
  lcd.begin(16, 2);      // moved to here, works with LiquidCrystal_I2C
  lcd.createChar(0, p1);
  lcd.createChar(1, p2);
  lcd.createChar(2, p3);
  lcd.createChar(3, p4);
  lcd.createChar(4, p5);

//   lcd.begin(16, 2);

}

Logged

Left Coast
Offline Offline
Newbie
*
Karma: 1
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And we cross-posted!  It seems to be the solution.

What I had found was that another sketch with custom characters was working, but this one didn't seem to have its own characters uploading...I was seeing characters from the other sketch.  Comparing the two solved it.
Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 62
Posts: 2635
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually,
That code with the begin() after the createChar() calls is wrong.

begin() must be the first thing that is done before attempting to use other LiquidCrystal library
API calls.
It is pure luck that it worked at all (actually it didn't) with the begin() after the createChar().

The reason that begin() must be first
is that the Arduino environment doesn't properly initialize itself before
the object constructors are called.
Because of that, the constructors cannot always talk to hardware to do all the h/w initialization
because things like interrupts are not properly set up.

To work around this, a begin() function was added to libraries.
The object constructors save away all the parameters and then
the begin() function is where the hardware is actually initialzed.
begin()  is called from setup() which called much later in the boot/startup process
and by that time all needed MCU and Arduino initializations have taken place.
If you attempt to talk to the device before you call begin() then
the results are un-predictable and are very likely to not work as desired.

While the LiquidCrystal library Tutorial and its references pages don't explicity
state that begin() must be called before any of the other LiquidCrystal methods,
if it isn't called first, the sketch will be attempting to use un initialized hardware.

The LiquidCrystal library should reject any attempts to talk to the LCD before proper initialization is done,
but as of today, this isn't done by libraries and that is why the results are unpredictable.

In the case of the LiquidCrystal i2c interface, attempting to talk to the LCD before
calling begin() will result in the lower level code trying to talk to the LCD
before the Wire library (i2c) is setup and before the PCF8574 chip is initialized.

The simple solution as you have seen is simple do the begin() first thing
as is required.

--- bill

Logged

Left Coast
Offline Offline
Newbie
*
Karma: 1
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bill,

Thanks for the detailed info.  The example LiquidCrystal Library - Custom Characters sketch that installed with the SDK shows:

Code:
void setup() {
  // create a new character
  lcd.createChar(0, heart);
  // create a new character
  lcd.createChar(1, smiley);
  // create a new character
  lcd.createChar(2, frownie);
  // create a new character
  lcd.createChar(3, armsDown); 
  // create a new character
  lcd.createChar(4, armsUp); 

  // set up the lcd's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the lcd.
  lcd.print("I ");
  lcd.write(0);
  lcd.print(" Arduino! ");
  lcd.write(1);

}

So you're saying this is incorrect?  Shouldn't it be updated?

Jeff

Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 62
Posts: 2635
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, it is wrong and should be updated.
I entered a bug report for it. Here is the bug report link:
https://github.com/arduino/Arduino/issues/1663

If you look at the LiquidCrystal library code, (LiquidCrystal.cpp)
the constructors call the function init()
init() saves away which pins are used and sets up some internal variables.
It does not initialize the LCD command/data interface or the LCD.

The begin() function intializes the LCD command/data interface
and initializes the LCD into a known state, as well as clearing the display.
The most important thing that is done during LCD initialization is to go
through a sequence to get the host (Arduino in this case)
in sync with the LCD with respect to the command/data interface.
This is very important when using 4 bit mode because if you are out of sync
then the LCD will end up seeing the command/data nibbles scrambled and then nothing
will work correctly.

I'll go look through the other LiquidCrystal examples to see if there are
any other similar errors.

--- bill
« Last Edit: November 07, 2013, 11:52:51 am by bperrybap » Logged

Leicester UK
Offline Offline
Full Member
***
Karma: 4
Posts: 136
Half intelligent old fart.....
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Bill, Jeff and others,
                                         Just looked at your comments, then all I had to do was to move the a begin() to the start of the void setup loop and it now works fine....    Another problem solved by those who know!!

Here's a picture...

Thanks again,
Regards
Mel.




* LcdBar.jpg (241.33 KB, 1024x768 - viewed 42 times.)
Logged

Open your mind, but not too far, your brain might fall out!!

Also like model building, photography and keeping an eye on my 294? Cacti & Succs...

Take a look at http://melsaunders.x10.bz

Pages: [1] 2   Go Up
Jump to: