TextLCD Enhanced

This page describes an enhanced forked version of the basic driver code library for Text LCD panels using the 4-bit interface of the HD44780 LCD display controller.

/media/uploads/wim/_scaled_hd44780.jpeg

Note that there are many HD44780 compatible LCD controllers around (e.g. KS0066, ST7066, SPLC780, SED1278, LC7985A, NT7603, AIP31066). There are also controllers available that are compatible and provide additional features like an increased number of segment drivers for more characters or internal LCD contrast voltage generators (e.g. KS0073, KS0078, ST7036, SSD1803, SSD1803A, HD66712, SPLC792A). Several other types of displays use controllers that are compatible with the HD44780 to allow an easy transition, for example OLED drivers such as the WS0010 and US2066 or SSD1311. The library controls the HD44780 through a 4-bit bus either directly or by using SPI or I2C portexpanders. Several compatible controllers also have native support for SPI and/or I2C serial interfaces in addition to, or instead of, the parallel bus (eg ST7032i, ST7036i, ST7070, SSD1803, AIP31068, PCF211X, AC780). The enhanced TextLCD library supports some of these devices.

New features

  • Support for more LCD types
    • TextLCD::LCD8x1 8x1 LCD panel
    • TextLCD::LCD8x2 8x2 LCD panel
    • TextLCD::LCD8x2B 8x2 LCD panel (actually 16x1 in different layout)
    • TextLCD::LCD12x2 12x2 LCD panel
    • TextLCD::LCD12x4 12x4 LCD panel
    • TextLCD::LCD12x3D 12x3 LCD panel (for PCF2116 and KS0073 controller)
    • TextLCD::LCD12x3D1 12x3 LCD panel (alternate for PCF2116 and KS0073 controller)
    • TextLCD::LCD12x4D 12x4 LCD panel (for PCF2116 and KS0073 controller)
    • TextLCD::LCD16x1C 16x1 LCD panel (actually 8x2 in different layout)
    • TextLCD::LCD16x2 16x2 LCD panel (default)
    • TextLCD::LCD16x3F 16x3 LCD panel (actually 24x2 in different layout)
    • TextLCD::LCD16x3G 16x3 LCD panel (for ST7036 controller)
    • TextLCD::LCD16x4 16x4 LCD panel
    • TextLCD::LCD20x2 20x2 LCD panel
    • TextLCD::LCD20x4 20x4 LCD panel
    • TextLCD::LCD20x4D 20x4 LCD panel (for SSD1803A and HD66712 controller)
    • TextLCD::LCD24x2 24x2 LCD panel
    • TextLCD::LCD24x4D 24x4 LCD panel (for KS0078 controller)
    • TextLCD::LCD32x2 32x2 LCD panel
    • TextLCD::LCD40x2 40x2 LCD panel
    • TextLCD::LCD40x4 40x4 LCD panel (with two controllers)
  • Support for Backlight control
  • Support for Cursor and/or Blinking current character
  • Support for User Defined Characters to display special symbols
  • Improved methods to get and set the memory address of the current character
  • Support for I2C PCF8574 or PCF8574A Portexpander, the MCP23008 Portexpander or a SPI Portexpander as alternative interface to save on mbed pins
  • Support for some controllers with native I2C or SPI interfaces to save on mbed pins.
  • Support for setting LCD Contrast and/or Powerdown mode on controllers which provide that option.
  • Support for Icons on controllers which provide that option.
  • Support for blinking UDCs and/or Icons on controllers which provide that option.

Revisions

Refactoring (April 2014)

TextLCD has been refactored to fix an issue with recent mbed libs and pins that are defined as NC by default. The change requires that the declaration of the SPI and I2C versions in user code needs a small modification: declare these as TextLCD_SPI() or TextLCD_I2C respectively. See example code below.

Native I2C and SPI interface support (June 2014)

TextLCD has been extended with support for controllers that have native I2C or SPI interfaces (eg ST7032i). Declare these as TextLCD_SPI_N() or TextLCD_I2C_N respectively. See example code in header file.

LCDType enhancements (June 2014, Aug 2014, Sept 2014, Oct 2014)

TextLCD has been extended with additional LCDTypes for 3 or 4 line displays that are supported by some controllers (PCF211X, KS0078, ST7036 and SSD1803A). These LCDTypes use different addressing schemes and are identified by a letter added to the LCDtype enumerator. See example code in header file.

TextLCD has been extended with additional controllers (US2066/SSD1311 (OLED), PT6314 VFD). Added support for blinking UDCs and Powerdown on controllers with these capabilities.

Added support for setting orientation (upside down), added support for double height lines and 16 UDCs on controllers with these features. Moved UDC defines to separate file and added separate file to configure features and allow some control over memory footprint.

Added support for AC780. Added some I2C expander module types and added support for modules that use inverted logic for backlight control.

LCDType enhancements (Nov 2014)

Added ST7070 and KS0073 support, added setIcon(), clrIcon() and setInvert() method for supported controllers.

LCDType enhancements (March 2015, April 2015, May 2015)

Improved speed for PCF8574 and MCP23008 I2C expander interfaces, Fixed problem in Adafruit I2C/SPI LCD portexpander. Fixed occasional init problem. Added PCF2119R and HD66712. Added some I2C portexpander types.

LCDType enhancements (Nov 2015)

Added SPLC792A. Added some defines to reduce memory footprint (LCD_TWO_CTRL, LCD_CONTRAST, LCD_UTF8_FONT). Added UTF8_2_LCD() decode for Cyrilic font (By Andriy Ribalko). Added setFont() method (for SSD1803A, US2066, ST7070).

Background

The LCD driver HD44780 is designed for 2 rows of max 40 chars. Note that it needs some support segment drivers to control that maximum number of chars, without those external drivers the device can only display 2x8 chars using its own 16 common drivers and 40 segment drivers.

/media/uploads/wim/2line-2.jpg

The default addressing scheme is as follows:

The address for the first char on the first line is 0x00. The address for the first char on the second line is 0x40. Four line displays are generally created by splitting the two line display and arranging the two parts above each other. For example 2x40 is split in 2 parts of 2x20 and arranged as 4x20. The addresses for the 3rd and 4th line just continue where the split was made:

  • The address for the first char on the first line is 0x00, the last char is 0x13.
  • The address for the first char on the second line is 0x40, the last char is 0x53.
  • The address for the first char on the third line is 0x14, the last char is 0x27.
  • The address for the first char on the fourth line is 0x54, the last char is 0x67.

The original TextLCD lib uses the address(column,row) method to return the memory address. However, the method adds 0x80 to the returned addressvalue to include the 'set display datamemory address' command. This is rather confusing when you try to make sense of the actual address. See discussion here.

The enhanced library provides the getAddress(column,row) method to return the correct address. The original method is still provided for compatibility reasons.

TextLCD has been extended with additional LCDTypes for 3 or 4 line displays that are supported by some controllers (eg PCF211X, KS0078, SSD1803). These LCDTypes use a different addressing scheme and are identified by letter 'D' added to the LCDtype enumerator. The addressing scheme for such a 12x4 display is:

  • The address for the first char on the first line is 0x00, the last char is 0x0B.
  • The address for the first char on the second line is 0x20, the last char is 0x2B.
  • The address for the first char on the third line is 0x40, the last char is 0x4B.
  • The address for the first char on the fourth line is 0x60, the last char is 0x6B.

These 3 line displays are configured as 4 line displays where last or first line is not shown. This mode is selected by choosing LCDType 12x3D or 12x3D1 respectively.

The addressing scheme for the 24x4 display is similar in the sense that the address of the last character on first line is 0x17, for the second line it is 0x37 etc.

There is yet another format for 3 line displays in which the first half of the third line is actually a continuation of the first line and second half of the third line is a continuation of the second line. TextLCD has been extended to support this type. These LCDTypes use a different addressing scheme and are identified by letter 'F' (eg LCDType 16x3F, which is actually a 24x2).

TextLCD has also been extended with additional LCDTypes for 3 line displays supported by the ST7036 controller. This LCDType use a different addressing scheme which is identified by letter 'G' added to the LCDtype enumerator. The addressing scheme for such a 16x3 display is:

  • The address for the first char on the first line is 0x00, the last char is 0x0F.
  • The address for the first char on the second line is 0x10, the last char is 0x1F.
  • The address for the first char on the third line is 0x20, the last char is 0x2F.
  • Note1: The HD44780 is pretty flexible and variations of driverhardware and LCD glass layout may result in differences. The 40x4 line displays actually use two controllers (in 2x40 mode) with separate enable pins.
  • Note2: The HD44780 supports left/right shifting of memory locations (address) wrt displayposition. That changes the address of the char that is shown on a displaylocation. This is pretty confusing and leads to inconsistencies between displaytypes of different numbers of lines or characters/line. The enhanced TextLCD lib therefore does not use this feature.

LCD wiring

