I2CLCDextraIO available - 2 pin LCD controller board

Have you run out of pins in your project?
Would you like to free up some pins that were used by the LCD?
Too many pins to connect an LCD?

Simplify LCD connection to your application with the I2CLCDextraIO backpack board.

The I2C LCD extra IO controller is now available for all of you who are interested.
The boards come in the following assembly options:

  • Bare boards - 2,20€
  • Fully assembled board - 6,20€
  • Fully assembled board + LCD (16 x 2), blue or green - 12,00€

Free shipping to the EU, US please enquire.

Here you have the links both for the board and control library.

Both libraries and boards are open source, you can download them, use them, clone them, … as long as you mention where you got them from :wink:

I still have to publish the board wiki, with all its schematics, PCB layout, etc. I’ll keep you posted.

Good work, and good price too! I'm doing it with serial way so there is an on-board processor to integrate more functions on it to free up the main arduino :) See my signature.

Hi liurd,

thanks for your comments.
our work looks fantastic I really like the looks of that MMI. I’ve gone through the code and love the simplicity behind it. Great work there.

This board is a little bit more modest than yours in the sense that it tries to be a very cheep way to get less pins to control an LCD.

BTW, I was thinking that you could give the LCD library a shot. The library is compatible with the current LiquidCrystal library, extendable, and currently supports several mechanisms to control LCDs.

The project wiki and documentation is already available.

You can download the schematics, Eagle files and part list here: https://bitbucket.org/fmalpartida/i2c-lcd-extra-io/wiki/Home

Hope you enjoy it.

fm: Hi liurd,

thanks for your comments. Y our work looks fantastic I really like the looks of that MMI. I've gone through the code and love the simplicity behind it. Great work there.

This board is a little bit more modest than yours in the sense that it tries to be a very cheep way to get less pins to control an LCD.

BTW, I was thinking that you could give the LCD library a shot. The library is compatible with the current LiquidCrystal library, extendable, and currently supports several mechanisms to control LCDs.

Thanks. I call MMI HMI so it is politically correct on this side of the pond :) I'm also making face plates for these panels besides a small version like your back pack. Your board definitely is on the other end of the complexity spectrum so it can be sold at a good price.

I will give your LCD library a try. My major focus is on the HMI functionality so not tied to a particular LCD library. Your library may be helpful in porting to GLCD, my next step, if it is generic enough. For the moment, I'll stick with the standard LCD library for my firmware release.

Your project sounds cool. The LCD library is for alphanumeric LCDs, not graphical ones. The GLCD, is a great library and is being actively maintained. The LCD library came about because of the need to drive my board, but above all because of the many libraries that were about (some better some worse, some more or less compatible with the standard LiquidCrytal) trying to control different interfaces for an LCD. This library kind off puts all that together in one place with one interface and extendable to new ways of interfacing to LCDs. For example SPI is missing and shouldn't take more than an hour to have it up and running.


Rel. V 1.1.2 of the LCD library has been released with performance enhancements.

Release highlights

  • Version V 1.1.2 is 3.25 times faster than the original LiquidCrystal library
  • Minor comments added to source code
  • Documentation only available in .html format

Download Project wiki - https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home Project donwload - https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads

So you must be busy improving your library lately. I was on a different direction, expanding my display back pack to have an addressable option so up to 254 LCDs can be connected together on one serial port :) Some details on the exhibition board.

I wonder if you are already implementing addressing since your I2C back pack can be addressed (up to 8 LCDs). I'd be happy to supply you the syntax of my serial LCD addressing and possibly work out a uniform/standard call to address a particular LCD, on I2C back pack, on serial back pack (only Liudr version has this capability ^_^), or on separate EN lines with original parallel LCD library. This should be useful to some people and will expand your library in a direction your I2C back pack is already headed. What do you think?

Hi Liudr,

The LCD library as it stands today is more of a driver to control LCDs than anything else. Addressing can be built on top. For the I2C class LCDs, addressing is implicit in the bus, ie. when you create the LCD object, you tell it what address the LCD is. Therefore, you can create multiple instances of each LCD.

For a serial LCD this might be different since it implies having a different protocol to manage the LCD and logic to control it. It'd be interesting to see you line of thoughts. Please do share.

I will give it a thought to see how it can fit, something like an abstract factory...


What about this? When you instantiate a serial LCD, have a parameter called address, you can do:

LCD (parameter list); // Constructor for regular serial LCDs LCD (parameter list, address); // Constructor for serial addressable LCDs

To communicate with my addressable serial LCD, just do Serial.print("\x1C\x01message for display 01\x17");

The 1C is the file separator in ASCII language, which I use to indicate I will issue an address. The next byte is the LCD address, 01. Then to end transmission with LCD 01, I issue 17, end of data block in ASCII language. You can also instantiate an "ALL serial addressable LCD" object with address FF. Then whatever you write to this LCD is shown up on all LCDs. You don't have to do anything. It's already done on my firmware. You just have to send out these addresses and end of block after transmission.

Hi liudr,

as I thought, you’ve built a protocol on top of the LCD library. So to control several LCDs using a serial line, you most likely have a daisy chain with a small controller on each node.

Now the whole thing about the LCD library, is as follows:
The LCD library is a pure abstract class that implements the generic mechanisms to control a Hitachi HD44780 controller. This means that it implements sending the actual commands to the LCD that it understands. For example, the base class implements:

void LCD::blink() 
   _displaycontrol |= LCD_BLINKON;
   command(LCD_DISPLAYCONTROL | _displaycontrol);

Regardless as to how the LCD is driven.

Now, each base class implements the initialization details and access mechanisms to actually write to the LCD.
In the example above, the command in every implementation, ends up calling the send. This send is in fact dependent on how you write to each LCD (4bit, 8bit, I2C, SPI or SR).

