I2C LCD Library... Help!

Discuss development of drivers for external hardware and components, such as LCD screens, sensors, motor drivers, etc.
Target audience: Users and developers of drivers.
synimak
Posts: 20
Joined: Sun Feb 28, 2016 5:11 am
Contact:

I2C LCD Library... Help!

Post by synimak » Tue Mar 01, 2016 1:00 am

I'm trying to get a 20x4 LCD with i2c packpack to work. I'm running the pyb_i2c_lcd_test.py. It prints to the console and if I pull SCI or SDA I get a OSError: 5 suggesting that things are communicating. But the LCD does nothing. It works great on an arduino no problem. And yes there is a LLC inbetween.

The hardware:

LCD - https://www.adafruit.com/product/499
i2c Backpack - https://www.adafruit.com/products/292

I've been looking through all the data sheets. I'm guessing that there are some bytes out of sequence with what has to be sent to the LCD or backpack. But it's getting beyond what I know and I'm starting to pull my hair out.

Any help would be greatly appreciated :D

Cheers

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

Re: I2C LCD Library... Help!

Post by dhylands » Tue Mar 01, 2016 4:09 am

If you're talking about the pyb_i2c_lcd_test.py from https://github.com/dhylands/python_lcd then I think that the backpacks are different (even though they're both i2c).

I wrote the code for an I2C backpack like this one:
http://arduino-info.wikispaces.com/LCD-Blue-I2C
which uses a PCF8574 chip. It turns out that are several variants of the design using the PCF8574 and not all of them are wired up the same.

The adafruit i2c backpack usese a totally different interface chip. It just so happens that I have one of the adafruit backpacks. I had thought to write a variant of my library to work with the adafruit backpack but just never got around to.

Give me a couple days, and I'll write a version of the code to work with the adafruit backpack.

synimak
Posts: 20
Joined: Sun Feb 28, 2016 5:11 am
Contact:

Re: I2C LCD Library... Help!

Post by synimak » Tue Mar 01, 2016 4:36 am

Yeah I thought it would be something like that.

Awesome! Thanks Dave!

Can't wait :D

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

Re: I2C LCD Library... Help!

Post by dhylands » Wed Mar 02, 2016 6:49 am

I've added pyb_i2c_adafruit_lcd.py and pyb_i2c_adafruit_lcd_test.py to my repository:
https://github.com/dhylands/python_lcd

and tested it with a 4 line, 20 column LCD (the test code assumes that A0, A1, and A2 are open, and it used I2C1 (although it should also work with any I2c bus).

synimak
Posts: 20
Joined: Sun Feb 28, 2016 5:11 am
Contact:

Re: I2C LCD Library... Help!

Post by synimak » Wed Mar 02, 2016 10:08 pm

Awesome thank you Dave
Absolute Legend! :D

sequel
Posts: 14
Joined: Wed Aug 03, 2016 1:52 pm

Re: I2C LCD Library... Help!

Post by sequel » Wed Aug 03, 2016 3:29 pm

Sorry to post on an old topic but, i am quite in the same situation.

I have been able to modify the pyb_gpio code over :
https://github.com/dhylands/python_lcd
to make it work on esp8266 with an HD44780 style character LCD but, after many attempts, i am still unable to get the same LCD working with an I2C interface.

The I2C interface i am using looks like the same as described at :
http://arduino-info.wikispaces.com/LCD-Blue-I2C
and i can make it work with arduino without any issue (chip is labelled as PCF8574T).

What i have tried so far was to change all the occurrences of :
self.i2c.send(value, self.i2c_addr)
to :
self.i2c.writeto(self.i2c_addr, hex(value))

as trying to send the actual value (int) will return :
TypeError: object with buffer protocol required

I also been fiddling with the LiquidCrystal code on arduino to intercept what was sent to the I2C slave during those simple steps :
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
lcd.begin(16,2);
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("a");
}

and i have tried to send the exact same thing while all is connected to the esp8266 but, no luck.


Am i missing something? Am i doing something wrong? Should writeto_mem be used instead of writeto (like in pyb_i2c_adafruit)? I have done some small tests in that regard but, what would be the registers for PCF8574T? Is it ok to send in hex? Maybe it have something to do with the fact that the I2C implementation on the esp8266 is done in software?

Any tips to help me get this working would be greatly appreciated!


Many thanks, regards

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: I2C LCD Library... Help!

Post by deshipu » Wed Aug 03, 2016 6:41 pm

You want chr() not hex(). hex() generates a string representing the value in hexadecimal, chr() generates a byte corresponding to the value.

sequel
Posts: 14
Joined: Wed Aug 03, 2016 1:52 pm

