Using Standard HD44780 LCDs on LoPy4

Discuss development of drivers for external hardware and components, such as LCD screens, sensors, motor drivers, etc.
Target audience: Users and developers of drivers.
gatorchu
Posts: 15
Joined: Sun Sep 22, 2019 3:50 pm

Re: Using Standard HD44780 LCDs on LoPy4

Post by gatorchu » Sat Sep 28, 2019 4:11 pm

Thank you for pointing out my silly problem!

Now, there is no error anymore, I can see the returns in the REPL,

Code: Select all

rst:0x7 (TG0WDT_SYS_RESET),boot:0x32 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff8028,len:8
load:0x3fff8030,len:2156
ho 0 tail 12 room 4
load:0x4009fa00,len:19208
entry 0x400a05f4
Initializing filesystem as FatFS!
Running test_main
Turning backlight off
Turning backlight on
Turning display off
Turning display on
Turning display & backlight off
Turning display & backlight on
Turning backlight off
Turning backlight on
Turning display off
Turning display on
Turning display & backlight off
Turning display & backlight on
Turning backlight off
Turning backlight on
Turning display off
Turning display on
Turning display & backlight off

but the LCD display nothing and no backlight on/off.

I do have a potentiometer connected to my LCD to adjust the contrast and the LCD works properly when using Arduino board!

User avatar
Roberthh
Posts: 1642
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Using Standard HD44780 LCDs on LoPy4

Post by Roberthh » Sat Sep 28, 2019 5:47 pm

It's either a problem with supply or the control signals.
Q1: What is the value of Vcc for the LCD. It has to be 5V.
Q2. For comparison: which Arduino code are you using for the test?

User avatar
dhylands
Posts: 3228
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Using Standard HD44780 LCDs on LoPy4

Post by dhylands » Sat Sep 28, 2019 5:59 pm

When you power on the LCD, even if it isn't connected to anything, you should see a row of black squares. If you don't see the black squares then that typically means that you need to adjust the contrast voltage until you see the black squares.

If you don't see the black squares the you won't see the text.

User avatar
Roberthh
Posts: 1642
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Using Standard HD44780 LCDs on LoPy4

Post by Roberthh » Sat Sep 28, 2019 6:01 pm

Besides that, I just noticed that there seems to be a adafruit version made by Dave: https://github.com/dhylands/python_lcd/ ... uit_lcd.py. That one looks better.

gatorchu
Posts: 15
Joined: Sun Sep 22, 2019 3:50 pm

Re: Using Standard HD44780 LCDs on LoPy4

Post by gatorchu » Sat Sep 28, 2019 9:38 pm

Roberthh wrote:
Sat Sep 28, 2019 5:47 pm
It's either a problem with supply or the control signals.
Q1: What is the value of Vcc for the LCD. It has to be 5V.
Q2. For comparison: which Arduino code are you using for the test?
A1: I supply 5V to the MCP23008 backpack mounted on the back of LCD.
A2: I run the HelloWorld_i2C.ino in the Adafruit_LiquidCrystal library on both Arduino UNO and MKR1010 board. The LCD worked properly.

gatorchu
Posts: 15
Joined: Sun Sep 22, 2019 3:50 pm

Re: Using Standard HD44780 LCDs on LoPy4

Post by gatorchu » Sat Sep 28, 2019 10:07 pm

dhylands wrote:
Sat Sep 28, 2019 5:59 pm
When you power on the LCD, even if it isn't connected to anything, you should see a row of black squares. If you don't see the black squares then that typically means that you need to adjust the contrast voltage until you see the black squares.

If you don't see the black squares the you won't see the text.
A 5V power supply was used to power the LCD, and a potentiometer was connected directly to the LCD as shown below.
Image

I can see the black squares on the LCD!

gatorchu
Posts: 15
Joined: Sun Sep 22, 2019 3:50 pm

Re: Using Standard HD44780 LCDs on LoPy4

Post by gatorchu » Sat Sep 28, 2019 10:32 pm

Roberthh wrote:
Sat Sep 28, 2019 6:01 pm
Besides that, I just noticed that there seems to be a adafruit version made by Dave: https://github.com/dhylands/python_lcd/ ... uit_lcd.py. That one looks better.
This one looks specifically designed for the pyboard.

Code: Select all

from lcd_api import LcdApi
from pyb import I2C
from pyb import delay

User avatar
Roberthh
Posts: 1642
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Using Standard HD44780 LCDs on LoPy4

Post by Roberthh » Sun Sep 29, 2019 6:17 am

Yes, you are right. But you can port the logic. The MCP chip requires special configuration, and data & commands written to internal registers. That must be ported to the machine.I2C logic. See e.g. line 53 and the register definitions in line 13-23. I do not have such a backplane here, so I cannot test.
So the register definitions have to be copied in, and the code might the look like:

