Pages: 1 ... 7 8 [9] 10   Go Down
Author Topic: New LiquidCrystal library - LCD library  (Read 19737 times)
0 Members and 1 Guest are viewing this topic.
Málaga, Spain
Offline Offline
Edison Member
*
Karma: 37
Posts: 2172
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you look in the project's wiki you will see that the 2 wire SR version of the library is about 4,5 times faster than the stock parallel LiquidCrystal an almos 40 times faster than the I2C versio.
Logged

   

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2329
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So, a final change to:-

Code:
LiquidCrystal_I2C lcd(0x27, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE); // addr, EN, RW, RS, D4, D5, D6, D7, BacklightPin, POLARITY

Code:
 lcd.setBacklightPin(7, NEGATIVE);
  lcd.setBacklight(1);

And.....VOILA! Everything working as it should.
tack,
Cool. Yep on i2c, and the SR interfaces the constructor values are all output bit numbers.
Makes sense if you think about it.
Glad it worked. Your i2c board matches mjkdz i2c board that I have.

When using the newer constructors that specify the backlight pin/bit  and backlight polarity, there is no need for
the setBacklightPin(). The constructor sets up everything.
There really is no need to ever use setBacklightPin() if you use the full constructor that includes backlight information.
This is true for all the interfaces that support backlight control: 4bit, i2c, SR2W, SR3W
(SR does not support backlight control)

i.e for i2c, all you need is the constructor:
Code:
LiquidCrystal_I2C lcd(0x27, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE); // addr, EN, RW, RS, D4, D5, D6, D7, BacklightPin, POLARITY

By default, duiring the initialization in begin(), the backlight will be turned on if you
set up the constructor with backlight information.
After begin() you can use the backlight functions.
To turn on/off the backlight:
Code:
lcd.backlight(); // turn on backlight with full brightness
lcd.noBacklight(); // turn off backlight

If you wan to use the setBacklight() function which is for dimming, then use:
Code:
lcd.setBacklight(brightnessvalue);
lcd.setBacklight(BACKLIGHT_ON); // full on
lcd.setBacklight(BACKLIGHT_OFF); // full off
A brighnessvalue of 1 will be full on for devices that don't support dimming or when an Arduino pin
that does not support dimming is used.
The reason to use BACKLIGHT_ON vs 1 to turn on the backlight is that you want to write
your lcd code to be portable across other interfaces that support PWM dimming.
Using a value of 1 will create a very dim backlight when pwm dimming is supported,
whereas BACKLIGHT_ON will be full brightness on all devices/interfaces.

--- bill



« Last Edit: January 06, 2013, 07:21:57 pm by bperrybap » Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2329
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you look in the project's wiki you will see that the 2 wire SR version of the library is about 4,5 times faster than the stock parallel LiquidCrystal an almos 40 times faster than the I2C versio.
Just don't try to convince GrumpyMike.... smiley-wink

Tack,
GrumpyMike argued and argued that the display update rate to the LCD was in no
way impacted by the interface used to talk to it. He flatly didn't believe
our transfer numbers and update rates vs 4bit and i2c.
And then for costs, he said i2c was just as effective and the
same cost as using a shift register.
I showed him how you could build a HC595 based board for $1 USD QTY 1
ordering parts from tayda electronics (20 cent 595s and cheap strip boards) and to show me where I could
find 20 cent PCF8574s. He never replied....

To see the update rate, run the LCDiSpeed sketch I wrote.
It is included in the examples.
You will have to modify the i2c constructor for your i2c board.


--- bill
Logged

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 37
Posts: 2172
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I still have to fine tune the 4bit version of the library to use fastIOs. Just a few micro seconds gain to reach the limit of the LCD.

Quote
Just don't try to convince GrumpyMike...

Simple facts, numbers are normally fairly objective. You could argue as much as you like but those figures talk for them selfs.
« Last Edit: January 06, 2013, 07:32:59 pm by fm » Logged

   

UK
Offline Offline
God Member
*****
Karma: 17
Posts: 568
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

