0

I'm currently using the LCD1602 with my raspberry pi 5 and have run into a few issues. I'm trying to use no library software i2c partially because I struggled to find a pi 5 - working LCD library and I want to gain a better understanding of the i2c protocol. So, to do this I decided to use the threading library to take control of the clock signal, and I'd have another thread for the main code: This is what it looks like:

import gpiod
import threading
import time
address = 0x27
Message = "hello"
global SDA
global SCL
global chip
chip = gpiod.Chip("gpiochip0")
SCL = chip.get_line(17)
SDA = chip.get_line(27)
event = threading.Event()
SDA.request(consumer="dev 1", type=gpiod.LINE_REQ_DIR_OUT)
SCL.request(consumer="dev 2", type=gpiod.LINE_REQ_DIR_OUT)
def CLOCK():
 global SDA
 global SCL
 global chip
 while True:
 SCL.set_value(1)
 event.set()
 time.sleep(0.00006)
 SCL.set_value(0)
 event.clear()
 time.sleep(0.00006)
CLOCK_thread = threading.Thread(target=CLOCK)
def Main_thread():
 global SDA
 global SCL
 global chip
 # 1. Start bits
 SDA.set_value(1)
 SCL.set_value(1)
 time.sleep(0.00006)
 SDA.set_value(0)
 SCL.set_value(0)
 CLOCK_thread.start()
 
 # 2. Address sharing
 for i in range(8):
 event.wait() # wait for SCL to go high to continue
 SDA.set_value((address >> (7 - i)) & 1)
 time.sleep(0.000006)
 # 3. Read/write bit
 event.wait()# wait for SCL to go high to continue
 SDA.set_value(0) # Assuming write operation
 time.sleep(0.000006)
 Start_time = time.time()
 
 #ACK/NACK
 SDA.release()
 SDA.request(consumer = "dev2", type = gpiod.LINE_REQ_DIR_IN)
 End_time = time.time()
 
 event.wait() # wait for clock to go high - when ACK will be sent
 ACK = SDA.get_value()
 time.sleep(0.0000006)
 print(ACK)
 total = Start_time - End_time
 print(total)
 SDA.release()
 SDA = chip.get_line(27)
 SDA.request(consumer = "dev3", type = gpiod.LINE_REQ_DIR_OUT)
 # 4. Data frame
 for char in Message:
 for bit in range(8):
 event.wait() # wait for SCL to go high to continue
 SDA.set_value((ord(char) >> (7 - bit)) & 1)
 time.sleep(0.000006)
 
 #ACK/NACK
 SDA.release()
 SDA.request(consumer = "dev2", type = gpiod.LINE_REQ_DIR_IN)
 End_time = time.time()
 
 event.wait() # wait for clock to go high - when ACK will be sent
 ACK = SDA.get_value()
 time.sleep(0.0000006)
 print(ACK)
 total = Start_time - End_time
 print(total)
 SDA.release()
 SDA = chip.get_line(27)
 SDA.request(consumer = "dev3", type = gpiod.LINE_REQ_DIR_OUT)
 # finish
 SCL.set_value(1)
 time.sleep(0.000006)
 SDA.set_value(0)
 time.sleep(0.00006)
 SDA.set_value(1)
 time.sleep(0.00006)
MAIN_thread = threading.Thread(target=Main_thread)
MAIN_thread.start()

Here is an explanation of what is going on:

  1. The start, I found that to start an i2c protocol you need to set the sda and scl high for one bit then low for one bit.

  2. For the address sharing I used the address 0x27 which I found from the SparkFun site. To transmit the data, I used a system that pauses the main thread until the CLK signal is outputting a 1 (i2c devices only read/write on a high clock signal.) Then I used a mechanism that outputs the values from the address bit by bit using a for loop system.

  3. Next is the read/write bit, where I again waited for the clock to go high, then sent a low (meaning the master is writing.)

  4. Now it was time to check for the ACK/NACK bit. For this I released the SDA line then reset it up as an input. Then I took the value on the SDA line and slept for 1 bit. I found that this made my code return a 1 (if it is an ACK it should return a 0.) To try and debug this I timed how long it takes to change the SDA to an input, it takes 7e-5 seconds and each bit is apparently

  5. Next, the data frame, here I made my code so that each letter of "hello" is converted into the ASCII of that letter then each individual bit is sent into the LCD’s SDA.

  6. Next is the second ACK/NACK bit. Where I did the same as the previous ACK/NACK bit, and am still unsuccessful.

Here is the problem: After all this code, there is no change on what is displayed on my LCD. I am wondering if this is due to there needing to be a cursor position set before the ASCII. Could anyone provide some guidance on anything that is left out?

Here is what the lcd looks like (it looks the same after I run the code as it does at startup): enter image description here

Here is a good datasheet on the LCD: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf

Thank you in advance.

asked Nov 1, 2024 at 5:29
8
  • what is displayed on the LCD? Commented Nov 1, 2024 at 6:55
  • @jsotola The LCD was displaying the same at startup as it is after the code I ran, I've updated the original post with a picture, thanks! Commented Nov 1, 2024 at 8:18
  • Can't see any Pi relevance. Get it working with a library before using your own code. E.g. abyz.me.uk/lg Commented Nov 1, 2024 at 9:06
  • @joan Hello, thank you for your helpful reply. I think it is a good idea to use a library before trying to create my own code. I think the one you suggested looks appropriate. Do you perhaps know where I can find the source code of the lgpio library, specifically its i2c capabilities so that I can use the source code to better understand how to create my own i2c? Thanks! Commented Nov 1, 2024 at 9:15
  • For some reason you keep trying to run I²C using a user space python GPIO library rather than any of the kernel based solutions which work. Commented Nov 1, 2024 at 10:13

1 Answer 1

1

There is kernel documentation See https://www.kernel.org/doc/html/latest/i2c/index.html for details of the I2C/SMBus Subsystem for background.

There are SMBus modules for python (I have used smbus2 although I normally use ioctl drivers in c with python wrappers).
Joan's lgpio Python I2C may be easier.
Using one of these would enable you to write a LCD1602 library, which should be relatively simple; CERTAINLY simpler than writing your own I2C code.

If you search there ARE LCD1602 python libraries, although I have never used one as I have only used on Arduino.

answered Nov 2, 2024 at 0:25
1
  • Thank you for your answer, it really helps! Commented Nov 2, 2024 at 2:21

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.