The new lib supports several ways of connecting with mbed:

  • Direct connection with mbed pins using a parallel bus (same as original TextLCD)
  • Serial connection using mbed I2C bus and a PCF8574/PCF8574A or MCP23008 portexpander
  • Serial connection using mbed SPI bus and a 74595 shiftregister
  • Serial connection using mbed I2C or SPI bus and a controller that has native support for I2C or SPI (eg ST7032i)

Pinout

The most commonly found connector on LCDs has 14 pins in a single row or as 2x7 pins. Note there may also be 2 additional pins for the backlight. The pinout for the LCD connector is fairly standard. However, exceptions are known. Always check the datasheet and verify by visual or conductivity testing of the GND pin. GND is normally connected to the metal frame around the LCD glass.

The 'standard' pinout has been used in the wiring table examples below. The tables refer to the pinnames of the LPC1768 mbed board and should be adapted to match your target platform.

/media/uploads/wim/_scaled_cbc0802e_rys.jpg

Contrast Voltage

The contrast VO pin may have different behaviour on different displays, so you may need to experiment for your display to see anything. The contrast voltage depends on the type of Liquid Crystal material that is being used for the display, it does not depend on the controller type. Obviously the controller has a certain voltage range it can withstand, but as long as you stay within its specs there will not be a problem. You will see that LCDs suitable for an extended temperature range often use larger and/or negative contrast voltages. The same is true for displays that have higher refresh frequencies, such as graphics displays. The contrast voltage is normally given or referenced against the positive powersupply (so NOT with reference to GND).

For example, the spec sheet for the display may say : LCD Driving Supply voltage Vdd - Vee (so referenced against powersupply Vdd, which is 5V): -0.3...13V. That translates to 5V-0.3V = 4.7V down to 5V-13V= -8V (now referenced against GND). The typical LCD operation voltage for this display is given as 4.2V..6.4V. This is again relative to Vdd so 0.8V..-1.4V relative to GND.

The optimal setting for the contrast voltage depends on the ambient temperature and the viewing angle.

Adjustable contrast can be achieved with a 10k trim-pot in a voltage divider configuration: one side to Vcc, other side to GND, wiper to VO. Adjust until you see a top line of solid rectangles, then back off until they just disappear. Most LCDs should be set at around 0.5 V for best results. The display goes dark or light for the largest part of the potmeter range and does not show much change in contrast anymore. Displays powered at 3V3 instead of 5V may also need a (small) negative voltage at VO. One side of the trimpot is connected to the negative voltage instead of GND in that case.

Standard or fully compatible controllers should at least show a top row of black rectangles as soon as power and contrast voltage are OK even without any other connections or without running any software. However, note that some (almost) compatible controllers remain in powerdown mode and must be fully initialised before showing anything.

Enhanced controllers which have LCD voltage generators onboard will usually support programmable contrast. This means you will not see anything on screen until the settings are correct! Some OLED displays will default to an average contrast.

Supply Voltage

The specsheet of the standard HD44780 says that powersupply should be between 4.5V and 5.5V. These displays should connect pin 2 VCC to 5V as shown in the tables below. The datapins will typically work with the 3V3 logiclevels provided by the processor since the minimum threshold for logic high is 2V2. Powersupply range is often less tolerant. More recent HD44780 compatible controllers may also run on 3V3 powersupply. Check the datasheet for details.

Use decoupling capacitors (100uF parallel to 100nF) on your 5V or 3V3 powersupply for the display, especially when the power is provided my mbed. This will help avoid brief powerline dips which could lead to distorted characters on the display.

Parallel bus wiring

TextLCD pinsmbed LPC1768 pins
p1 GNDp1 0V
p2 VCCp39 5V Vout
p3 VOvia wiper of 10k pot
p4 RSp15
p5 RWp1 0V
p6 Ep16
p7 D0not connected
p8 D1not connected
p9 D2not connected
p10 D3not connected
p11 D4p17
p12 D5p18
p13 D6p19
p14 D7p20

The mbed pins can be supplied in the TextLCD constructor and may be changed. Some LCD displays will work OK with a 3V3 powersupply voltage. You may have to provide a small negative Vo in that case to get good contrast. A simple schematic is here.

Serial I2C bus expander wiring

The advantage of using the I2C bus and a PCF8574/PCF8574A or MCP23008 portexpander is that you save on mbed pins. This is even more true when you use the bus anyhow for other purposes. The small disadvantage that the I2C may be slower than a parallel bus is not a big problem for a slow device like a text display.

TextLCD pinsPCF8574 pinsmbed LPC1768 pins
p1 GNDp8 0Vp1 0V
p2 VCCp16 Vccp39 5V Vout
p3 VOvia wiper of 10k potnot connected
p4 RSp9 P4not connected
p5 RWp8 0Vp1 0V
p6 Ep10 P5not connected
p7 D0not connectednot connected
p8 D1not connectednot connected
p9 D2not connectednot connected
p10 D3not connectednot connected
p11 D4p4 P0not connected
p12 D5p5 P1not connected
p13 D6p6 P2not connected
p14 D7p7 P3not connected
not connectedp11 P6not connected
not connectedp12 P7not connected
not connectedp1 A0 GND or Vccnot connected
not connectedp2 A1 GND or Vccnot connected
not connectedp3 A2 GND or Vccnot connected
not connectedp15 SDAp9 or p28
not connectedp14 SCLp10 or p27

The mbed I2C bus must be supplied in the TextLCD constructor and may be changed (p9,p10) or (p28,p27). Note that you must provide pullup Rs of about 4K7. PCF8574 addresspins (p1,p2,p3) must be strapped to GND or Vcc to set the deviceAddress. That address must also be supplied in the LCDText constructor. The PCF8574 supports 8 different addresses (0x40..0x4E). The PCF8574A is similar but has a different baseaddress (0x70..0x7E). So in total you can connect upto 16 LCDs to one I2C bus!

  • Note1: Several other vendors supply full clones of the PCF8574 (eg Texas Instruments). The lib now also supports the MCP23008 portexpander. This device has some different features and it must be selected by activating the #define MCP23008 in TextLCD_Config.h.
  • Note2: The spare pin D7 on the PCF8574 is available to control the LCD Backlight.
  • Note3: You can change the wiring connections between the PCF8574 pins and the LCD. Just update the appropriate pin mapping definitions in TextLCD_Config.h.
  • Note4: You can roll-your-own PCF8574 interface or try to find one of the ready made modules on ebay. Search for TWI or I2C and LCD. The boards are all based on the same concept, but there are differences: pinmapping between serial port expander pins and LCD controller, slaveaddress hardwired of selectable by jumpers, solderbridges or a switch, support for backlight control, pull-up resistors for SDA/SCL onboard or not present.
  • Note5: Predefined mappings are provided for a DEFAULT version (used in wiring table below) and for several others such as the LCD2004 module from DFROBOT and for a very nice combination of SPI/I2C portexpander by Adafruit. This hardware supports both an I2C expander (MCP23008) and an SPI expander (74595) selectable by a jumper. Some other types with PCF8574 are branded as LCM1602, YFRobot, GY-LCD-V1 etc. The expanders produced by WideHK or Jeelabs use an MCP23008.

Here is a picture with a bunch of serial port expanders for LCDs. The top two (Adafruit and WideHK) have MCP23008 I2C expanders. The others use PCF8574 or PCF8574A I2C expanders.

/media/uploads/wim/backpacks.jpg

Find the following #defines in TextLCD_Config.h to select the appropriate module version.

//Pin Defines for I2C PCF8574/PCF8574A or MCP23008 and SPI 74595 bus expander interfaces
//Different commercially available LCD portexpanders use different wiring conventions.
//LCD and serial portexpanders should be wired accordingly.
//
//Select Serial Port Expander Hardware module (one option only)
#define DEFAULT   1
#define ADAFRUIT  0
#define DFROBOT   0
#define LCM1602   0
#define YWROBOT   0
#define GYLCD     0
#define MJKDZ     0
#define SYDZ      0
#define WIDEHK    0
#define LCDPLUG   0

When the DEFAULT wiring is selected you will also have the additional option to select either the PCF8574 or the MCP23008 expander. The predefined definitions include an option that deals with modules that use inverted logic for backlight control.

Example of a ready made PCF8574 I2C expander (www.mjkdz.com) for LCDs

/media/uploads/wim/_scaled_image2.jpg

Example schematic of homemade I2C expander for LCDs

/media/uploads/wim/_scaled_lcd1602_i2c_sch.png

Serial SPI bus expander wiring

The advantage of using the SPI bus rather than I2C is that the 74595 shiftregister is cheaper than a PCF8574. Disadvantages are that it needs more pins (MOSI, SCLK and CS). You also need a separate CS for every new device since SPI does not support a slaveAddress.

TextLCD pins74595 pinsmbed LPC1768 pins
p1 GNDp8 0Vp1 0V
p2 VCCp16 Vccp39 5V Vout
p3 VOvia wiper of 10k potnot connected
p4 RSp4 Q4not connected
p5 RWp8 0Vp1 0V
p6 Ep5 Q5not connected
p7 D0not connectednot connected
p8 D1not connectednot connected
p9 D2not connectednot connected
p10 D3not connectednot connected
p11 D4p15 Q0not connected
p12 D5p1 Q1not connected
p13 D6p2 Q2not connected
p14 D7p3 Q3not connected
not connectedp10 nMR Vccp39 5V
not connectedp11 SHCPp7 or p13 SCK
not connectedp12 STCPp8 CS
not connectedp14 DSp5 or p11 MOSI
not connectedp13 nOE GNDp1 0V