Therefore, this is not compatible with the way you send commands to the LCD, since there is someone doing these operations on each node. A different story would be if you sent to the LCD commands like: <bot><address><command>\0x80<eot>. This command would arrive to node with address <address> and write to the LCD a command of value 0x80. This would cause the cursor to position at location (0,0). You would then have to send <bot><address><data>Hello world<eot>, and would write the message.

So, what this library would understand is the <command|data><values>. To do this in the library is straight forward. However, on top of the library you have built a small link protocol, i.e. <bot><address><my message><eot>.

Not too sure if I have explained my self :blush:.

So as a conclusion we could say that the library could be extended to process messages like: <command|data><values>, where commands are binary commands sent to the LCD and data is whatever you want to write on the LCD via a serial link, for example. Could you have a link protocol on top within the LCD library? Yes you could. In the sense that, you could have a class called "LiquidCrystal_SerialAddr. This could send LCD messages to the other end in the following format: <bot><address><my message><eot>, where <my message> ::= <command|data><value list>, where the value list for commands are the raw control commands for the LCD. The LCD driver would just need to have in the constructor the address of a remote node.

The only problem here is that you have to build on the receiving end a small “serial to LCD proxy”. On the serial to LCD proxy you would have to have an intelligent processor that would initialize the local LCD, and then read from the serial line, interpret the header, determine if its a command for this LCD, and call the send methods of the LCD accordingly. Broadcast messages, could have 0xff, how would they work: what ever comes over the serial line, I write it to the local LCD and resend it over the other serial line of the daisy chain.

What do you think? Is this in the lines of what you were thinking?


Understand. In this case, maybe just instantiating one serial LCD object is appropriate. The user will then be responsible to address the appropriate LCD by printing to the serial object the appropriate command+address. Then after done with the LCD, print end of block to the serial LCD. So this way the existence of multiple LCDs on one serial line is transparent to (or known by) the library. Just very little extra work by the user of the library to make it work on my simple protocol.

I have not got a chance to read through your library yet (bit hard for me to understand the abstract syntax :sweat_smile:). So what characters, besides 0x80 are considered as commands? I know that sparkfun serLCD uses 254, or 0xFE, to start a command, right?


The values you can find them in the LCD.h there are about 20 in total.

What I was thinking is if anybody creates more that one with this method it would consume a good range of memory. That is, you create on object for each LCD in your bus.

Perhaps you could use your protocol and limit it to a certain range of commands, or the driver/protocol could be simple but proprietary.

Also you could use the Sparkfun library and make it addressable?

Let me give it a thought.


Sparkfun's serLCD is a pretty basic system, can't address serially. Mine is probably 10 times as complex with interactive features and compatible with several types of keypads. I have not seen any other serial addressable LCD except for RS-485 devices used for industry. My command set is entirely different from sparkfun or other simple serial LCDs since I implement the ANSI escape sequences to adjust cursor positions, types, etc. besides ASCII control characters and custom escape sequences. Everything sparkfun does is probably sending 0XFE followed by a one byte command and variable bytes of operands. I could make mine interpret sparkfun way too, just adding a few percent to the project code ;)

I understand! Sorry but I have only seen a fraction of it :-(.

liudr, fm's LCD class library is really a hd44780 library. It knows how to translate the existing LiquidCrystal API into lower layers that talk to the hd44780 based lcds over different interface mechanisms. So regardless of the communication mechanism (4 bit parallel, I2C, SPI, etc...) the assumption is that it is a hd44780 command/data interface and the interface class modules are merely providing the appropriate transport to move the hd44780 commands and data from the AVR to the lcd. So for example, when the user calls the home() function, the LCD class sends a LCD_RETURNHOME (0x02) command by calling the send() function in the appropriate interface class. It is the responsibilty of the interface class to deliver that to the lcd over whatever means is available. The LCD class keeps track of all the low level information such as where the row offsets are, number of lines, etc..

Your interface seems to be a higher level interface based on commands embedded in the messages and is a superset of the hd44780 capabilities. So I would think that if you wanted to be compatible with a low level interface like fm's LCD class library, you would need to provide a "passthrough" command. This would allow the sending of a raw hd44780 commands and data. Yes, it wouldn't use any of your additional/extended functionality and would be limited to the simpler hd44780 commands.

For a more intelligent type of interface that could take advantage of the smarts in an interface board, I'd say that is a higher level library. In fact that library could potentially sit on top of fm's library. So that if the device was intelligent, higher level messages would pass through to the device over the communication path. But if the device was less intelligent the library could have the smarts to peek into the messages and interpret the message and then call the LCD class to translate that into the various hd44780 commands to provide the same functionality.

Then there is the alternate approach of simply defining an API and leaving it as kind of a free-for-all saying that all lcd class libraries should implement these API functions. This is kind of what exists today. Here is a playground thread about that: http://arduino.cc/playground/Code/LCDAPI

--- bill

hola fm, me ha costado mis buenos 4 o 5 minutos pero encontre el post. Quiero montar una pantalla GLCD al arduino y me he acordado de que tu proyecto. La pantalla seria esta http://www.ebay.com/itm/170899666269

Se podria usar tu controlador para controlarla con solo I2c?

un saludo.

Hi thanks for the question. That particular module can’t be driven with this particular backpack.

The main reasons:

  • not enough pins to drive the GLCD. The backpack assumes the base configuration and pin layout of a standard character LCD module 16 pins as opposed to 20 with a particular layout.
  • Even if it could be driven, I am not sure if the I2C speed would be sufficient to have fast enough refresh rate. Could be OK for static images but certainly not for animations.

So for character LCD: OK