LCD1602 RGB Module, 16x2 Characters LCD, RGB Backlight, 3.3V/5V, I2C Bus.
This post is to provide information from my experience that may help others who have purchased one of these LCD modules.
The project was to connect the LCD to a PICO W to display temperature from a local sensor and a remote sensor accessed via WiFi. The Pico was loaded with
rp2-pico-w-20220831-unstable-v1.19.1-358-g0b26efe73 Micropython. The project was proceeding nicely until Micropython was updated. Exactly the same code resulted in an I2C I/O error.
The update was to redefine the default I2C pins. The Raspberry Pi Foundation had not specifically declared which pins they considered to be default. Each I2C bus can be configured for 6 different pin sets.
Forum posts showed other persons had problems with their code related to incorrect pins, mostly due to assuming the defaults. The problem I experienced was not related to incorrectly assigned pins, it was to do with LCD driver and how it configured I2C. I did notice a few posts where the situation seemed to be the same as I had experienced. The driver failed on
I2c.scan() worked correctly and the addresses returned were the correct device addresses. But when running the demo for the LCD it produced an I/O error. The only change was the Micropython update, so naturally it was blamed for the fault. A post from a Micropython developer indicated there should nothing in the update to cause I2C to fail. The only change in the update was the default pin assignments.
Based on this I began looking at the LCD driver library. I thought it had been fixed when the frequency was specified as 100 khz, but later testing showed this to be incorrect. The real fix came when the main code created an I2C instance and passed this to the library. This is similar to how the Makerverse RTC library works. Anything else did not work.
Modified example, Choose_color.py
import RGB1602_01 import time import math from machine import Pin, I2C colorR = 64 colorG = 128 colorB = 64 i2c = I2C(id=0, sda=Pin(8), scl=Pin(9), freq=400000) lcd=RGB1602_01.RGB1602(16,2,i2c=i2c) rgb1 = (148,0,110) #深紫罗兰色 rgb2 = (255,0,255) #紫色 rgb3 = (144,249,15) #青白 rgb4 = (0,128,60) #浅蓝 rgb5 = (255,209,0)#黄色 rgb6 = (248,248,60)#幽灵的白色 rgb7 = (80,80,145) #深蓝色 rgb8 = (255,0,0) #红色 rgb9 = (0,255,0) #青色 # set the cursor to column 0, line 1 lcd.setCursor(0, 0) # print the number of seconds since reset: # print the number of seconds since reset: lcd.printout("Waveshare") # lcd.setCursor(0, 1) # lcd.printout("Hello,World!") # # lcd.setRGB(rgb1,rgb1,rgb1); time.sleep(1) lcd.setRGB(rgb2,rgb2,rgb2); time.sleep(1) lcd.setRGB(rgb3,rgb3,rgb3); time.sleep(1) lcd.setRGB(rgb4,rgb4,rgb4); time.sleep(1) lcd.setRGB(rgb5,rgb5,rgb5); time.sleep(1) lcd.setRGB(rgb6,rgb6,rgb6); time.sleep(1) lcd.setRGB(rgb7,rgb7,rgb7); time.sleep(1) lcd.setRGB(rgb8,rgb8,rgb8); time.sleep(1) lcd.setRGB(rgb9,rgb9,rgb9); time.sleep(1)
LCD Library, RGB1602_01.py
# -*- coding: utf-8 -*- import time from machine import Pin,I2C #Device I2C Arress LCD_ADDRESS = (0x7c>>1) RGB_ADDRESS = (0xc0>>1) #color define REG_RED = 0x04 REG_GREEN = 0x03 REG_BLUE = 0x02 REG_MODE1 = 0x00 REG_MODE2 = 0x01 REG_OUTPUT = 0x08 LCD_CLEARDISPLAY = 0x01 LCD_RETURNHOME = 0x02 LCD_ENTRYMODESET = 0x04 LCD_DISPLAYCONTROL = 0x08 LCD_CURSORSHIFT = 0x10 LCD_FUNCTIONSET = 0x20 LCD_SETCGRAMADDR = 0x40 LCD_SETDDRAMADDR = 0x80 #flags for display entry mode LCD_ENTRYRIGHT = 0x00 LCD_ENTRYLEFT = 0x02 LCD_ENTRYSHIFTINCREMENT = 0x01 LCD_ENTRYSHIFTDECREMENT = 0x00 #flags for display on/off control LCD_DISPLAYON = 0x04 LCD_DISPLAYOFF = 0x00 LCD_CURSORON = 0x02 LCD_CURSOROFF = 0x00 LCD_BLINKON = 0x01 LCD_BLINKOFF = 0x00 #flags for display/cursor shift LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 LCD_MOVERIGHT = 0x04 LCD_MOVELEFT = 0x00 #flags for function set LCD_8BITMODE = 0x10 LCD_4BITMODE = 0x00 LCD_2LINE = 0x08 LCD_1LINE = 0x00 LCD_5x8DOTS = 0x00 class RGB1602(): def __init__(self, col=16, row=2, i2c=None): if isinstance(i2c, I2C) is False: print("RGB1602 requires a valid i2c device") raise TypeError self.RGB1602_I2C = i2c self._row = row self._col = col self._showfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; self.begin(self._row,self._col) def command(self,cmd): self.RGB1602_I2C.writeto_mem(LCD_ADDRESS, 0x80, chr(cmd)) def write(self,data): self.RGB1602_I2C.writeto_mem(LCD_ADDRESS, 0x40, chr(data)) def setReg(self,reg,data): self.RGB1602_I2C.writeto_mem(RGB_ADDRESS, reg, chr(data)) def setRGB(self,r,g,b): self.setReg(REG_RED,r) self.setReg(REG_GREEN,g) self.setReg(REG_BLUE,b) def setCursor(self,col,row): if(row == 0): col|=0x80 else: col|=0xc0; self.RGB1602_I2C.writeto(LCD_ADDRESS, bytearray([0x80,col])) def clear(self): self.command(LCD_CLEARDISPLAY) time.sleep(0.002) def printout(self,arg): if(isinstance(arg,int)): arg=str(arg) for x in bytearray(arg,'utf-8'): self.write(x) def display(self): self._showcontrol |= LCD_DISPLAYON self.command(LCD_DISPLAYCONTROL | self._showcontrol) def begin(self,cols,lines): if (lines > 1): self._showfunction |= LCD_2LINE self._numlines = lines self._currline = 0 time.sleep(0.05) # Send function set command sequence self.command(LCD_FUNCTIONSET | self._showfunction) #delayMicroseconds(4500); # wait more than 4.1ms time.sleep(0.005) # second try self.command(LCD_FUNCTIONSET | self._showfunction); #delayMicroseconds(150); time.sleep(0.005) # third go self.command(LCD_FUNCTIONSET | self._showfunction) # finally, set # lines, font size, etc. self.command(LCD_FUNCTIONSET | self._showfunction) # turn the display on with no cursor or blinking default self._showcontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF self.display() # clear it off self.clear() # Initialize to default text direction (for romance languages) self._showmode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT # set the entry mode self.command(LCD_ENTRYMODESET | self._showmode); # backlight init self.setReg(REG_MODE1, 0) # set LEDs controllable by both PWM and GRPPWM registers self.setReg(REG_OUTPUT, 0xFF) # set MODE2 values # 0010 0000 -> 0x20 (DMBLNK to 1, ie blinky mode) self.setReg(REG_MODE2, 0x20) self.setColorWhite() def setColorWhite(self): self.setRGB(255, 255, 255)
PS I will add to this post after I have looked at the Arduino library.