The mbed SPI bus must be supplied in the TextLCD constructor and may be changed (p5,NC,p7) or (p11,NC,p13). You must also provide a CS pin. A simple schematic is here.

  • Note1: The 74HC595 should work on 3V3, but 5V is the prefered supplyvoltage
  • Note2: The spare pin D7 on the 74HC595 is available to control the LCD Backlight.
  • Note3: You can change the connections between the 74595 pins and the LCD. Just update the appropriate pin definitions in TextLCD_Config.h

Native Serial I2C or SPI bus wiring example for LPC1768 mbed

The SPI port on controllers with native '4 wire' SPI support needs MOSI, SCK, CS and RS pins on the mbed side. Optionally you may connect a Backlight control pin (BL). The default controller type is ST7032i running on 3V3 and using the internal voltage booster. Some devices also use a native '3 wire' SPI interface which needs MOSI, SCK and CS on the mbed side. The RS bit (to select between Data and Command) is transmitted as bit 9 of the SPI communication. This mode is used by AIP31068 and other controllers. The enhanced TextLCD lib provides code for this device, but note that the current mbed libs only support 9 bit SPI messages for the NXP platforms. To make things even more complicated, some controllers (eg WS0010) use a 10 bit 3 wire SPI mode. Again, the code is included in the lib, but will only work on the NXP mbed. Finally there are some controllers (eg SSD1803) that use a 3 wire SPI interface to send a 24 bit message. The RS and RW bit are encoded in the message. This message is broken down into 3 messages of 8 bit each, which means all mbeds can support it. The ST7070 and some other devices also use a '3 wire, 8 bit' SPI interface which needs MOSI, SCK and CS on the mbed side. There is no RS bit and Data exchange is started by first sending a special Command followed by a number of databytes. This mode is supported but is not very efficient wrt communication time.

The I2C port on controllers with native I2C support needs SCL and SDA pins on the mbed side. Optionally you may connect a Backlight control pin (BL). The default controller type is ST7032i running on 3V3 and using the internal voltage booster. Only one slaveaddress is supported for the ST7032i. That means you can connect only one device to the I2C bus. Some other controllers support either 2 (eg PCf21xx, SSD1803A) or up to 4 slaveaddresses (eg ST7036, AC780). Note that some I2C controllers dont support the I2C Ack. This applies sometimes for Chip-on-Glass (COG) devices due to the electrical characteristics of that technology. The #define LCD_ACK may be used to modify TextLCD lib so that these devices can be used with the mbed I2C lib.

Wiring for 40x4 LCDs

The 40x4 LCDs are different from the regular types because they have two controllers. In fact this is a combination of two 40x2 displays. They have a different pinout with two enable lines (e1 and e2). The example below shows how to connect it using the SPI 74595 shiftregister. Note that currently LCD40x4 is NOT supported by any of the native SPI or I2C controllers.

TextLCD pins74595 pinsmbed LPC1768 pins
p1 D7p3 Q3not connected
p2 D6p2 Q2not connected
p3 D5p1 Q1not connected
p4 D4p15 Q0not connected
p5 D3not connectednot connected
p6 D2not connectednot connected
p7 D1not connectednot connected
p8 D0not connectednot connected
p9 E1p5 Q5not connected
p10 RWp8 0Vp1 0V
p11 RSp4 Q4not connected
p12 VOvia wiper of 10k potnot connected
p13 GNDp8 0Vp1 0V
p14 VCCp16 Vccp39 5V Vout
p15 E2p6 Q6not connected
p16 NC/Veenot connectednot connected
not connectedp10 nMR Vccp39 5V
not connectedp11 SHCPp7 or p13 SCK
not connectedp12 STCPp8 CS
not connectedp14 DSp5 or p11 MOSI
not connectedp13 nOE GNDp1 0V

The mbed SPI bus must be supplied in the TextLCD constructor and may be changed (p5,NC,p7) or (p11,NC,p13). You must also provide a CS pin.

  • Note1: The 74HC595 should work on 3V3, but 5V is the preferred supplyvoltage
  • Note2: The spare pin D7 on the portexpander is available to control the LCD Backlight.
  • Note3: You can change the connections between the 74595 pins and the LCD. Just update the appropriate pin definitions in TextLCD_Config.h

The display can also be interfaced to the I2C portexpander or directly to mbed pins using an additional pin for E2.

TextLCD pinsPCF8574 pinsmbed LPC1768 pins
p1 D7p7 P3not connected
p2 D6p6 P2not connected
p3 D5p5 P1not connected
p4 D4p4 P0not connected
p5 D3not connectednot connected
p6 D2not connectednot connected
p7 D1not connectednot connected
p8 D0not connectednot connected
p9 E1p10 P5not connected
p10 RWp8 0Vp1 0V
p11 RSp9 P4not connected
p12 VOvia wiper of 10k potnot connected
p13 GNDp8 0Vp1 0V
p14 VCCp16 Vccp39 5V Vout
p15 E2p11 P6not connected
p16 NC/Veenot connectednot connected
not connectedp12 P7not connected
not connectedp1 A0 GND or Vccnot connected
not connectedp2 A1 GND or Vccnot connected
not connectedp3 A2 GND or Vccnot connected
not connectedp15 SDAp9 or p28
not connectedp14 SCLp10 or p27

Text LCD Enhanced Library

Import libraryTextLCD

Updated for more display types. Fixed memoryaddress confusion in address() method. Added new getAddress() method. Added support for UDCs, Backlight control and other features such as control through I2C and SPI port expanders and controllers with native I2C and SPI interfaces. Refactored to fix issue with pins that are default declared as NC.

Example Code

// Hello World! for the TextLCD

#include "mbed.h"
#include "TextLCD.h"

// Host PC Communication channels
Serial pc(USBTX, USBRX); // tx, rx

// I2C Communication
I2C i2c_lcd(p28,p27); // SDA, SCL

// SPI Communication
SPI spi_lcd(p5, NC, p7); // MOSI, MISO, SCLK

//4-bit bus
//TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD40x2); // RS, E, D4-D7
//TextLCD lcd(p15, p16, p17, p18, p19, p20);  // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=HD44780

//I2C Portexpander PCF8574
TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD20x4); // I2C bus, PCF8574 Slaveaddress, LCD Type
//TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD16x2, TextLCD::WS0010); // I2C bus, PCF8574 addr, LCD Type, Ctrl Type

//I2C Portexpander MCP23008
//TextLCD_I2C lcd(&i2c_lcd, MCP23008_SA0, TextLCD::LCD16x3G, TextLCD::ST7036_3V3); // I2C bus, MCP23008 Slaveaddress, LCD Type, LCDTCtrl=ST7036

//SPI Portexpander SN74595
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD24x4D; TextLCD::KS0078); // SPI bus, CS pin, LCD Type
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD40x2); // SPI bus, CS pin, LCD Type
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD40x4); // SPI bus, CS pin, LCD Type

//Native I2C
//TextLCD_I2C_N lcd(&i2c_lcd, ST7032_SA, TextLCD::LCD16x2, NC, TextLCD::ST7032_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=ST7032_3V3  
//TextLCD_I2C_N lcd(&i2c_lcd, PCF2116_SA0, TextLCD::LCD12x4D, NC, TextLCD::PCF2116_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=PCF2116_3V3  
//TextLCD_I2C_N lcd(&i2c_lcd, PCF2116_SA0, TextLCD::LCD24x2, NC, TextLCD::PCF2116_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=PCF2116_3V3  
//TextLCD_I2C_N lcd(&i2c_lcd, SSD1803_SA1, TextLCD::LCD20x4D, NC, TextLCD::SSD1803_3V3); // I2C bus, slaveaddress, LCDType=LCD16x2, BL=NC, LCDTCtrl=SSD1803A 

//Native SPI 4 wire, 8 bits
//TextLCD_SPI_N lcd(&spi_lcd, p8, p9);    // SPI bus, CS pin, RS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=ST7032_3V3   

//Native SPI 3 wire, 10bits
//TextLCD_SPI_N_3_10 lcd(&spi_lcd, p8, TextLCD::LCD16x2, NC, TextLCD::WS0010); // SPI bus, CS, LCDType=LCD16x2, BL=NC, LCDTCtrl=WS0010
//TextLCD_SPI_N lcd(&spi_lcd, p8, p9, TextLCD::LCD16x3G, NC, TextLCD::ST7036_3V3); // SPI bus, CS pin, RS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=ST7036

//Native SPI 3 wire, 24 bits, SSD1803A
//TextLCD_SPI_N_3_24 lcd(&spi_lcd, p8, TextLCD::LCD20x4D, NC, TextLCD::SSD1803_3V3); // SPI bus, CS pin, LCDType=LCD20x4, BL=NC, LCDTCtrl=SSD1803A

