Go Down

Topic: New LiquidCrystal library - LCD library (Read 26 times) previous topic - next topic


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.


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


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?


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


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.


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

Go Up