LCD Chip P017(serial) & P018(I2C)


This is a 20 pin IC that will take either a serial or I2C input and convert this to suitable signals for a standard character type LCD display, these usually come as 16x2, 20x4, 40x2 lines etc.

A unique feature of this IC is that it has three PWM back light outputs making it suitable for ordinary displays with just one back light or the newer displays that have a red green and blue back light.

The PWM outputs will normally go to the cathode of the LCD, LED with a common anode. The back light LED anode (+V) on nearly all displays is pin 15. If it is the other way round then the PWM will still work but backwards. However if using the PCB, this is designed that pin 15 is the anode.

The Chip can be fully controlled, The sign on screen is saved to EEPROM and so this can be changed by the user.

The P017 has a serial input and the PO18 has an I2C input otherwise they are identical.

The IC can be used in a stand alone project or it can be used with the purpose made PCB that attaches to the back of the display. The circuit diagram for the PCB is on the data sheet.

Windows Serial

The chip has TX and RX connections that can be connected to a USB to serial device. If the PCB is not used then only one device at a time can be connected to the serial bus. If the PCB is used then many can be used as the PCB TX attaches to an open collector (more or less) output.

No handshaking is required simply connect TX to RX and RX to TX as shown. It is important that the F and reset pins are tied to +V The variable resistor is for the LCD contrast, for experimentation this pin can be tied to ground but the display may then have too much contrast but at least it can be seen.

Once connected use BV_COM, this is free and does not need installing, just run the exe.

Set echo on, set the correct COM port.

The P017 has a default address of 'p' and from the factory will display a sign on message:

For here some commands can be entered through the terminal for example:

  • pdfred - will display fred
  • pc1 - will clear the display
  • pc212 and then pdfred will place 'fred' on the bottom line of a 20x4 display


The session of the above looks like the above. The prompt coming back is '>' which is wrong, it should be the value 6. This is because the chip can be used with or without the open collector TX output mentioned earlier.

The command pD will bring back the device ID which is 17, as can be seen at '1' this is not correct. To invert the output 'pI' is send and immediately device operates correctly sending back 6 as the ACK and observe at 2 the output from 'pD' is now, correctly, 17. The invert command is a toggle and it will stay even after power remove, so it is a one time operation.

The '>' is easy to detect on automated systems and so can be handles easily.

A much easier way to use the device on windows is to run the sws software that works with the Python language. It is not that difficult to install, the instructions are given here.

Once up and running this is the dialog screen.

The back light for the normal screens with only one back light is the red one. The sliders will control the brightness from off to full brightness in 10 steps.

Windows I2C

There is no output on a Windows PC that will give I2C and so some other device is required. For this a BV4221_V2 device is used that allows an I2C device to be connected via the USB. The Python code '' is given in the link as the BV4221_V2 does require setting up for this it is best to follow the instructions on that link. If you have the dialog box running above then you can run the '' code and obtain the dialog box as above but this time via the I2C interface.

Raspberry Pi Serial

Voltages: Most LCD displays are 5V logic and so there will be a problem if just using the IC alone. This is because the TX output will be at the voltage supplied to the +V pin, i.e. 5V. The PCB however that can be supplies with this IC has the following circuit:

RB7 is the TX pin form the IC and D1 is a 3.3V* zener diode thus limiting the output to the Rpi and providing a safe serial interface. This circuit also has the added bonus that multiple devices can share the TX line and thus the same serial bus.

*The diode may in fact be rated at a higher voltage due to the low resistance characteristic of zener diodes at low current.

Install the serial software as given in the instructions on this site. The connections to the RPi are as shown above. Note that the 5V supply is used to provide the power, it is therefore important to have the above circuit, which the PCB has.

Raspberry Pi I2C (Updated 26 April 2018)

Connection to the RPi via the I2C lines. Here the logic voltage is not important as the PRi will control this with its own internal pull up resistors. (+L goes to 5V)

1) Check that you have connected the device correct by by using I2C detect:

  • Older rpi: sudo i2cdetect -y 0
  • Newer rpi: sudo i2cdetect -y 1

If it can't find i2cdetect then the software has not been installed correctly, go back to step 1) For just the P018 connected it should look exactly like the above 0x38 (decimal 56) is the address of the device.

2) This zip file contains a library for the P018, create a folder and unzip the contents of the Rpi folder, then type python

Check the library '' in the folder for the functions that are available.


There are two libraries for the Arduino depending on the interface. Both are for version 1.01.

Both use the same library functions except the constructor which is slightly different.

  • lcd_cls() // clears LCD display
  • lcd_rowcol(row,col) // places cursor on defined row and column, both start at 0
  • lcd_cursor(type) // type=0=cursor off, type=1=cursor normal, type=2=block flashing
  • lcd_print(string)
  • lcd_print(integer)
  • lcd_bl(red,green,blue) // see below
  • lcd_defcust(address, definition) // see below
  • lcd_printcust(address) // see below

Back Light

The display controller can support up to three back lights and each output is PWM. The function will accept 0-10 for any value. For example:

lcd_bl(3,3,0) // dim yellow

lcd_bl(0,10,0) // bright green

lcd_bl(0,0,0) // back light off

This of course applies to displays that have 3 back light LED's. For 'normal' displays normally just the RED is connected.