int main() {
    pc.printf("LCD Test. Columns=%d, Rows=%d\n\r", lcd.columns(), lcd.rows());
    
    for (int row=0; row<lcd.rows(); row++) {
      int col=0;
      
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
//      lcd.putc('-');
      lcd.putc('0' + row);      
      
      for (col=1; col<lcd.columns()-1; col++) {    
        lcd.putc('*');
      }

      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
      lcd.putc('+');       
    }    
    
// Show cursor as blinking character
    lcd.setCursor(TextLCD::CurOff_BlkOn);

// Set and show user defined characters. A maximum of 8 UDCs are supported by the HD44780.
// They are defined by a 5x7 bitpattern. 
    lcd.setUDC(0, (char *) udc_0);  // Show |>
    lcd.putc(0);    
    lcd.setUDC(1, (char *) udc_1);  // Show <|
    lcd.putc(1);    
    lcd.setUDC(2, (char *) udc_2);
    lcd.putc(2);    
    lcd.setUDC(3, (char *) udc_3);
    lcd.putc(3);    
    lcd.setUDC(4, (char *) udc_4);
    lcd.putc(4);    
    lcd.setUDC(5, (char *) udc_5);
    lcd.putc(5);    
    lcd.setUDC(6, (char *) udc_6);
    lcd.putc(6);    
    lcd.setUDC(7, (char *) udc_7);
    lcd.putc(7);   
}

The terminal will print the actual memory addresses like this:

LCD Test. Columns=20, Rows=4

MemAddr(Col=0, Row=0)=0x00

MemAddr(Col=19, Row=0)=0x13

MemAddr(Col=0, Row=1)=0x40

MemAddr(Col=19, Row=1)=0x53

MemAddr(Col=0, Row=2)=0x14

MemAddr(Col=19, Row=2)=0x27

MemAddr(Col=0, Row=3)=0x54

MemAddr(Col=19, Row=3)=0x67

User Defined Characters (UDC)

The HD44780 supports 8 different custom characters. They are shown by printing a charactervalue between 0 and 7. So rather than lcd.putc(‘a’) to display an ‘a’ you would call lcd.putc(0) to show the first user defined character. The UDC will display at the current cursorlocation. Any displaylocation where you have written a 0 will show that same UDC.

Obviously you first need to store a bitpattern before using this new UDC. All characters on the LCD consist of a 5 (horizontal) x 7 (vertical) pixel font. You can easily recognise that outline shape on the display by inspecting any character. There is in fact an 8th row at the bottom, but that is reserved for the cursor.

You define the 5x7 pattern by writing 8 bytes to 8 sequential UDC memory locations inside the LCD controller. The initial address for the UDC memory depends on which of the 8 available UDCs you want to define. The stored bit pattern will show on the display from top to bottom. So the first byte you store will later show up as the top row:

bit4 bit3 bit2 bit1 bit0.

Note that b7-b5 are don’t care for the UDC pattern since the font is only 5 pixels horizontal.

The second byte shows up as the next row of pixels etc.

The 8th byte should be all 0’s to avoid problems with the cursor.

Example from this site

/media/uploads/wim/_scaled_udc_map.jpg

The method lcd.setUDC(unsigned char c, char *udc_data) makes UDC storage more easy. The first parameter selects the UDC you want to define (should be between 0 and 7 for default HD44780). The second param is a pointer to an array of 8 bytes that holds the pattern. Some sample patterns are defined in TextLCD_UDC.inc. Note that most of them are commented out to save memory space. Enable them as needed or add your own.

const char udc_Bat_Hi[] = {0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00};  // Battery Full

lcd.setUDC(0, (char *) udc_Bat_Hi);  // Define Bat High pattern for UDC index number 0
lcd.putc(0);                                        // Display the Bat High pattern by printing character value 0

Decode the above example UDC by drawing an 8x8 grid and filling each cell that represents a 1 in the bitpattern above. You will see the ''battery full'' symbol appear.

You can redefine the UDCs at any time, but note that whenever you change the UDC pattern for an index all occurrences of that index showing on the display will instantly change to the new pattern. Redefining the UDC at short regular intervals allows some simple animation on the display.

Example User Defined Characters shown on display

/media/uploads/wim/_scaled_img_2645_-_copy.jpg

Note that b7-b5 are don’t care for the UDC pattern since the font is only 5 pixels horizontal. However, some enhanced LCD controllers (eg SDD1803A) use b7-b6 to enable blinking UDCs. This feature is supported by the lib. See setUDCBlink() method. Some controllers also support 16 instead of the default 8 UDCs. They will occupy character codes 0..15. The original HD44780 supports only 8 UDCs and mirrors the character range 8..15 onto 0..7.

Icons

The original HD44780 does not support Icons. Later clones had an additional common driver pin and they could show a row of Icons (e.g. special symbols). Some devices (eg PCF2103) used a number of the available UDC memory locations to store the Icon bits. More recent devices (eg KS0073) offer a special memory of 16 bytes dedicated to Icons. The memory can be accessed through extended instructions. Blinking icons are enabled when a specific controlbit (BE) is set. The blinking pixels in the icons can be controlled by setting additional bits in the icon bitpattern. Icons are defined by a byte bitpattern. The P0..P5 form the Icon pattern for KS0073, and P0..P4 for KS0078

IndexP7P6P5P4P3P2P1P0
0B1B0001110
1B1B0110001
.............................
15B1B0110001

Bit 6 and Bit 7 in the pattern will control the blinking mode when Blink is enabled through BE.

B1B0Mode
00No Blinking for this icon row
01Enabled pixels in P5 will blink
1xEnabled pixels in P0..P5 will blink

Note: the PCF2103 and PCF2113 use UDCs to set Icons

3 x 8 rows x 5 bits = 120 bits Icons for Normal pattern (UDC 0..2)
3 x 8 rows x 5 bits = 120 bits Icons for Blink pattern (UDC 4..6)

Note: the PCF2119 uses UDCs to set Icons

4 x 8 rows x 5 bits = 160 bits Icons for Normal pattern (UDC 0..3)
4 x 8 rows x 5 bits = 160 bits Icons for Blink pattern (UDC 4..7)

The TextLCD lib now supports methods setIcon() and clrIcon() to access Icon functions for several controllers. The mapping between the individual bits in the memory and the Icon on the screen depends on the hardware and glass patterns. These functions therefore need to be developed for each specific display.

Fontsets

Some controllers are available with different ROM fontsets. Examples are Asian, Cyrillic, special graphics symbols etc. The fontset is usually encoded in the controller type designation (eg PCF2119x). The default setting of the library assumes the regular ASCII compatible character set when using prinft() calls. Some conversion functions are available for different fontsets to make sure that at least ASCII text shows up readable in case of the PCF2119C and PCF2119R font. This conversion is provided by ASCII_2_LCD() method and it also works for several other alternative fonts, but does not cover all types. The conversion is not used in default setting to save some processing time. Activate the conversion when needed through the option in TextLCD_config.h

//Select option to activate default fonttable or alternatively use conversion for specific controller versions (eg PCF2116C, PCF2119R, SSD1803A, US2066)
#define LCD_DEF_FONT   1           //Default HD44780 font
//#define LCD_C_FONT     1           //PCF21xxC font
//#define LCD_R_FONT     1           //PCF21xxR font
//#define LCD_UTF8_FONT  1           /* Enable UTF8 Support (eg Cyrillic tables) -0.4K codesize*/
//#define LCD_UTF8_CYR_B 1           /*  Select specific UTF8 Cyrillic table (SSD1803A ROM_B)              */

Some controllers support multiple tables that can only be selected by logic levels on a few pins. Some controllers (eg SSD1803A, US2066, ST7070) also support runtime fontable switching through a specific instruction. The setFont() method can be used on these controllers. The selected font must be provided as parameter. See enum LCDFont for options.

The lib now supports extended characters encoded as UTF-8 2-byte characters. This feature allows for example the use of Cyrillic charactersets for the Russian language. The method UTF8_2_LCD() converts the 2-byte codes into a 1-byte reference to the LCD controllers charactermap. The mapping depends on the specific fontset of the controller (some controllers support multiple fontsets, you have to switch fonts before it works). Original code was provided by Andriy and modified by WH.

Activate the UTF decoding for Cyrillic by selecting the following setting in TextLCD_config.h

//Select option to activate default fonttable or alternatively use conversion for specific controller versions (eg PCF2116C, PCF2119R, SSD1803, US2066)
//#define LCD_DEF_FONT   1           //Default HD44780 font
//#define LCD_C_FONT     1           //PCF21xxC font
//#define LCD_R_FONT     1           //PCF21xxR font
#define LCD_UTF8_FONT  1           /* Enable UTF8 Support (eg Cyrillic tables) -0.4K codesize*/
#define LCD_UTF8_CYR_B 1           /*  Select specific UTF8 Cyrillic table (SSD1803A ROM_B)              */

Note: The UTF8 decoding table for a specific controller is defined and selected in file TextLCD_UTF8.inc Only one table is active at any time. The table is accessed in the UTF_2_LCD() method through

