Go Down

Topic: Folding 3-wire support into the LiquidCrystal library (Read 2448 times) previous topic - next topic


OK, so I'm using the 3-wire (shift register) interface to a LCD, in order to save precious I/O pins. Unfortunately the 3-wire LCD library is not code-compatible with the LiquidCrystal library and is missing some useful features (it doesn't implement the Print class, for example).

So I've edited the LiquidCrystal library to include a new constructor. If you pass it just data, clock and strobe pins, it operates in 3-wire mode; otherwise it carries on as normal.

Does this sound like a useful hack to anyone else? Anyone want to test it to make sure it still works correctly in 4- and 8-bit mode, as well as 3-wire mode?


Oct 29, 2011, 01:21 pm Last Edit: Nov 11, 2011, 12:50 pm by m12lrpv Reason: 1

Ha ha

I just came in to post that I have done the same thing and thought I better check that I wasn't posting something someone had already done.

I too modified the standard library to handle the 4 bit configuration via shift register while maintaining the existing functionality entirely.

This was born out of frustration at having to always reconfigure my LCD to free up some of the "feature" pins on the Arduino, like the interrupt pins 2, 3, the T1 pin 5 and the PWM pins plus the analog pins.

I feel that this modification should be standard in the library because it allows people to wire their LCD into a DIY shield with just 3 pins used (for me that's 4, 7 and 8 which don't appear to have any special function) and never have to modify it again.

I've attached my library code and here is how it varies.
You tell it the Arduino pins used for the shift register pins data, latch and clock and you tell it which shift register pins you have wired to the standard LCD inputs. For me that's outputs 1 to 6 on a 74HC595N
Code: [Select]

//LiquidCrystal lcd( sr_data, sr_latch, sr_clk, rs_bit, enable, d0,  d1,  d2,  d3)
 LiquidCrystal lcd(       4,        7,      8,      1,      2,  3,   4,   5,   6);

Edit: There was a bug in the library modification that would set the pins that matched the d0, d1, d2 and d3 pin values to output only. In the example that's pins 3,   4,   5 and  6.

A new version is attached.


Hey guys

I'm a bit of a newbie at this!

I tried to use your library (the one attached to the last post) but I can't get it to compile. I am using a Sketch that already works for 7 pin mode. I get this error on compilation:

Code: [Select]
In file included from DistanceLCD.cpp:1:
/Applications/Arduino.app/Contents/Resources/Java/libraries/LiquidCrystal/LiquidCrystal.h:105: error: conflicting return type specified for 'virtual void LiquidCrystal::write(uint8_t)'
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:48: error:   overriding 'virtual size_t Print::write(uint8_t)'

Doing a bit of googling this suggests the library isn't compatible with Arduino 1.0 - I tried to fix this by using #include "Arduino.h" but this had no effect.

Can you help?


I was wondering if this would still work. I'll have to download 1.0 and try it.


I was wondering if this would still work. I'll have to download 1.0 and try it.

Cool, would be great if you could get it working. I had no idea 1.0 was so fresh!


I've found the problem. They've gone from this in the 0022 library
Code: [Select]
virtual void write(uint8_t);

to this in the 1.0
Code: [Select]
virtual size_t write(uint8_t);
  using Print::write;

I've been too long out of C++ programming to get the parlance correct but they are redirecting the write through the print so they had to redefine the function declaration to be compatible.

There was one other minor fix too between the old and new original libraries.


Cannot upload. It seems the forum file folder is full.

If you want to modify the other one at around line 106 in the LiquidCrystal.h is the change I mentioned above.

In LiquidCrystal.cpp at about line 399

the write function declaration changes to this
Code: [Select]

inline size_t LiquidCrystal::write(uint8_t value) {
  send(value, HIGH);

that should get it compiling.


OK, it compiles now. Unfortunately not been able to get it to work yet. I am using the same pin assignments as in your example but I just get a blank screen.

I will do some more troubleshooting (it's a new SR chip and I need to make sure it works with LEDs etc) but in the meantime can you clarify something for me?

When you say d0 d1 d2 d3 on the LCD side is that accurate or do you mean the high nibble of d5 d6 d7 d8? The only reason I ask is that d5-d8 are the pins I connect to in 4-bit mode when using the regular LiquidCrystal library.


The example is for an LCD wired to the output of a shift register such as a 74HC595N

For a regular LCD you just use the call the same as you would in any of the liquidcrystal examples.

In my example
Code: [Select]
LiquidCrystal lcd(       4,        7,      8,      1,      2,  3,   4,   5,   6);
the first part
Code: [Select]
4,        7,      8 are Arduino pins that are connected to the shift register

The second part
Code: [Select]
1,      2,  3,   4,   5,   6 are the outputs of the shift register that are connected to the LCD the first two parameters being the shift register pins connected to rs_bit and enable on the LCD and the last 4 define the data pins on the LCD.

What shift register are you using?


I am using the same Shift Register - the 74HC595N well, actually a clone SN74AHC595N but I think it should be the same - this is why I need to check with LEDs!

I hooked up the pins as per your example, so using 4,7,8 on the Ardiuno side, and outputs A,B,C,D,E,F on the SR side. I am using data pins d4,d5,d6,d7 on the LCD.

I have tied pin 13 of the SR (Output enable) to GND and pin 10 (Reset) to 5v as per another example I have been using. Does that sound correct?


It's a pity the upload's not working or I could just post a photo.

I take it you're using the TI datasheet. I have the NXP one as that matches my version of the chip and it uses numbers.

QA = 0
QB = 1
QC = 2
QD = 3
QE = 4
QF = 5
QG = 6
QH = 7

I used 1 to 6 (B to G) because they're all on the same side.

To translate my example. d0, d1, d2, d3 are defined in the standard liquid crystal library parameters even though sparkfun have them as d4, d5, d6, d7 (which is how you wire them).
For instance if you call this LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) with standard LCD wiring you're actually calling this in the library LiquidCrystal(rs, rw, enable, d0, d1, d2, d3 ) (datatypes removed for clarity)

To rewrite for your datasheet my call would be this.
Code: [Select]

//LiquidCrystal lcd( sr_data, sr_latch, sr_clk, rs_bit, enable, d0,  d1,  d2,  d3)
//LiquidCrystal lcd(       4,        7,      8,     QB,     QC, QD,  QE,  QF,  QG);
  LiquidCrystal lcd(       4,        7,      8,      1,      2,  3,   4,   5,   6);

Everything you've said you've done sounds right however I expect that you're starting with QA or Q0 on the shift register where I didn't. In that case your call might be
  LiquidCrystal lcd(       4,        7,      8,      0,      1,  2,   3,   4,   5);


Aha, that could explain things! I will have a go a building again later and will let you know how it goes. Thanks a lot for your help :)


All working now - both in 6 wire and 3 wire mode. Thanks a bunch :)


Glad it's working.

I soldered the shift register to the underside of a shield with the LCD on top and after doing that haven't had to re solder a single pin on the shield for any sketch.

It's a little bit slower but that hasn't been a major problem.

Go Up