Code: Select all

"""Implements a HD44780 character LCD connected via MCP23008 on I2C.
   This was tested with: https://www.adafruit.com/product/292"""

from lcd_api import LcdApi
from machine import I2C
from time import sleep_ms

# The MCP23008 has a jumper selectable address: 0x20 - 0x27
DEFAULT_I2C_ADDR = 0x20

# MCP23008 Registers

IODIR   = 0x00
IPOL    = 0x01
GPINTEN = 0x02
DEFVAL  = 0x03
INTCON  = 0x04
IOCON   = 0x05
GPPU    = 0x06
INTF    = 0x07
INTCAP  = 0x08
GPIO    = 0x09
OLAT    = 0x0A

# Defines shifts or masks for the various LCD line attached to the MCP23008

# GP0 - NC
# GP1 - RS
# GP2 - E
# GP3 - DB4
# GP4 - DB5
# GP5 - DB6
# GP6 - DB7
# GP7 - LITE

MASK_RS = 0x02
MASK_E = 0x04
SHIFT_DATA = 3
SHIFT_BACKLIGHT = 7


class I2cLcd(LcdApi):
    """Implements a HD44780 character LCD connected via MCP23008 on I2C."""

    def __init__(self, i2c, i2c_addr, num_lines, num_columns):
        self.i2c = i2c
        self.i2c_addr = i2c_addr

        # Send IODIR address, set IODIR to all inputs, init all other registers 0
        self.i2c.writeto(self.i2c_addr, b'\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00')

        # Set pins GP1 through GP7 to output, leave GP0 as input
        self.i2c.writeto_mem(self.i2c_addr, IODIR, bytearray([0x01]))

        # Send reset 3 times
        self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
        sleep_ms(5)    # need to delay at least 4.1 msec
        self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
        sleep_ms(1)
        self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
        sleep_ms(1)
        # Put LCD into 4 bit mode
        self.hal_write_init_nibble(self.LCD_FUNCTION)
        sleep_ms(1)
        LcdApi.__init__(self, num_lines, num_columns)
        cmd = self.LCD_FUNCTION
        if num_lines > 1:
            cmd |= self.LCD_FUNCTION_2LINES
        self.hal_write_command(cmd)

    def hal_write_init_nibble(self, nibble):
        """Writes an initialization nibble to the LCD.

        This particular function is only used during initialization.
        """
        byte = ((nibble >> 4) & 0x0f) << SHIFT_DATA
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte  | MASK_E]))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte]))

    def hal_backlight_on(self):
        """Allows the hal layer to turn the backlight on."""
        self.i2c.writeto_mem(1 << SHIFT_BACKLIGHT, self.i2c_addr, GPIO)

    def hal_backlight_off(self):
        """Allows the hal layer to turn the backlight off."""
        self.i2c.writeto_mem(0, self.i2c_addr, GPIO)

    def hal_write_command(self, cmd):
        """Writes a command to the LCD.

        Data is latched on the falling edge of E.
        """
        byte  = ((self.backlight << SHIFT_BACKLIGHT) |
                (((cmd >> 4) & 0x0f) << SHIFT_DATA))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte | MASK_E]))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte]))
        byte = ((self.backlight << SHIFT_BACKLIGHT) |
                ((cmd & 0x0f) << SHIFT_DATA))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte | MASK_E]))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte]))
        if cmd <= 3:
            # The home and clear commands require a worst
            # case delay of 4.1 msec
            sleep_ms(5)

    def hal_write_data(self, data):
        """Write data to the LCD."""
        byte = (MASK_RS |
                (self.backlight << SHIFT_BACKLIGHT) |
                (((data >> 4) & 0x0f) << SHIFT_DATA))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte | MASK_E]))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte]))
        byte = (MASK_RS |
                (self.backlight << SHIFT_BACKLIGHT) |
                ((data & 0x0f) << SHIFT_DATA))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte | MASK_E]))
        self.i2c.writeto_mem(self.i2c_addr, GPIO, bytearray([byte]))

User avatar
Roberthh
Posts: 1642
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Using Standard HD44780 LCDs on LoPy4

Post by Roberthh » Sun Sep 29, 2019 6:17 pm

I updated line 50 in the code above. Another i2c call had to be changed. Still untested, but at least it imports.

gatorchu
Posts: 15
Joined: Sun Sep 22, 2019 3:50 pm

Re: Using Standard HD44780 LCDs on LoPy4

Post by gatorchu » Tue Oct 01, 2019 2:13 am

Hi Robert,

I appreciate your detailed reply!

Now I received the backpack with PCF8574 chip. It works perfectly with your modified esp8266_i2c_lcd.py in https://forum.pycom.io/topic/4841/1602- ... with-pycom.

I haven't got your code tested for MCP23008 chip yet, but I will inform you the result after the test.

Post Reply