#define UTF_FIRST, UTF_LAST, UTF_SEQ_REC_FIRST, UTF_SEQ_REC_LAST and 
#define UTF_SEQ_RECODE and UTF_RND_RECODE

Modify the table for your language needs or specific controller. Please let me know so it can be included in a next release.

// SSD1803, Text Cyrillic UTF-8
lcd.setFont(TextLCD::Font_RB);    // Select the correct fonttable

lcd.locate(0, 0);
//               01234567890123456789
lcd.printf("Hello world!\n");
lcd.printf("Привет мужики!\n");                     // UTF8 multibyte code (IGNORE COMPILER WARNINGS)
lcd.printf(" SSD1803A UTF8 code\n");                     
lcd.printf(" ROM_B Cyrillic");    

See picture below for an example of Cyrillic font on an SSD1803A. The conversion tables may not be fully correct since the SSD1803 supports only a subset of the upper- and lowercase Cyrillic font. Please improve the table for the SSD1803A if you speak Russian and let me know your fixes so they can be included in a next release.

/media/uploads/wim/ssd1803_cyrillic.jpg

Options and memory footprint

Some of the additional features of this library over the original TextLCD lib may be switched off when not needed to reduce memory footprint. Select the desired options in the TextLCD_config.h file (multiple options allowed). Default all options are activated except for setFont().

#define LCD_UDC          1           /* Enable predefined UDC example*/
#define LCD_PRINTF     1           /* Enable Stream implementation */
#define LCD_ICON         1           /* Enable Icon implementation -2.0K codesize*/
#define LCD_ORIENT    1           /* Enable Orientation switch implementation -0.9K codesize*/
#define LCD_BIGFONT  1           /* Enable Big Font implementation -0.6K codesize */
#define LCD_INVERT     1           /* Enable display Invert implementation -0.5K codesize*/
#define LCD_POWER    1           /* Enable Power control implementation -0.1K codesize*/
#define LCD_BLINK        1           /* Enable UDC and Icon Blink control implementation -0.8K codesize*/
#define LCD_CONTRAST   1           /* Enable Contrast control implementation -0.9K codesize*/
#define LCD_TWO_CTRL   1           /* Enable LCD40x4 (two controller) implementation -0.1K codesize*/
#define LCD_FONTSEL    0           /* Enable runtime font select implementation using setFont -0.9K codesize*/

Compatible or Enhanced LCD Controllers

There are many HD44780 compatible LCD controllers around (e.g. KS0066, SPLC780, SED1278, LC7985A), which will work fine with this library. There are also controllers available that are compatible while providing additional features like an increased number of segment drivers for more characters or internal LCD contrast voltage generators (e.g. KS0073, KS0078, ST7036, SSD1803A and WS0010, US2066/SSD1311 (OLED drivers)). Some of these controllers will work fine with the library without further software changes since they just remove the need for some supporting hardware that an HD44780 based display would have used. However, some new features require additional code and some displays won't even work without these specific new set-up instructions. The library has been extended further to support some of the features provided by alternative controllers (i.e. ST7036, and WS0010 OLED driver with internal DC/DC converters). The additional software is found in the init() method and a new parameter in the constructor is needed to identify the alternative controllertype and activate the new code. Support for some controllers with native SPI or I2C interfaces is now available and will be further improved and extended. Support for setting LCD Contrast on controllers which provide that option has also been added. Some controllers (eg US2066/SSD1311, SSD1803A) also support changing display orientation. This may be used to flip between top and bottom view when the display is turned upside down. This feature is controlled through the setOrient() method. Icons and blinking features are supported as explained above. Double height lines are available on some controllers and may be selected by the setBigFont() method. However, this doesn't look great on most displays due to the small gap between lines...

Examples

Some results are shown here:

LCD8x2B (actually 16x1, using SPI expander)

/media/uploads/wim/_scaled_img_2662.jpg

LCD12x1, (actually 16x2, Native I2C, ST7032i controller, with icons used for 7 segment digits, salvaged from a baby monitor)

/media/uploads/wim/img_3659_-_copy.jpg

LCD12x2, (Native I2C, PCF2113 controller, with icons, Chip-on-PCB from stone-age cellphone)

/media/uploads/wim/img_3355.jpg

LCD12x3D1, (Native I2C, PCF2116 controller, Chip-on-Glass (COG))

/media/uploads/wim/img_3342.jpg

LCD12x3D1, (Native I2C (No Ack), PCF2116 like controller, Chip-on-Glass (COG))

/media/uploads/wim/img_3362.jpg

LCD12x4D, (Native SPI, KS0073 controller, with icons, salvaged from a Crouzet PLC)

/media/uploads/wim/img_3955.jpg

LCD16x1C (actually 8x2, using SPI expander, Model Data Image CM160104)

/media/uploads/wim/_scaled_img_2659.jpg

LCD16x2, (SYDZ PCF8574A I2C portexpander, Model Powertip PC1602LRU)

/media/uploads/wim/powertip_pc1602lru.jpg

LCD16x2, (Native SPI, ST7032i controller, Model EastRising ERC1602FS-4, Buydisplay.com, ebay)

/media/uploads/wim/img_3339.jpg

LCD16x2, (Native I2C, ST7032i controller, Model EastRising ERC1602FS-4, Buydisplay.com, ebay)

/media/uploads/wim/img_3340.jpg

LCD16x2, (Native I2C, ST7032i controller, White on Blue display with jumpers to reverse Row and Column order, Model JLX1602G-390, Aliexpress)

/media/uploads/wim/jlx1602g-390_small_RuRCHEG.jpg

LCD16x2, (Native I2C, AC780 controller, White on Blue display, Model JLX1602A-4, ebay)

/media/uploads/wim/img_3402.jpg

LCD16x2, (Native I2C, AIP31068 controller, Model JHD1214M1, ebay)

/media/uploads/wim/img_3356.jpg

LCD16x2, (Native I2C, PCF2119R controller, Model Batron BT21605V, 5mm (alternate Fontset), ebay)

/media/uploads/wim/bt21605j_i2c_pcf2119r.jpg

LCD16x2, (Native SPI, ST7070 controller, white on blue, Model EastRising ERM1602K, Buydisplay.com, ebay)

/media/uploads/wim/st7070_spi.jpg

LCD16x2, (OLED, I2C portexpander, WS0010 controller, Model Winstar EH001602E, ebay)

/media/uploads/wim/img_3359.jpg

LCD16x2 (Vacuum Fluorescent Display (VFD) Noritake Itron CU16025 with controller that is compatible to HD44780, using SPI expander)

/media/uploads/wim/_scaled_img_2668.jpg

