Currently I'm working on a project where I want to display some data on an LCD. I'm using a MCP2221A to communicate with a PCF8574, which then sends the bits to the HD44780 LCD.
How:
I'm using the LCD in 4-bit mode so I have to send the data-bytes in nibbles, first the higher and then the lower. The bytes I'm sending have the following composition: [RS,RW,E,K,D4,D5,D6,D7].
I've been following a manual to initialize and write to the LCD. For the I2C communication I'm running a python-script using CircuitPython. Here are the two functions I'm using:
def init(lcd_address):
commands = {
"set": "00110011",
"4bit": "00110010",
"clear1": "00110000",
"clear2": "00110001",
"home1": "00110000",
"home2": "00110011",
"ON1": "00110000",
"ON2": "00111111",
}
for i in range(3):
i2c.writeto(lcd_address, bytes([int(commands["set"], 2)]),stop=False) # Function set
sleep(0.01)
i2c.writeto(lcd_address, bytes([int(commands["4bit"], 2)]), stop=False) # Set 4-bit mode
i2c.writeto(lcd_address, bytes([int(commands["clear1"], 2)]), stop=False) # Clear the screen. Higher nibble
i2c.writeto(lcd_address, bytes([int(commands["clear2"], 2)]), stop=False) # Clear the screen. Lower nibble
i2c.writeto(lcd_address, bytes([int(commands["home1"], 2)]), stop=False) # Set cursor to (0,0). Higher nibble
i2c.writeto(lcd_address, bytes([int(commands["home2"], 2)]), stop=False) # Set cursor to (0,0). Lower nibble
i2c.writeto(lcd_address, bytes([int(commands["ON1"], 2)]), stop=False) # Turn on display. Higher nibble
i2c.writeto(lcd_address, bytes([int(commands["ON2"], 2)]), stop=True) # Turn on display. Lower nibble
def write(lcd_address): # Writing the letter 'H' to the lcd
char1 = "10110100"
char2 = "10110100"
i2c.writeto(lcd_address, bytes([int(char1, 2)]), stop=False)
sleep(0.02)
i2c.writeto(lcd_address, bytes([int(char2, 2)]), stop=True)
Problem:
I can't get the character to show up on the LCD. The bytes in the code are the same that get sent to the LCD (checked with scope), so that is not the problem. I'm guessing it has something to do with the enable pin and how that should be triggered, but I'm not sure.
EDIT
This is how my code looks now:
def init(lcd_address):
commands = {
"setD": "00010011",
"setE": "00110011",
"setF": "00010011",
"4bitD": "00010010",
"4bitE": "00110010",
"4bitF": "00010010",
"clear1D": "00010000",
"clear1E": "00110000",
"clear1F": "00010000",
"clear2D": "00010001",
"clear2E": "00110001",
"clear2F": "00010001",
"home1D": "00010000",
"home1E": "00110000",
"home1F": "00010000",
"home2D": "00010011",
"home2E": "00110011",
"home2F": "00010011",
"ON1D": "00010000",
"ON1E": "00110000",
"ON1F": "00010000",
"ON2D": "00011111",
"ON2E": "00111111",
"ON2F": "00011111",
}
for i in range(3):
sleep(0.01)
i2c.writeto(lcd_address, bytes([int(commands["setD"], 2)]), stop=False) # Function set
sleep(0.01)
i2c.writeto(lcd_address, bytes([int(commands["setE"], 2)]), stop=False)
sleep(0.01)
i2c.writeto(lcd_address, bytes([int(commands["setF"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["4bitD"], 2)]), stop=False) # Set 4-bit mode
i2c.writeto(lcd_address, bytes([int(commands["4bitE"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["4bitF"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["clear1D"], 2)]), stop=False) # Clear the screen
i2c.writeto(lcd_address, bytes([int(commands["clear1E"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["clear1F"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["clear2D"], 2)]), stop=False) # Clear the screen
i2c.writeto(lcd_address, bytes([int(commands["clear2E"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["clear2F"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["home1D"], 2)]), stop=False) # Set cursor to (0,0)
i2c.writeto(lcd_address, bytes([int(commands["home1E"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["home1F"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["home2D"], 2)]), stop=False) # Set cursor to (0,0)
i2c.writeto(lcd_address, bytes([int(commands["home2E"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["home2F"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["ON1D"], 2)]), stop=False) # Display on
i2c.writeto(lcd_address, bytes([int(commands["ON1E"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["ON1F"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["ON2D"], 2)]), stop=False) # Display on
i2c.writeto(lcd_address, bytes([int(commands["ON2E"], 2)]), stop=False)
i2c.writeto(lcd_address, bytes([int(commands["ON2F"], 2)]), stop=True)
def write(lcd_address): # Writing the letter 'H' to the lcd
char1D = "10010100"
char1E = "10110100"
char1F = "10010100"
char2D = "10010100"
char2E = "10110100"
char2F = "10010100"
i2c.writeto(lcd_address, bytes([int(char1D, 2)]), stop=False)
sleep(0.02)
i2c.writeto(lcd_address, bytes([int(char1E, 2)]), stop=False)
sleep(0.02)
i2c.writeto(lcd_address, bytes([int(char1F, 2)]), stop=False)
sleep(0.02)
i2c.writeto(lcd_address, bytes([int(char2D, 2)]), stop=False)
sleep(0.02)
i2c.writeto(lcd_address, bytes([int(char2E, 2)]), stop=False)
sleep(0.02)
i2c.writeto(lcd_address, bytes([int(char2F, 2)]), stop=True)
So now I'm sending 3 bytes per command but the display is still empty. It only flashes once when the code runs.