Re: I2C LCD Library... Help!

Post by sequel » Wed Aug 03, 2016 7:35 pm

Thank you so much for your reply deshipu.

I just tried with chr() instead of hex() but unfortunately, it still does not work.

There is probably not much missing as the communication seems to flow from esp8266, trough the backpack, to the LCD as, the LCD react when i am sending stuff to the backpack I2C slave address.

Like for example, if i send a really simple command (well, probably not a command but just a toggle of the BacklightPin), in any of those ways :

i2c.writeto(0x27, '8')
i2c.writeto(0x27, hex(8))
i2c.writeto(0x27, chr(8))

the backlight of the LCD is lightning up.

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

Re: I2C LCD Library... Help!

Post by dhylands » Wed Aug 03, 2016 10:19 pm

The LCD has a very specific protocol for sending character to it, so you don't want to be making i2c.write commands directly.

Here is some sample code that shows how to use it:
https://github.com/dhylands/python_lcd/ ... cd_test.py

sequel
Posts: 14
Joined: Wed Aug 03, 2016 1:52 pm

Re: I2C LCD Library... Help!

Post by sequel » Wed Aug 03, 2016 11:08 pm

I know that i cannot just do :

i2c.writeto(0x27, 'A')

and that magically upper case A will appear on the LCD.

As stated in my previous post, i started with your code, pyb_i2c_lcd.py, and that i have adapted it to try to make it work on esp8266. Here is my latest attempt while using chr() (as suggested by deshipu) :

Code: Select all

"""Implements a character based lcd connected via PCF8574 on i2c."""

from lcd import LcdApi
from machine import I2C
from time import sleep_ms

DEFAULT_I2C_ADDR = 0x27

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

MASK_RS = 0x01
MASK_RW = 0x02
MASK_E = 0x04

#MASK_RS = 4
#MASK_RW = 5
#MASK_E = 6

SHIFT_BACKLIGHT = 3
SHIFT_DATA = 4


class I2cLcd(LcdApi):
    """Implements a character based lcd connected via PCF8574 on i2c."""

    def __init__(self, i2c, i2c_addr, num_lines, num_columns):
        self.i2c = i2c
        self.i2c_addr = i2c_addr
        self.i2c.writeto(self.i2c_addr, chr(0))
        sleep_ms(20)   # Allow LCD time to powerup
        # 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 intiialization.
        """
        byte=((nibble >> 4) & 0x0f) << SHIFT_DATA
        print(byte | MASK_E)
        print(chr(byte))
        self.i2c.writeto(self.i2c_addr, chr(byte | MASK_E))
        self.i2c.writeto(self.i2c_addr, chr(byte))

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

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

    def hal_write_command(self, cmd):
        print('in hal_write_command')
        """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))
        print(byte | MASK_E)
        print(byte)
        self.i2c.writeto(self.i2c_addr, chr(byte | MASK_E))
        self.i2c.writeto(self.i2c_addr, chr(byte))
        byte=((self.backlight << SHIFT_BACKLIGHT) |
                ((cmd & 0x0f) << SHIFT_DATA))
        print(byte | MASK_E)
        print(byte)
        self.i2c.writeto(self.i2c_addr, chr(byte | MASK_E))
        self.i2c.writeto(self.i2c_addr, chr(byte))
        if cmd <= 3:
            # The home and clear commands require a worst
            # case sleep_ms of 4.1 msec
            sleep_ms(5)

    def hal_write_data(self, data):
        print('in hal_write_data')
        """Write data to the LCD."""
        byte=(MASK_RS |
                (self.backlight << SHIFT_BACKLIGHT) |
                (((data >> 4) & 0x0f) << SHIFT_DATA))
        print(byte | MASK_E)
        print(byte)
        self.i2c.writeto(self.i2c_addr, chr(byte | MASK_E))
        self.i2c.writeto(self.i2c_addr, chr(byte))
        byte=(MASK_RS |
                (self.backlight << SHIFT_BACKLIGHT) |
                ((data & 0x0f) << SHIFT_DATA))
        print(byte | MASK_E)
        print(byte)
        self.i2c.writeto(self.i2c_addr, chr(byte | MASK_E))
        self.i2c.writeto(self.i2c_addr, chr(byte))
with this code in place on my esp8266, running the following :

>>> from machine import Pin, I2C
>>> from time import sleep_ms, sleep_us
>>> from machine_i2c_lcd import I2cLcd
>>> i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
>>> lcd = I2cLcd(i2c, 0x27, 2, 16)
>>> lcd.putstr("Hello World!")

Just make the LCD blink a couple of times rapidly and nothing is printed on the LCD.


Thank you so much!

Post Reply