character lcd – LCD Display Corruption on Raspberry Pi Pico (MicroPython) – Lines Overwriting Each Other
I am building a system using a Waveshare RP2040-Zero ( like a Raspberry Pi Pico ) with an HD44780-2004 LCD over I2C. I’m facing a strange issue where the text on one line of the display occasionally gets overwritten by text from another line after the main loop runs for a while.
My sample code has two main parts:
- A Timer interrupt that updates the time and date on line 1 every second.
- A main loop that updates the thermostat status on line 2
every 5 seconds.
The Problem:
After approximately 10 loops, the text intended for line 3 (“Status: …”) is sometimes printed on line 2. Later this happens again, every 6-12 loops after the first occurrence with even half words but not clearing existing text (it looks like that the added spaces are removed ). Line 1 (the time) continues to update correctly.
Here is my simplified test code that reproduces the issue:
# micro python
# lcd row test
import machine
import time
from machine import I2C, Pin, Timer
from time import sleep
from pico_i2c_lcd import I2cLcd
LCD_HD44780_2004_ADDR = 0x27
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
devices = i2c.scan()
if LCD_HD44780_2004_ADDR in devices:
lcd = I2cLcd(i2c, LCD_HD44780_2004_ADDR, 4, 20)
else:
lcd = None
def update_tijd_datum(timer):
"""Show time and date on line 1 of the LCD - independent of main loop"""
if lcd is None:
return
current_time = time.localtime()
tijd_str = "{:02d}-{:02d}-{} {:02d}:{:02d}:{:02d}".format(
current_time[2], current_time[1], current_time[0],
current_time[3], current_time[4], current_time[5]
)
lcd.move_to(0, 0)
tijd_str = tijd_str + ' ' * (20 - len(tijd_str))
lcd.putstr(tijd_str)
# INITIALIZE TIMER INTERRUPT
tijd_timer = Timer()
tijd_timer.init(period=1000, mode=Timer.PERIODIC, callback=update_tijd_datum)
def toon_thermostaat_info():
if lcd is None:
return
lcd.move_to(0, 1)
lcd.putstr("Temp: 21.5C" + ' ' * (20 - len("Temp: 21.5C")))
lcd.move_to(0, 2)
lcd.putstr("Status: Verwarming" + ' ' * (20 - len("Status: Verwarming")))
lcd.move_to(0, 3)
lcd.putstr("Set: 22.0C" + ' ' * (20 - len("Set: 22.0C")))
toon_thermostaat_info()
counter = 0
try:
while True:
sleep(5)
counter += 1
if lcd:
lcd.move_to(0, 2) # Intend to write to line 3
import random
status = random.choice(["Status: Verwarming", "Status: Koeling", "Status: Uit"])
print(f"{counter}, {status}")
status = status + ' ' * (20 - len(status))
lcd.putstr(status) # This text sometimes appears on line 2!
except KeyboardInterrupt:
print("Programma gestopt")
tijd_timer.deinit()
What I’ve Investigated:
I am padding the strings with spaces to clear the entire line, so it shouldn’t be leftover characters.
The move_to(0, 2) command is correctly placed before writing the status.
The problem is intermittent, which makes me suspect a race condition or a shared resource conflict.
As a side note, I did try it with a different same type/model brand new display but same result.
The timer interrupt (updating line 1) and the main loop (updating line 2) are both accessing the same lcd object. I suspect they might be interfering with each other, even though they are writing to different lines.
My Questions:
What is the root cause of this “line jumping” behavior? Is my suspicion about a race condition between the interrupt and the main loop correct?
How can I make this solid? What is the best practice for handling concurrent access to an I2C LCD from both a timer interrupt and the main loop in MicroPython?
Any insights or suggestions would be greatly appreciated
Read more here: Source link