tack,
Cool. Yep on i2c, and the SR interfaces the constructor values are all output bit numbers.
Makes sense if you think about it.
Glad it worked. Your i2c board matches mjkdz i2c board that I have.

When using the newer constructors that specify the backlight pin/bit  and backlight polarity, there is no need for
the setBacklightPin(). The constructor sets up everything.
Yes, it does make perfect sense now. It was just frustrating trying to work it out. LOL.

As for the SR vs I2C issue, the cheapest I've managed to find 8674 SMD is about $0.65, wheras a 100 595N cost me $12.00 or $0.12 each. To me, in the UK, that works out about 40p cheaper per board. I also need fewer headers (for my flexible setting address, backlight via I2C/Pin(PWM) and Contrast via Trimmer/Pin(PWM). That all adds up to maybe more than halve the build cost against using 8574 for I2C.

If you look in the project's wiki you will see that the 2 wire SR version of the library is about 4,5 times faster than the stock parallel LiquidCrystal an almos 40 times faster than the I2C versio.
Wow, that's some difference. I actually expected it to be slower for some reason. No real basis for that though, other than I guess some intuition that a cheaper method using generic SR would be slower than a specific implementation like I2C, or a parallel interface using a lot more pins.

I'll definitely give that a try at some point as I have plenty of 595N's coming. I think I'll be off to design a new 2W SR based backpack. ;-)

I guess the only difference is with controlling multiple LCD's. With 2W SR would I need another 2 pins for a an LCD displaying different data?

How does the library handle daisy chained SR? Does it, or would it be possible, to support multiple LCD's by writing 16, 24, 32 bits across multiple SR to display the same or different data on each? I'm thinking of this from the way ShiftPWM works. If you actually have 2 SR connected, but specify only 1 then the data gets repeated on the second.

Maybe the SR constructor could include a NUM_SR data to effectively specify how many LCD's. I suppose you'd need some kind of reference to each one for lcd.write() etc, such as lcd1.write, lcd2.write like you would if declaring multiple constructors normally.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2329
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you look in the project's wiki you will see that the 2 wire SR version of the library is about 4,5 times faster than the stock parallel LiquidCrystal an almos 40 times faster than the I2C versio.
Wow, that's some difference. I actually expected it to be slower for some reason. No real basis for that though, other than I guess some intuition that a cheaper method using generic SR would be slower than a specific implementation like I2C, or a parallel interface using a lot more pins.
There are some things to consider as well. The default i2c clock 100 khz - That is according to the I2C spec.
And that is the clock rate that Arduino programs the i2c interface to clock at. That is pretty slow.
Some of the newer i2c chips support higher speed and can can clock up to 10mhz.
(I bet wiring and pullups/termination becomes much more critical at those speeds)
So there is some room there if you use a faster i2c chip and put in an Arduino hack to speed up the i2c bus.
(But that might interfere with other slower i2c devices if present).

On the parallel mode, it is a bit unfair in that the serial shift register code is using indirect port i/o
while not as fast as direct port i/o, it is MUCH faster than using the SLOW digitalWrite() functions
in the Arduino core code. Currently the 4bit code is not using the indirect port i/o functions. This would be
a small change to the code and would speed up the 4bit code quite a bit.

Quote

I'll definitely give that a try at some point as I have plenty of 595N's coming. I think I'll be off to design a new 2W SR based backpack. ;-)

I guess the only difference is with controlling multiple LCD's. With 2W SR would I need another 2 pins for a an LCD displaying different data?

How does the library handle daisy chained SR? Does it, or would it be possible, to support multiple LCD's by writing 16, 24, 32 bits across multiple SR to display the same or different data on each? I'm thinking of this from the way ShiftPWM works. If you actually have 2 SR connected, but specify only 1 then the data gets repeated on the second.

Maybe the SR constructor could include a NUM_SR data to effectively specify how many LCD's. I suppose you'd need some kind of reference to each one for lcd.write() etc, such as lcd1.write, lcd2.write like you would if declaring multiple constructors normally.

There are three different SR device layer interfaces.
SR - output bits and wiring is hard coded but supports 2 wire or 3 wire mode. Currently no backlight support.