Custom Charatcters

These can be defined using 8 bytes, see the various web sites for determining which bytes to use. The address supplied is from 0 to 7 and this will be used for displaying a custom character. The example in the zip files above have two custom characters defined.


Mini Project

This little bit of code can read the system details using Python and display them to the LCD. On windows the output is like this:

On the RPi it looks like this:

(sorry about poor quality picture)

Software Required.

For this to work without a hitch all of the software is required as explained in the software section for the particular host (Windows or Rpi) that you are using. The RPI requires more setting up than Windows.

The following files will be needed to complete the project, they can be downloaded into a separate directory if required. The classes are in the downloads section.

This gives access to the methods which are:

  •,g,b) # sets the back light brightness 0 to 10
  • lcd.cmd(cmd) # sends an LCD command
  • lcd.lcd(data) # sends data to the lcd display, can be string, number or variable
  • lcd.rc(row,col) # puts the cursor to a specified row or columns; start at 0
  • lcd.cls() # clears the display
  • lcd.cursor(v) # sets cursor appearance v = 0 to 2

For single colour backlights just specify the red and leave green and blue 0. The lcd.rc(r,c) relies on a table at the head of the p017A file, the values are suitable for most LCD displays.

For Windows:

python 0 COM21 115200 55 # I2C using BV4221 on COM21
python 1 COM14 9600 p # SERIAL on com14 with address 'p'

For RPi

python 0 1 "" 56 # I2C using bus 1
python 1 /dev/ttyAMA0 9600 p # SERIAL on ttyAMA0 with address 'p'


#! /usr/bin/python
# Mini Project for the PO17 LCD see
# wget
# wget
# wget

import p017A     # LCD class
from sv3A import sv3Bus
import sys
import platform
# ------------------------------------------------------------------------------
# This just ramps up and down the pwm on channel 1, if a LED is connected
# it will go bright and dim
# ------------------------------------------------------------------------------
def lcd_test(bustype,bus,adr):
    if bustype == '1':
        # serial
        lcd = p017A.p017(bus,adr) # adr is string
    if bustype == '0':
        # i2c 
        lcd = p017A.p017(bus,int(adr)) # adr will be a number 
    value = 0
    print "Device id", lcd.ID()
    print "Firemware ",lcd.FW()
    msg = " "+platform.processor()[0:9]
    msg = platform.platform()[0:15]

if __name__ == "__main__":
    # type = 1 for serial 0 for i2c
    # usage python 1 COMx Baud h // for serial
    #       python 0 COMx Baud 54 // for indows i2c
    #       python 0 1 "" 54// for rpi i2c using bus 1
        bus = sv3Bus(int(sys.argv[1]),sys.argv[2],sys.argv[3]) # open bus for all devices
        msg = 'Cant open comport,'+str(sys.argv[2])+' use: see file'
        print msg

Additional Resources

A big thanks to Julian for these Python scripts.


1) Can you confirm the above item will work with a 3.3v display as well as a 3.3v host processor.

the controller will work down to 2.5V and is designed for 3.3V or 5V logic and so there should be no reason why it will not work with a 3.3V display although I have not tried it.


Using I2C you can run it at 5V with a 5V LCD and use the 3.3V pull up resistors of the RPi, this will give a safe 3.3V interface to a 5V IC.


The shown circuit above that is built into the PCB will give 3.3V protection and so can be used in a 3.3V logic system but the IC and LCD can run at 5V

2) Example of using the P017A class

a) You need to install the software as described above.

b) Type python to get the
>>> prompt

Depending on the host platform (Windows, Rpi) and the method of access (Serial, I2C) will depend on how the bus is activated.

Windows Serial
>>> import p017A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(1,'COM14',9600) # open bus for all devices
>>> lcd = p017A.p017(bus,'p')

Windows I2C using a BV4221 device
>>> import p017A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(0,'COM21',115200) # open bus for all devices
>>> lcd = p017A.p017(bus,56)

RPi Serial
>>> import p017A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(0,'/dev/ttyAMA0',115200) # open bus for all devices
>>> lcd = p017A.p017(bus,56)

>>> import p017A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(0,'1','') # change to '1' to '0' for older RPi
>>> lcd = p017A.p017(bus,56)

If any of the above reports errors then go back and re-install the software, it is likely that something has been missed.

Try a few commands:

lcd.ID() # get the identiy,0,0) # set back light to red full on



3) How do I move the cursor to another line on the display?

This is done with a command and applies if type HD44780 or similar controller is fitted to the display (most are or compatible). It also only applies to 2x16 and 4x16 or 4x20 line displays.

A command is used with a value to move the cursor to a particular position on the display, the start of the line has the following command values:

  • line 1 128
  • line 2 192
  • line 3 148
  • line 4 212

This will put the cursor to the start of one of those lines. So for example when using the P017 the serial command is 'c' so if the address is 'p' then

  • pc128  puts cursor to start of line 1
  • pc192  puts cursor to start of line 2
  • pc148  puts cursor to start of line 3
  • pc212  puts cursor to start of line 4

If you want to put the cursor some way along the line, say line 2 column 5 then simply add it to the command value, 192+5 = 197 so

  • pc194  puts cursor on position 5 of line 2