LCD16x2 (Big (Optrex PWB16230), normal (SED1278 Controller and small (Batron BT21603V, 3mm), using SYDZ I2C portexpander)

/media/uploads/wim/optrex_pwb16230_-_sed1278_-_bt21603v.jpg

LCD16x3F (actually 24x2, custom display, using I2C expander MCP23008)

/media/uploads/wim/img_3375.jpg

LCD16x3G (ST7036 controller in native SPI mode, Model Electronic Assembly DOGM163W-A, Reichelt.nl)

/media/uploads/wim/st7036_img_3378.jpg

LCD16x4

/media/uploads/wim/_scaled_img_2640.jpg

LCD20x2

/media/uploads/wim/_scaled_img_2636.jpg

LCD20x2 (US2066/SSD1311 OLED Native SPI, Model EastRising ER-OLED2002-4, Buydisplay.com, ebay) /media/uploads/wim/img_3388.jpg

LCD20x2 (US2066/SSD1311 OLED (bottom view)) /media/uploads/wim/img_3392.jpg

LCD20x4 (I2C portexpander interface MCP23008, Model DataImage CM2020-SLYT)

/media/uploads/wim/_scaled_img_2642.jpg

LCD20x4 (I2C portexpander interface PCF8574, Model Optrex DMC2034)

/media/uploads/wim/_scaled_img_2649.jpg

LCD20x4 Crazy Big Character Display (I2C portexpander interface PCF8574, Model Batron BT42012AV, 12mm)

/media/uploads/wim/img_3653.jpg

LCD20x4D (SYDZ I2C portexpander interface PCF8574A, HD66712 Controller, Model Batron BT42003AV, 3mm)

/media/uploads/wim/batron_bt42003av_3mm.jpg

LCD20x4D (SSD1803A controller in native I2C mode, Model Electronic Assembly DOGM204N-A, Reichelt.nl)

/media/uploads/wim/ssd1803a_img_3381.jpg

LCD20x4D (US2066/SSD1311 OLED 4Bit bus, Model Newhaven, tested by hs)

/media/uploads/wim/us2066_20x4d.jpg

LCD24x2

/media/uploads/wim/_scaled_img_2638.jpg

LCD24x2, (Native I2C, PCF2116 controller)

/media/uploads/wim/img_3352.jpg

LCD24x2 (Icons, KS0073 controller, Model Samsung UC24214)

/media/uploads/wim/ks0073_icons.jpg

LCD24x4D (KS0078 controller, Model Agena AA24411)

/media/uploads/wim/_scaled_img_2646.jpg

LCD32x2 (i2C port expander, HD44780 controller, Model Optrex DMC32239A)

/media/uploads/wim/img_3639.jpg

LCD40x2 (Model Powertip PC4002BRU)

/media/uploads/wim/_scaled_img_2637.jpg

LCD40x4 (2 controllers, SPI shiftregister interface, Model Winstar WH4004A)

/media/uploads/wim/_scaled_img_2655.jpg

References


43 comments on TextLCD Enhanced:

08 Sep 2015

Great work!, Many thanks for sharing this information.

02 May 2016

Although most displays use a common pin-out I understand that there are at least two different pin-out mappings for the 4*40 display (the one with two controllers).

I do not know the details of the differences though, only that I have encountered equipment using an adaptor PCB to operate with a substitute display.

15 May 2016

Hello. Have you runned this with mbed-RTOS? Only thing that show up after board startup is cursor at (0,0). Also, other threads are failing too.

19 Jun 2016

@Andrew Bentley: Thx

@Oliver Broad: It is likely that there are some non-standard displays out there. The datasheets of 4x40 displays that I have seen are all compatible with the table above. However, a google search resulted in this example of a differing pinout. I recommend that you always search for the datasheet of a display or that you perform some reverse engineering to confirm pinouts.

@Michal Wisniewski: I have not tested or used mbed-RTOS. However, there is information that RTOS and printf dont work together unless you modify the stacksize of the thread. See here.

22 Aug 2016

Thanks to all those who have worked on this. Once I finally put the pullup resistors on my YwRobot/nucleo446 it has been awesome.

Thanks again

31 Mar 2017

Hello Wim, I am trying to use and 1602 OLED/US2066 display, and got stuck. Could you give me a hand by posting an example code of "hello world" targeted US2066, 4-bit interface ? Thanks in advance

H.M.

31 Mar 2017

and one of the problems I have is what to do with thoese extra pins of US2066 modules that HD44780 ones do not have, like D/C, R/W . Thanks again H.M

04 Apr 2017

Hi HM

The US2066 supports several interface modes: 4bit, 8 bit parallel, I2C and SPI. You have to wire the controller differently for each mode and pull-up or pull-down the configuration pins BS0, BS1, BS2 to select the correct mode. Note that several pins change function depending on the config settings. The datasheet provides the detailed wiring info. The US2066 testboard that I show in the picture above has some jumpers to select all supported interface modes.

The 4bit parallel mode needs

  • /RES pull high, but also connect a 100n capacitor to GND to get a power-on reset
  • /CS pull low
  • RW (=WR) pull low
  • E (=RD) connected to an mbed pin for E,
  • RS (=D/C) connected to an mbed pin for RS,
  • D4,D5,D6,D7 connected to an mbed pin for the datalines
  • D0,D1,D2,D3 pull low

You also need to set the configuration pins for the 4bit parallel mode:

  • BS0 pull high
  • BS1 pull low
  • BS2 pull high

Use a 4K7 resistor to pull a pin up or down.

Note that Vcc should be 3V3

When the config pins are set correctly you can declare the display for 4bit mode like this:

TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2, NC, NC, TextLCD::US2066_3V3);  // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=US2066

Note that the serial ports require the least amount of mbed pins. When the config pins are set correctly you can declare it for serial mode like this:

//US2066
TextLCD_I2C_N lcd(&i2c_lcd, US2066_SA0, TextLCD::LCD16x2, NC, TextLCD::US2066_3V3); // I2C bus, slaveaddress, LCDType=LCD16x2, BL=NC, LCDTCtrl=US2066

//TextLCD_SPI_N_3_24 lcd(&spi_lcd, p8, TextLCD::LCD16x2, NC, TextLCD::US2066_3V3); // SPI bus, CS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=US2066
06 Apr 2017