SR2W - (I did this this one) output bits and wiring is hard coded for 2 wire mode (clock, data) but
supports backlight control and has ASCII wiring diagrams in the header file for using various shift registers
and a sample backlight control circuit. Because the output bits/pins are hard-coded and can take advantage of certain
optimizations, it is actually faster than the SR3W code.
As expected, less flexibility = faster. (byte xfer time of 76us for SR2W vs 102us for SR3W)

SR3W - runs with 3 wires (data, clock, latch) and allows configuring output bits to allow any wiring - supports backlight.

The obvious down side of SR modes vs i2c is the number of pins.
I2c adds no additional pins for additional devices whereas SR modes do.
For driving multiple LCDs with the the existing SR code, you can share data and latch pins but not clock pins.
So the total numbers of Arduino pins doesn't have to be replicated for each additional LCD.
It will be I+(N-1) pins. Where I is the initial number of pins (2 or 3) and N is the total number of displays.
So for 4 displays in 2 wire mode it would be 2+(4-1) or 5 pins.

--- bill
Logged

UK
Offline Offline
God Member
*****
Karma: 17
Posts: 568
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll certainly play with the SR modes as well.

Noted on the number of pins required for multiple LCD's via SR.

Could you not cascade by connecting Q7S of one into DS of the next, with Latch and Clock shared.  If you kept track of whih LCD was to be updated the could you not shift in the required number of bits, with unchanged LCD(s) having the SR bit set to state that would cause no change?

Would that not effectively allow you to daisy chain more and more displays for no extra pins? It might have a speed effect if you had many many displays, but how many would seriously affect update speed by causing so many bits to be shifted in?

I'm not conversant with the low level driving of the LCD's, but it just occurs to me that you might control LCD3, for example, by only changing bits 8-15. With bits 0-7 and 16-31 in a 'neutral' state then LCD's 1, 2 & 3 wouldn't be driven by their SR.

When we you want to drive one display you have to do a full write across all SR but the bits for the others are just set to cause no change?
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2329
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Many things are theoretically possible. The issue with cascading the shift registers is that the
low level library functions would somehow have to know about this.
The current model is that each lcd object is separate and the configuration data for
each lcd device is contained within its object.
None of the lcd objects know about each other.

The challenge is that you can't really change the other outputs (at least not the backlight output)
when updating any given lcds outputs.
So the code that handles the updating/writing to the SR would somehow have to have knowledge of all
the devices attached and a bit of knowledge of their current state.


The general method the LCD is controlled for writes (which is all that is happening here)
 is that the data and control lines are setup.
(d4-d7, RS, RW) and then EN is raised high and then EN is lowered.

The lcd ignores the signals while EN is low.


BTW, I mad a mistake on the sharing of pins above.
It should be
2 wire mode: data pins can be shared but not clock.
3 wire mode: data and clock pins can be shared but not latch.

Sharing pins is actually kind of cheating in that multiple devices are told the pins belong to them.
Since there is no multitasking you can get away with sharing some of the pins between devices.

--- bill
Logged

UK
Offline Offline
God Member
*****
Karma: 17
Posts: 568
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What If you has a software buffer, 8 bits for each LCD that held the last state it was set to.

In each constructor you have a total_lcds and this_lcd item so that each constructor know how many lcds (buffers 1 to x) there are and what it's own position is. When you write to this LCD, say lcd3, you update buffer 3 and just take the contents of all other buffers and do the full x bit shift out with the buffer data in the correct order, before latching for transfer to outputs.

I guess that there is a sequence of events that occurs, so all other LCD buffers would basically need to  obtain data that doesn't alter their respective LCD state, such as setting the RW line to read, or not setting Enable like, for example, while the sequence is carried out with buffer(x) data being shifted to the 'active' LCD.

I'm just think in general terms as a question as to whether the methodology sounds like something achievable.

Being able to get a 2 wire implementation, with daisy chained displays, that is faster than I2C with the same wiring benefits, would be quite an achievement.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2329
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Being able to get a 2 wire implementation, with daisy chained displays, that is faster than I2C with the same wiring benefits, would be quite an achievement.
But I2C can be much faster than 100kbit if you use faster i2c chips and bump the clock rate.

