Připojíme Grove LCD display 16x2 s čipem JHD1802M1 k Pi pomocí I2C sběrnice a budeme měřit interní teplotu.
LCD display 16x2 s čipem JHD18002M1

Poznámka: Zespodu připájené 10k rezistory mezi SDA-Vcc, SCL-Vcc výrobce zapomněl zapojit.
Zapojení pinů na Raspbery Pi Pico

| Sběrnice | SDA pin (bílá) | SCL pin (žlutá) | Piny v MicroPythonu |
|---|---|---|---|
I2C 0 |
GP8 pin 11 |
GP9 pin 12 |
8 a 9 |
I2C 1 |
GP6 pin 9 |
GP7 pin 10 |
6 a 7 |
MicroPython
Modul grove_lcd_i2c.py
#
# Grove 16x2 I2C LCD (White on Blue)
# - https://my.cytron.io/p-grove-16-x-2-lcd-white-on-blue?tracking=idris
#
# Update:
# 22 Jan 2021 - Tested with MicroPython Pico V1.13-290-g556ae7914
#
from machine import Pin, I2C
import utime
class Grove_LCD_I2C(object):
# Commands
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_5x10DOTS = 0x04
LCD_5x8DOTS = 0x00
def __init__(self, i2c, address, oneline=False, charsize=LCD_5x8DOTS):
self.i2c = i2c
self.address = address
self.disp_func = self.LCD_DISPLAYON # | 0x10
if not oneline:
self.disp_func |= self.LCD_2LINE
elif charsize != 0:
# For 1-line displays you can choose another dotsize
self.disp_func |= self.LCD_5x10DOTS
# Wait for display init after power-on
utime.sleep_ms(50) # 50ms
# Send function set
self.cmd(self.LCD_FUNCTIONSET | self.disp_func)
utime.sleep_us(4500) ##time.sleep(0.0045) # 4.5ms
self.cmd(self.LCD_FUNCTIONSET | self.disp_func)
utime.sleep_us(150) ##time.sleep(0.000150) # 150µs = 0.15ms
self.cmd(self.LCD_FUNCTIONSET | self.disp_func)
self.cmd(self.LCD_FUNCTIONSET | self.disp_func)
# Turn on the display
self.disp_ctrl = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
self.display(True)
# Clear it
self.clear()
# Set default text direction (left-to-right)
self.disp_mode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
self.cmd(self.LCD_ENTRYMODESET | self.disp_mode)
def cmd(self, command):
assert command >= 0 and command < 256
command = bytearray([command])
self.i2c.writeto_mem(self.address, 0x80, bytearray([]))
self.i2c.writeto_mem(self.address, 0x80, command)
def write_char(self, c):
assert c >= 0 and c < 256
c = bytearray([c])
self.i2c.writeto_mem(self.address, 0x40, c)
def write(self, text):
for char in text:
if char == '\n':
self.cursor_position(0, 1)
else:
self.write_char(ord(char))
def cursor(self, state):
if state:
self.disp_ctrl |= self.LCD_CURSORON
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
else:
self.disp_ctrl &= ~self.LCD_CURSORON
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
def cursor_position(self, col, row):
col = (col | 0x80) if row == 0 else (col | 0xc0)
self.cmd(col)
def autoscroll(self, state):
if state:
self.disp_ctrl |= self.LCD_ENTRYSHIFTINCREMENT
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
else:
self.disp_ctrl &= ~self.LCD_ENTRYSHIFTINCREMENT
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
def blink(self, state):
if state:
self.disp_ctrl |= self.LCD_BLINKON
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
else:
self.disp_ctrl &= ~self.LCD_BLINKON
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
def display(self, state):
if state:
self.disp_ctrl |= self.LCD_DISPLAYON
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
else:
self.disp_ctrl &= ~self.LCD_DISPLAYON
self.cmd(self.LCD_DISPLAYCONTROL | self.disp_ctrl)
def clear(self):
self.cmd(self.LCD_CLEARDISPLAY)
utime.sleep_ms(2) # 2ms
def home(self):
self.cmd(self.LCD_RETURNHOME)
utime.sleep_ms(2) # 2m
main.py
#
# Read internal temperature in Raspberry Pi Pico
# and display to Grove I2C LCD
#
# Raspberry Pi Pico
# - [Bare Board] https://my.cytron.io/p-raspberry-pi-pico?tracking=idris
# - [Pre-soldered Headers] https://my.cytron.io/p-raspberry-pi-pico-pre-soldered-headers?tracking=idris
# - [Maker Pi Pico] https://my.cytron.io/p-maker-pi-pico?tracking=idris
# Grove 16x2 I2C LCD (White on Blue)
# - https://my.cytron.io/p-grove-16-x-2-lcd-white-on-blue?tracking=idris
#
# Update:
# 22 Jan 2021 - Tested with MicroPython Pico V1.13-290-g556ae7914
#
from machine import *
from utime import sleep
from grove_lcd_i2c import Grove_LCD_I2C
sleep(1)
print("MicroPython on Raspberry Pi Pico")
print()
temp_builtin = ADC(ADC.CORE_TEMP)
LCD_SDA = Pin(8) (1)
LCD_SCL = Pin(9)
LCD_ADDR = 62 # 0x3E or 62
i2c = I2C(0, sda=LCD_SDA, scl=LCD_SCL) (2)
print(i2c.scan())
lcd = Grove_LCD_I2C(i2c, LCD_ADDR)
lcd.home() (3)
lcd.write("Raspberry Pi\nPico") (4)
conversion_factor = 3.3 / (65535)
duty = 0
direction = 1
lcd.clear()
lcd.write("Internal Temp:")
while True:
for _ in range(256):
duty += direction
if duty > 255:
duty = 255
direction = -1
elif duty < 0:
duty = 0
direction = 1
sleep(0.001)
reading = temp_builtin.read_u16() * conversion_factor
temperature = 27 - (reading - 0.706)/0.001721
lcd.cursor_position(0, 1)
lcd.write("{:.2f}".format(temperature))
| 1 | Při zapojení do konektoru I2C0 se nastavují piny SDA=8 a SCL=9 |
| 2 | Nastavení I2C 0 |
| 3 | Nastavení domovské pozice (1.řádek, 1.znak) |
| 4 | Zápis na display. |
Fungující program

| Nejtěžší je správně nastavit piny SDA a SLC a potom I2C adresu. Je to vždy jinak, než se píše v návodech. |