Hi Wim, Thanks so much for the detailed help. I hooked up the OLED ( PN# NHD-0216CW-AY3) per your instruction, and the display lighted up and started working for the first time !!! Only a little problem, the first 4 letters got chopped off (see the photo). At this moment, I don't know what has caused the problem. My test code goes like this ------------- Hello World! for the TextLCD

  1. include "mbed.h"
  2. include "TextLCD.h"

TextLCD lcd(D7, D8, D10, D11, D12, D13, TextLCD::LCD16x2, NC, NC, TextLCD::US2066_3V3); RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=US2066

int main() { lcd.printf("Hello Jorge! \n"); } ---------- Thanks again H.M.

06 Apr 2017

/media/uploads/mahengjie/photo3.jpg it should say "Hello Jorge!"

06 Apr 2017

Now I recall that you might have said in somewhere that currently the library supports only 20x4 of US2066 based OLED panels, while I am here using a 16x2. Could that be the problem ? - HM

06 Apr 2017

and no luck with I2C. I hardwired B02 = 2'b010, pulled up D/C (SA0), connected SDA, SCL line. I declared the port like this

I2C i2c_lcd(D12,D13); SDA, SCL, TextLCD_I2C_N lcd(&i2c_lcd, US2066_SA0, TextLCD::LCD16x2, NC, TextLCD::US2066_3V3);

I am wondering if I did the port declaration right. HM

08 Apr 2017

Hi HM. Good to see there is progress!

Please use the <<code>> and <</code>> tags on separate lines around posted code to keep it readable.

The US2066 is a driver for 20x4 characters. When used for a 16x2 LED panel it means that 4 characters will have to be dropped on either the left or right side. In your case the OLED panel wiring and TextLCD lib default setting seems to result in losing the characters on the left hand side where TextLCD expects the line to start at cursorlocation 0. The easiest way to fix the problem is probably by 'flipping' the driver interface lines. That is done by the using the 'top' and 'bottom' view as they call it in the datasheet (see my example picture above). Add the following command to your code:

lcd.setOrient(TextLCD::Bottom);
//lcd.setOrient(TextLCD::Top);                      

The display orientation will change, but all characters should be visible (Note that I dont have any 16 characters or 4 line displays with the US2066 for testing all possible combinations).

The I2C mode needs:

  • /RES pull high, but also connect a 100n capacitor to GND to get a power-on reset
  • /CS pull low
  • RW (=WR) pull low
  • E (=RD) pull low
  • RS (=D/C) pull low (to select I2C slave address US2066_SA0)
  • D4,D5,D6,D7 pull low
  • D3 pull low
  • D0 connect to mbed pin SCL, use a pull-up
  • D1 and D2 connected to mbed pin SDA, use a pull-up

You also need to set the configuration pins for the I2C mode:

  • BS0 pull low
  • BS1 pull high
  • BS2 pull low

Use a 4K7 resistor to pull a pin up or down.

Note that Vcc should be 3V3

Note that you need to use one of the supported I2C pins for your platform. In the your case for the WIZwiki that could be D14 for SDA and D15 for SCL.

I2C i2c_lcd(D14, D15); //SDA, SCL pins for your mbed platform

TextLCD_I2C_N lcd(&i2c_lcd, US2066_SA0, TextLCD::LCD16x2, NC, TextLCD::US2066_3V3);

int main() {
  lcd.setOrient(TextLCD::Bottom);

...
19 Apr 2017

Wim, Thanks so much again. Without your help, I would never be able to figure it out by myself, as the datasheet from Newhaven Display does not have this information on setting the view orientation. The funny thing is that if I set the "bottom view", by adding the code "lcd.setOrient(TextLCD::Bottom)" , the text image is not flipped, but is actually displayed in the correct orientation instead, with the OLED module is positioned with the header connector on top as suggested in the datasheet, see the first photo. However, if I set it to "Top", or do not set the orientation at all, the text image will be displayed upside down, and with the first 4 characters chopped (see the 2nd photo). Wondering if it is because the default orientation of this Newhaven Display OLED is reversed with that of TextLCD Library. /media/uploads/mahengjie/us2066bottomview.jpg /media/uploads/mahengjie/us2066topview.jpg

19 Apr 2017

The above was done with 4-bit parallel interface. The I2C next.

20 Apr 2017

The controller has column drivers for 20 characters although only 16 character drivers are connected on your display. The display manufacturer can connect the controller outputs to the LEDs as he pleases: either connect 1-16 or 4-20. He can also choose whether it is more convenient to wire the LED panel left to right or the other way around. The memory address where the 16 characters on a line are stored stays the same, but assuming drivers 1-16 are used and connected left-to-right then by changing the top/bottom option you either display the character in memory address 0 (ie letter 'H') on the upper left side of the display on position 1 or on the (invisible) right most position 20 of the display. Note that both rows and columns are flipped by the top/bottom selection otherwise the text will appear mirrored.

The TextLCD lib defaults to 'top' mode for the US2066 controller. Selecting 'top' again has no effect. Selecting 'bottom' will adjust the display in case the wiring is different from the display module that I used for development. Although you can flip the orientation of the characters, you can not show the 4 missing characters on a 16x2 display. You will have to skip those memory addresses 0-3 and write to address 4-19 instead. This can be done by calling lcd.locate(col, row).

24 Apr 2017

Wim, Now I am testing an OLED 2004 panel, and it seems the US2066 20x4 support is not working. If I declare TextLCD::LCD20x4, the display will be completely dark. If, TextLCD::LCD16x2 is declared, some text will be displayed, but limited to 2 lines, and 16 characters long, not surprisingly. Could you take a look into the library, see if anything for the US2066 20x4 support is missing thanks. H.M. /media/uploads/mahengjie/us2066_oled2004.jpg

24 Apr 2017

Here is the code I am using

#include "mbed.h"
#include "TextLCD.h"
TextLCD lcd(D7, D8, D10, D11, D12, D13, TextLCD::LCD20x4, NC, NC, TextLCD::US2066_3V3);  // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=US2066
int main() {
    lcd.setOrient(TextLCD::Bottom);
    // lcd.setOrient(TextLCD::Top); 
    uint16_t x=0;
    lcd.printf("Hello Jorge!   \n");
    lcd.printf("Hello Chelsea! \n");
    lcd.printf("Hello Ashley!  \n");
//    lcd.printf("Hello Marie!   \n");        
}
25 Apr 2017

should I declare "TextLCD::LCD20x4D", instead of "TextLCD::LCD20x4" for this 2004 display ?

25 Apr 2017

Wim, Declaring "TextLCD::LCD20x4D" works for this US2066-based 20x4 OLED panel by Newhaven Display. Now all 4 lines are displayed. /media/uploads/mahengjie/us2066lcd20x4d.jpg

The test code I used

// Hello World! for the TextLCD

#include "mbed.h"
#include "TextLCD.h"

TextLCD lcd(D7, D8, D10, D11, D12, D13, TextLCD::LCD20x4D, NC, NC, TextLCD::US2066_3V3);  // RS, E, D4-D7, LCDType=LCD20x4, BL=NC, E2=NC, LCDTCtrl=US2066

int main() {
    lcd.setOrient(TextLCD::Bottom);
    // lcd.setOrient(TextLCD::Top); 
    uint16_t x=0;
    lcd.printf("Hello Jorge!   \n");
    lcd.printf("Hello Chelsea    !!\n");
    lcd.printf("Hello Ashley!  \n");
    lcd.printf("Hello Marie!   \r");        
}
25 Apr 2017

Now the question is whether the "LCD20x4D" is the intended one for this device. - H.M.

25 Apr 2017

Still no luck with I2C interface, on both 16x2 and 20x4 panel. The I2C port declaration I used

I2C i2c_lcd(D14,D15); // SDA, SCL,  
TextLCD_I2C_N lcd(&i2c_lcd, US2066_SA0, TextLCD::LCD20x4D, NC, TextLCD::US2066_3V3); 
26 Apr 2017

The "LCD20x4D" is indeed the intended configuration mode for the US2066 device. This is due to the way this controller addresses its displaymemory. It is different from the way a fully HD44780 compatible controller handles a 3 or 4 line display. The 'standard' method is selected when you use "LCD20x4" but this mode is ignored by the TextLCD lib for a US2066 to avoid errors.

I dont see what the problem is with the I2C mode. Maybe it is an issue with the board. Have you ever used I2C for this board with any other I2C devices? Can you measure with a scope or logic analyser what happens on the I2C bus. I dont have the board available so I cant test it at the moment.

26 Apr 2017

Wim, The display panels I have tried with the I2C of TextLCD are the two US2066-based OLED's from Newhaven Display, one is 16x2, and one is 20x4. I do not have any other I2C-support charater/numeric displays to test with. I will get a scope, and run "lcd.printf" in loop, see what I get on the scope. Later. - H.M.

08 May 2017

Wim, It has been a while. Finally got a oscilloscope to see the SCL and SDA signal, and saw nothing. The two channels (which are hooked up to D15, D14 of Wizwiki ) are completely silent, despite that I am repeatedly running "printf". It is very strange....

// Hello World! for the TextLCD
#include "mbed.h"
#include "TextLCD.h"
TextLCD_I2C_N lcd(&i2c_lcd, US2066_SA0, TextLCD::LCD20x4D, NC, TextLCD::US2066_3V3); // I2C bus, slaveaddress, LCDType=LCD16x2, BL=NC, LCDTCtrl=US2066

int main() {
    lcd.setOrient(TextLCD::Bottom);
    while(1)
    {
        // lcd.setOrient(TextLCD::Top); 
        lcd.printf("123\n");     
        wait(0.5);
    }    
}
08 May 2017

There should be at least some activity on the I2C bus. Do you have the pull-up resistors installed (3K3 to 3V3). The levels on SDA an SCL should be 3V3 when you press the reset button on the Wizwiki. Make sure you dont reverse SDA and SCL declarations Make sure you have updated the mbed lib to the latest version: right click on mbed in your project and select ''update''

I have tested the board with a simple PCF8574 portexpander. That works fine. Make sure the code runs by checking the serial debug window. Make sure it detects the US2066 using this code:

// Hello World! for the TextLCD
#include "mbed.h"
#include "TextLCD.h"

Serial pc(USBTX, USBRX); // tx, rx

I2C  i2c_lcd(D14, D15); //SDA, SCL = PA_10, PA_09
char cnt = 0;  

TextLCD_I2C_N lcd(&i2c_lcd, US2066_SA0, TextLCD::LCD20x4D, NC, TextLCD::US2066_3V3); // I2C bus, slaveaddress, LCDType=LCD16x2, BL=NC, LCDTCtrl=US2066
 
int main() {
  pc.printf("Hello World from W7500!\n\r");

  if (! i2c_lcd.write(US2066_SA0, &cnt, 1)) {
    pc.printf("Found I2C Slave Device\n\r");
  }    
  else {  
    pc.printf("Ooops, cant find I2C Slave Device\n\r");
  }
 
   lcd.setOrient(TextLCD::Bottom);

   while(1) {
      lcd.printf("123\n");     
      wait(0.5);
   }    
}
09 May 2017

Thanks for trying to help. I ran your test code once before making a update, and my Tera Term windows did show an echo, saying not seeing US2066 (screenshot attached). Then I updated the library per your instruction. The compilation failed. I could not tell if anything is wrong in the code, except a typo "i2c" which I think should be "i2c_lcd". Is there something wrong in the l library update ? /media/uploads/mahengjie/i2c_detect.png /media/uploads/mahengjie/afterupdate.png

09 May 2017

Did you update the mbed lib or the TextLCD lib? It looks like you have somehow damaged my TextLCD lib in your project or replaced it by another one. Maybe the original version by Simon Ford. That is probably why the compiler cant find the I2C version of the TextLCD Class and why ''US2066_SA0'' and ''Bottom'' are missing.. Make sure you import the correct TextLCD lib in your project. Also check TextLCD_Config.h file to make sure you have the native I2C version enabled:

#define LCD_I2C_N      1           /* Native I2C bus     */

Is the I2C idle level OK, is there any activity on the I2C bus? If the bus works and you dont see the slave device found message it tells you that the wiring is wrong or maybe the US2066 interface is not set for I2C. Check table given above for the I2C mode. Check BS0-BS2 as well as all other connections.

09 May 2017

Wim, there was never any activity on the I2C bus. But it is entirely possible that there is something wrong in my wiring as all those pull-ups and pull-downs made the wiring on the breadboard a mess. It is also possible that the way I did the library update was wrong. I right clicked on the very top level to do the update (tried both update and update-all) . Maybe I should click only on your TextLCD library only ???

10 May 2017

I have successfully tested TextLCD Enhanced on a W7500 using I2C for a US2066 20x2 display. Import this example and try the code: https://developer.mbed.org/users/wim/code/W7500_hello/

It should work when your wiring is correct. You may want to change the LCDType to LCD20x4D instead.

13 May 2017

Wim, Thanks so much. Will give it a try on Monday

Update : double-checked the wiring, no error found, and then tried your i2c code as whole, the New Haven Display 20x4 OLED still not responding. I guess it must be this particular device that is a bit different. It is not a big problem for me, as I am quite satisfied with the 4-bit interface working. Thanks again for all your help.

17 Mar 2018

Your library is just pure awesomeness! I wanted to ask you about the support of Cyrillic. My display WH1604a-yyt-ct# is supposed to have Cyrillic support. I enable

#define LCD_UTF8_FONT 1 and #define LCD_UTF8_CYR_B 1 as you wrote in your article here, but the display doesn't read Russian characters.

TextLCD lcd(PD_7, PD_5, PC_12, PD_2, PG_2, PG_3, TextLCD::LCD16x4);

int main()

{

lcd.locate(0, 0);

lcd.printf("калибровка");

// other stuff

}

What is read on the display is English characters, and Russian are omitted: "ka<missing><missing><missing>pobka";

What am I missing?

10 Apr 2018

Hi Dima, sorry for the late response. I don't seem to get email alerts anymore when someone asks a question on a notebook page and I don't check that often to see if anything was posted.

Anyhow, the datasheet says that your display has a KS0066 or equivalent controller. That device has support for different characterfonts, but it depends on the ROM version of the chip. Typically the lower ASCII character codes are used for standard English characters and the upper ASCII set (above 128) is used for other fonts and/or symbols.

I have sofar only been able to test this function with the SSD1803 that I have available. Your #define settings are OK, but the mapping of characters may be different for that KS0066 and my SSD1803 so this might need to be adapted for your specific controller. Also note that because of the limited memory space not all Cyrillic characters may be supported by a particular device ROM which would explain blank/missing or incorrect characters. You will normally find a fonttable in the datasheet for the specific controller ROM version to get an overview of all available characters.

Could you post some pics or more info on the controller so we can try and fix this issue. Try and print all chars between ASCII 0x00 and 0xFF to check all characters that are available in the ROM.

08 Jul 2018

Hi all. Just got a nifty cool 16x2 LCD w/ 4 wire SPI. Driver is ST7070. Will the enhanced TextLib work with this? Saw the ST7032 driver mentioned above but wasn't clear that it was the only 4w SPI driver that TextLib would successfully interface with. Tnx again !!

24 Jul 2018

Hi Gary, the ST7070 has been tested with TextLCD lib. I recommend you use the display in the regular SPI_N mode with 4 pins (mosi, sck, cs and the pin for rs) rather than the awkward SPI_N_3_8 mode which is also supported but is slower.

12 Oct 2018

Hi, i have a little problem with my LCD. I can't change LCD contrast and with default setting i can't see text very well. It's very difficult to see the text on LCD. i use the latest Lib. and 5v. for LCD. this is my LCD specification:

LCD16x2, PFC8574AT, HD44780, I2C. And i use this for my Programm:

TextLCD_I2C lcd(&i2c_lcd, 0x7E, TextLCD::LCD16x2, TextLCD::HD44780);

and for Serial Port Expander Hardware module:

  1. define LCM1602 1

anybody can help me? I don't know anymore.

/media/uploads/Dapa/lcd1602.jpg

15 Oct 2018

Hello Da Ar, Did you try adjusting the blue potmeter on the I2C adapter board? Does the contrast change when you adjust it? Can you measure the actual voltage on pin 3 of the LCD to see if it really changes (in case there is a bad solder joint). In case the contrast is still too low when pin 3 is at 0 volts you may have to modify the board to try a small negative voltage (ca -1V) on pin 3. Some LCD modules require that negative contrast voltage before working properly. Check the datasheet of your LCD Module.

16 Oct 2018

Wim Huiskamp wrote:

Hello Da Ar, Did you try adjusting the blue potmeter on the I2C adapter board? Does the contrast change when you adjust it? Can you measure the actual voltage on pin 3 of the LCD to see if it really changes (in case there is a bad solder joint). In case the contrast is still too low when pin 3 is at 0 volts you may have to modify the board to try a small negative voltage (ca -1V) on pin 3. Some LCD modules require that negative contrast voltage before working properly. Check the datasheet of your LCD Module.

Hi Wim Huiskamp,

thanks a lot for your answer. I tried that, i mean adjusting the blue pot. and also measuring voltage on pin 3. The best contrast is with 0 Volt. but it's still too low. I checked all components on LCD Board and I2C board, they working fine. but i have still the same problem. Just i didn't try with negativ voltage, because i don't know, how do that. another case when i try to use the ( #define default ) instead ( #define LCM1602) for Serial Port Expander Hardware module, than i can see something (sometime a Charakter or somethings else) very well and with acceptable contrast, but i can't see my Text on LCD (see Picture). I ordered another LCD with I2C board too. It work with I2C slave address 0x4E. But the same problem. I think, that my Programm is incorrect :

  1. include "mbed.h"
  2. include "TextLCD.h"
  3. include "stm32f103c8t6.h"
  4. I2C i2c_lcd(PB_9,PB_8);
  5. TextLCD_I2C lcd(&i2c_lcd, 0x4E, TextLCD::LCD16x2,TextLCD::HD44780);
  6. int main()
  7. { lcd.cls();
  8. lcd.setBacklight(TextLCD::LightOn);
  9. lcd.printf(" LCD CHECK");
  10. lcd.setAddress(0, 1);
  11. lcd.printf(" Hello MBED \n");
  12. }/media/uploads/Dapa/lcd1602new.jpg
17 Oct 2018

Hi Da Ar, please use the <code>> and <</code>> on separate lines around your posted code to keep it readable.

The LCD in the top picture should typically show a single line of black rectangles after a power-on. Remove the I2C wires and power-on the board to test that. See if the contrast is OK and adjustable. Some modules may need small negative contrast voltages on pin3 in particular when they are powered by 3V3 instead on 5V. Disconnect pin 3 on the LCD from the I2C adapterboard and connect it to negative powersupply of -1V or use a 1.5V battery to test that (+pin of battery to GND (ie pin1 of the LCD), -pin of batt to pin3). That will require some soldering. Before doing that, can you show pics of the adapterboard and the reverse of the LCD to check the type. Perhaps the LCD uses a controller that is not fully HD44780 compatible and it needs some special commands to adjust the contrast. What powersupply are you using , is it 3V3 or 5V?

It seems that the second LCD is a white-on-blue type that should typically show a single line of white rectangles after a power-on. Remove the I2C wires and power-on the board to test that. See if the contrast is OK and adjustable. The LCD seems to have good contrast, but it has not been configured properly: you see only one line (instead of 2) and incorrect characters. You use I2C address 0x4E, that means the adapter has a PCF8574T instead of PCF8574AT. When the display responds to that address it means I2C address and contrast are OK. Check that all solder joints for D4-D7 are also correct. Can you show pics of the adapterboard and the reverse of the LCD to check the type.

22 Nov 2018

I have a same problem. In the mode :

//Select Serial Port Expander Hardware module
#define DEFAULT   1 

Outputs incorrect symbols, the contrast is normal and is regulated by a potentiometer. In the mode:

#define LCM1602       1

Outputs the normal text, but contrast very low, rotation of a potentiometer only reduces contrast. Checked on two different displays and modules for PCF8574T. My init string -

 TextLCD_I2C lcd(&i2c_lcd, 0x4F, TextLCD::LCD16x4, TextLCD::HD44780); 
25 Nov 2018

Hi Anton, your module seems to use the LCM1602 wiring as it works as expected when you select that setting. The contrast issue may be due to the supply voltage that you use. Is it 3V3 or 5V? You seem to get decent contrast when the module is not connected properly (ie with the DEFAULT setting). This could be caused by the fact that after a power-on the LCD defaults to a one-line mode in which it seems to need lower contrastvoltages. As soon as you have the correct LCM1602 setting selected it gets configured as 16x4 display (actually a two-line display) and it needs a bit more contrast voltage because it drives more characters. The contrast may be insufficient when the module is powered at 3V3. You either need to power it at 5V or connect a slightly negative contrast voltage to pin 3 when using a 3V3 powersource. Note that 'contrastvoltage' is really the difference between the powersupply voltage and the voltage on pin3 of the LCD. So assuming you have an LCD module that allows a 5V supply you should power it from that voltage and get sufficient contrast range. Note that the I2C SDA and SCL might have pull-up resistors installed on the I2C port expander module that will then also be connected to 5V. That should still be OK as most mbed I2C ports will tolerate that. Remove the onboard pull-ups and use external pull-ups to 3V3 is you want to be on the safe side.

29 Feb 2020

Some newer I2C expanders may use the PCA8574 instead of the PCF8574. The PCA8574 is a newer version of the PCF8574. It should work with the same code. The differences are that the newer devices seem to work at higher I2C clockrates (400Kbit vs 100Kbit for the older types) and the newer devices have pull-up resistors on the address select lines. Check the product datasheet (google PCA8574; PCA8574A v3 -3 june 2013). https://www.nxp.com/docs/en/data-sheet/PCA8574_PCA8574A.pdf?

You should still be able to use the TextLCD lib. Make sure to select the correct #define in TextLCD_Config.h for the port expander (eg DFROBOT). A common error is that you have the wrong slave address parameter in the TextLCD instantiation code, It must match the solderbridges or jumpers for the A0,A1,A2 pins on the PCA8574 (0x40 .. 0x4E). However, note that there are also PCA8574A types which use slave addresses (0x70 .. 0x7E). Check which device version your port expander module uses.

02 Dec 2021 This post is awaiting moderation

Hi, I try to connect the LCD (EA DOGM204) with the Mbed LPC1768 by using I2C for about 2 weeks. I connect all the pins as shown on the page4 in the manual (https://www.lcd-module.de/fileadmin/eng/pdf/doma/dogm204e.pdf). I try to write the code by using I2C API and setup the register as shown on the page 5, but it doesn't work. Then I try the code from here (https://os.mbed.com/users/wim/code/TextLCD/), it also doesn't work. I try to edit some code in the TextLCD, such as change the device Address and etc. It doesn't work as well. Every methods I have tried the LCD did turn on or show anything on the screen. So, I thought maybe I have to adjust the contrast to the maximum to make any text appear but it doesn't work at all. Does any one have any advice? Please feel free to comment, I would appreciate it.

Thank you in advance,

Please log in to post comments.