Another way to communicate for use on an output only device like an LCD backpack
would be to use the AVR USART's multi-processor mode. That way you only use 1 pin
and can address up to 256 slaves.

--- bill


Logged

Seattle
Offline Offline
Newbie
*
Karma: 0
Posts: 46
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using an MJKDZ board  I2C SPI LCD serial interface
http://www.ebay.com/itm/170926744803?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649
for a 20x4 display...

The following program works for me:

Program:
Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

                  //  addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);  // Set the LCD I2C address

// Creat a set of new characters
const uint8_t charBitmap[][8] = {
   { 0xc, 0x12, 0x12, 0xc, 0, 0, 0, 0 },
   { 0x6, 0x9, 0x9, 0x6, 0, 0, 0, 0 },
   { 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0, 0x0 },
   { 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0, 0x0 },
   { 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0x0 },
   { 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0x0 },
   { 0x0, 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0x0 },
   { 0x0, 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0x0 }
  
};

void setup()
{
   int charBitmapSize = (sizeof(charBitmap ) / sizeof (charBitmap[0]));

   lcd.begin(20,4);               // initialize the lcd

   for ( int i = 0; i < charBitmapSize; i++ )
   {
      lcd.createChar ( i, (uint8_t *)charBitmap[i] );
   }

  lcd.home ();                   // go home
  lcd.print("Hello, ARDUINO ");  
  lcd.setCursor ( 0, 1 );        // go to the next line
  lcd.print (" FORUM - fm   ");
  delay ( 1000 );
}

void loop()
{
   lcd.home ();
   // Do a little animation by writing to the same location
   for ( int i = 0; i < 2; i++ )
   {
      for ( int j = 0; j < 16; j++ )
      {
         lcd.print (char(random(7)));
      }
      lcd.setCursor ( 0, 1 );
   }
   delay (200);
}


The display backlight comes on, which suggests that the I2C is communicating, however I was not able to see anything but the backlighting.

The potentiometer is a multiturn one with little resistance or feedback so I thought perhaps it was damaged. Using a multimeter I was able to see it reducing resistance after many turns, and finally I saw an image. So if you're just getting backlighting - try adjusting the contrast even if it looks like it's not changing.

FM - thanks for the new library!

--creatrope
« Last Edit: January 08, 2013, 10:34:18 pm by creatrope » Logged

Germany
Offline Offline
Edison Member
*
Karma: 100
Posts: 1229
If you believe something is right, you won't see what's wrong (David Straker).
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi

I just wanted to mention that i have updated the menu und user interface library M2tklib fo support your New LiquidCrystal Library.
A beta release of M2klib for New LiquidCrystal can be downloaded from the M2tklib project page http://code.google.com/p/m2tklib/downloads/list. New LiquidCrystal needs to be installed before using M2tklib.

All in all, adding support for New LiquidCrystal was really easy and the transition was without any problems. Thank you for the excellent library and the great documentation.

Oliver
Logged

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 37
Posts: 2172
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That is a very cool contribution! Nice one.
Logged

   

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

it it possible to use this library with slightly a different connection between the LCD and the PCF8574? I'm referring to this schematic https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/i2c_lcd_schematic.jpg

can this be done by hacking a certain .h or .cpp file? I'm asking this was I'm working on a pbc layout of the above circuit, and that change would simplify things a bit  smiley

edit: it's trivial after all, the documentation was clear smiley
you just use the appropriate constructor which also defines the EN, RW, RS pins
LiquidCrystal_I2C (uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs)
« Last Edit: July 20, 2013, 07:18:26 am by straddlethemoon » Logged

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 37
Posts: 2172
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, it shouldn't be a problem at all. You shouldn't even need to touch the header files. All the "constructors" can be parametrized. Meaning that you can configure the pin mapping to match your connections. Look at the examples and header files.
Logged

   

Pages: 1 ... 7 8 [9] 10   Go Up
Jump to: