I2C Python Library - LCD with the Raspberry Pi

This is the first of a couple libraries to come that greatly simplify using I2c capable devices on the Raspberry Pi with Python. Although there is a couple code examples out there, the intent of this library was to be flexible enough to allow for the various types of I2c LCD devices available. The main variation in these devices are the pin layout between the I2c IO expander (ex. PCF8574*) and the LCD HD44780 controller; the library can be configured at instantiation to accomodate any of these pin layouts. Additionally it has simple functions for home, clear, cursor position and backlight control.


 Determining The Pin Layout

Determining what the correct pin numbers is crucial for the library to function. This should be available from the vendor you purchase the LCD or could be acquired from the schematic. Additionally most vendors will have example Arduino code which could be used to determine the pin layout. Here is an example of Arduino code and how to interpret it.

The port is easy to determine. The original Pi is 0 and the new version is 1.

Installing the I2C Libraries

Note: This library has changed and now requires the Quick2Wire libraries. To use a legacy smbus version, use i2c_lcd_smbus.py.

Instructions for installing the Think Bowl I2C Libraries are here.



Turns the backlight on if available


Turns the backlight off if available


Clears text from screen


Sends a command function to LCD. Variables with the different commands and options are available in the object.


Returns cursor to top left position

setPosition(line, position)

Sets the cursor to the given line and position on that line. Lines are 1-4 and positions are 0-19.


Writes a single character at the current cursor position


Writes a string to the screen starting at the current postion



Posted in Peripherals, Raspberry Pi
22 comments on “I2C Python Library - LCD with the Raspberry Pi
  1. Ruaridh says:

    Thank you, thank you, thank you!! I've been battling with a cheap chinese i2c backpack (mjkdz on the back) and a similarly cheap 1602 16x2 module for a few days, but was struggling with the pinouts. For the benefit of others with this module (and a new PI), this is what you need:

    lcd = i2c_lcd.i2c_lcd(0x27, 1, 4, 5, 6, 0, 1, 2, 3, 7)

  2. Fixair says:

    first of all, thank you for your work, it helped well me. I have nevertheless a problem with a command(order) of the I2C LCD: I wish to deactivate the cursor which does not serve me in my project. Can you give me the correct syntax to use " command () " please? Thank you in advance and one thousand excuses for my level of English because I use an automatic translator.
    Cordialy FX ;op

    • ebartel says:

      The library turns the cursor on by default. You can turn it off after you initialize the LCD by issuing the display control command and omitting the OPT_Enable_Cursor option. Here is an example:

      lcd = i2c_lcd.i2c_lcd(0x27,0, 2, 1, 0, 4, 5, 6, 7, 3)
      lcd.command(lcd.CMD_Display_Control | lcd.OPT_Enable_Display)

      I hope this translates back fine. I've also updated the code above so that it is a little easier to read.

      • Fixair says:

        Well done, thank you, I did not understand everything but it works ;op
        Here is a piece of my project: http://vimeo.com/42509258
        I make a simulator of helicopter around FSX

        Now I look has to realize a client tcp under Linux or c/c ++, or Python and a server tcp under win7 C# to use Raspberry Pi has the place of Arduino UNO in c/c ++ .

  3. Sven says:

    Nice, but does not work on my PI.

    I have done the installation like here this but this is the result:

    pi@dev ~ $ python3 test.py
    Traceback (most recent call last):
    File "test.py", line 1, in <module>
    from i2clibraries import i2c_lcd
    File "/home/pi/i2clibraries/i2c_lcd.py", line 1, in <module>
    from i2clibraries import i2c
    File "/home/pi/i2clibraries/i2c.py", line 1, in <module>
    from quick2wire.i2c import I2CMaster, writing_bytes, reading
    ImportError: No module named quick2wire.i2c


    • ebartel says:

      I've updated the installation instructions here with a FAQ related to this. Looking at the error above it looks like your project folder is the pi users home directory so you would want to use the following commands to set your environment variables:

  4. cbaket says:

    Thank you!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    it helped me very very much.

  5. peterrus says:

    I have version 1 of the mjkdz i2c lcd backpack and can't get it working using your modified initialization line. Here is the 'datasheet' of both v1 and v2 http://we.tl/s3B73cPgTB beware: it's of really poor quality, hardly the word 'datasheet' worthy.

    Some things I found out:
    - I have to use lcd.backLightOff() in order to turn the backlight ON
    - it uses i2c adres 0x20
    - There is a table with pinouts/instructions? in the sheet, but they make no sense to me.

    • ebartel says:

      The problem most likely is unfortunately the various manufactures of these boards hook up the PCF8574 chip differently to the LCD. They normally provide a pinout table for this but I didn't see one in the document you provided. I took a look on the internet and I believe this is it:
      RS - 6
      RW - 5
      E - 4
      D4 - 0
      D5 - 1
      D6 - 2
      D7 - 3
      Backlight - 7

      So you should use the following to initialize the lcd object on v1 RPI
      lcd = i2c_lcd.i2c_lcd(0x20,0, 4, 5, 6, 0, 1, 2, 3, 7)
      or on v2 RPI
      lcd = i2c_lcd.i2c_lcd(0x20,1, 4, 5, 6, 0, 1, 2, 3, 7)

  6. peterrus says:

    Thanks for your reply!

    unfortunately no success yet. I did some digging however and found this pack of information that was supposed to be shipped with the module: http://www.nimseugjs.com/IC/All%20data%20modules/1792.zip

    In zip you will find several schematics in '\code\Arduino\LiquidCrystal_I2C\info'.

    I was most interested in this schematic:

    I tried the following line:

    lcd = i2c_lcd.i2c_lcd(0x20, 1, 9, 10, 11, 4, 5, 6, 7, 12)

    but this gave me the following exception:


    I tried to find the pinouts in the initialization line of the example arduino code, but no such line is used. i2c_lcd's default constructor contains no pin defintions:

    LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
    _Addr = lcd_Addr;
    _cols = lcd_cols;
    _rows = lcd_rows;
    _backlightval = LCD_NOBACKLIGHT;

  7. peterrus says:

    Also, this schematic refers to http://i.imgur.com/5pqI3Wm.jpg (image was not showing in my preview)

  8. peterrus says:

    Above comment was an addition to a post that was not approved it seems, mistake ?

  9. peterrus says:

    Never mind, browser acted up, sorry 😉

  10. peterrus says:

    Alright, above pinmapping, which gave the exception is complete nonsense. I used the schematics contained in the zip from the manufacturer to create a pin mapping and came to the same conclusion as you did. Does not work.

    I think the manufacturer used a different layout so I am going to desolder the port expander chip from the board and trace the wires later. Will report back.

  11. peterrus says:

    The pinout on the board is exactly as you told me. I am not sure what is going wrong here, the backlight does get turned on (when expected to be off, and vice versa) and thats is.

    • ebartel says:

      It is possible that you got a bad board or LCD. Could you provide your full source code? I believe I have one of the mjkdz boards and I could give it a try.

  12. kamencesc says:

    I've the mjkdz with 0x20 port and works fine with the pinouts listed on comments, test the signals with a LED and send easy binnary signals to send trought each pin.

  13. peterrus says:

    I have used an arduino sketch to test the board/display and exactly the same happens: backlight works and thats it. I doubt it has anything to do with your code. I have two boards and two displays, so having a faulty board seems a bit far fetched. Then again: I have no idea what else could be the issue.

    As far as the sourcecode goes: I have used your example code under 'I2C LCD Usage Example' on top of this page, with the modified constructor.

    I will test kamencesc's suggestion later, as well as completely different display (from another supplier). Will report back, and if someone has suggestions in the meantime: i'll be happy to hear them.

  14. peterrus says:

    It works, kinda. Something is clearly wrong with both boards. On one board I get text on the screen if I short two pins on the contrast potmeter and on one board even that makes no difference. Clearly off topic now. Thanks for the help 😉

  15. kamencesc says:

    Test with a tester if the value of potentiometer is fine, usualy a value of 2K works fine, otherwise use a 2K resistor (or between 2K and 3,9K) or with a LED test if it dims when you change the value of the potentiometer.

    Check this, is a translated version of a post of my project that I talk about something similar that happens to you: http://translate.google.com/translate?hl=ca&sl=auto&tl=en&u=http%3A%2F%2Fpimyheater.wordpress.com%2F2013%2F09%2F15%2Fja-funciona-la-lcd%2F

    Then, for the visitors of this post, there's a portion of code of how add custom chars:

    def customChar(vect, pos=0x0):
    for x in range(0,8):

    vec = [0xe,0x1b,0x11,0x11,0x11,0x11,0x11,0x1f]
    customChar(vect) #create char, on default position 0
    lcd._write(0x0,False) #this line writes the char

    It creates a custom char of an empty battery. You have 8 positions and you can write it with 0x0 to 0x8 (well... 0 to 8 is the same :P)

    By sending a list full of 0x0 you can delete the character.

    I don't know if it's the correct way, but it works :)

  16. kamencesc says:

    An appointment about the code for custom characters, on function customChars:



    If we point con 0x41, we start the custom character at the second line of the first customchar, so each new character starts after 8 positions.

    And then on array:

    vec = [0xe,0x1b,0x11,0x11,0x11,0x11,0x11,0x1f]

    vect = [0xe,0x1b,0x11,0x11,0x11,0x11,0x11,0x1f]

    The custom characters are in the 0 to 8 position of the memory, so, if we create a custom character on 0 and we write a chr(0) on our LCD, it show the custom character, so we don't need to use lcd.setPosition(x,y) and then write the character.

Have a Question? I read and respond.

Your email address will not be published. Required fields are marked *


* Copy This Password *

* Type Or Paste Password Here *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">