Doplnění českých znaků pro zobrazení na LCD displeji 1602. Zároveň měření teploty.

Knihovna Micropython LCD1602/LCD2004-I2C Lib

Knihovna lib_lcd1602_2004_with_i2c.py
'''
    mpy drive for I2C LCD1602
    Author: shaoziyang
    Date:   2018.2
    http://www.micropython.org.cn
'''
import time
from machine import SoftI2C, Pin


class LCD():
    def __init__(self, i2c):

        # board definition
        # P0: RS
        # P1: R/W
        # P2: E
        # P3: --
        # P4-P7: DB4-DB7

        self.i2c = i2c
        print('(Re)Initializing...')
        scan_result = i2c.scan()
        while not scan_result:
            print("Cannot Locate I2C Device")
            time.sleep_ms(10)
            scan_result = i2c.scan()
        self.LCD_I2C_ADDR = i2c.scan()[0]
        self.bufs = []  # a list of bytes, created as writing things all in one go with i2c.writeto is more efficient than writing each byte
        self.BK = 0x08
        self.RS = 0x00
        self.E = 0x04

        self.queue(0x30)  # 0011
        self.execute()
        time.sleep_ms(5)
        self.queue(0x30)  # 0011
        self.execute()
        time.sleep_ms(5)
        self.queue(0x20)  # 0010
        self.execute()
        time.sleep_ms(5)
        self.add_command(0x28,run=True)  # 0010   1000
        self.on()
        self.add_command(0x06)  # 0000   0110
        self.add_command(0x01)  # 0000   0001
        self.execute()

    def queue(self, dat):
        '''
        Add data to queue, wait execution
        :param dat: 8-bit data, first 4 bit is D7-D4, Last 4 bit is NC, E, RW, RS
        :return:
        '''

        dat = dat & 0xF0
        dat |= self.BK
        dat |= self.RS

        self.bufs.append(dat | 0x04) # enable high
        self.bufs.append(dat) # enable low

    def execute(self):
        try:
            bytearray_to_write = bytearray(len(self.bufs))
            for i in range(len(self.bufs)):
                bytearray_to_write[i] = self.bufs[i]
            self.i2c.writeto(self.LCD_I2C_ADDR, bytearray_to_write)
            self.bufs=[]
            time.sleep_us(50)
        except Exception as e:
            print(e)

    def add_command(self, cmd, run=False):
        self.RS = 0
        # I2C chip only has 8 bit, so only 4 bit can be used for data, thus the data needs to be send in two parts
        self.queue(cmd)
        self.queue(cmd << 4)
        if run:
            self.execute()

    def add_data(self, dat):
        self.RS = 1
        # I2C chip only has 8 bit, so only 4 bit can be used for data, thus the data needs to be send in two parts
        self.queue(dat)
        self.queue(dat << 4)

    def clear(self):
        self.add_command(1,run=True)

    def backlight(self, on):
        if on:
            self.BK = 0x08
        else:
            self.BK = 0
        self.add_command(0,run=True)

    def on(self):
        self.add_command(0x0C,run=True)  # 0000 1100 Turn on screen,  turn cursor off, turn blink off

    def off(self):
        self.add_command(0x08,run=True)  # 0000 1000 Turn off screen, turn cursor off, turn blink off

    def shl(self):
        self.add_command(0x18,run=True)

    def shr(self):
        self.add_command(0x1C,run=True)

    def char(self, ch, x=-1, y=0):
        if x >= 0:
            if y == 0:
                a = 0x80
            if y == 1:
                a = 0xC0
            if y == 2:
                a = 0x80 + 20
            if y == 3:
                a = 0xC0 + 20
            a += x
            self.add_command(a)
        self.add_data(ch)

    def puts(self, s, y=0, x=0):
        '''

        :param s: string, ascii only
        :param y: row (you need to write reasonable number to this parameter yourself)
        :param x: column (you need to write reasonable number to this parameter yourself)
        :return:
        '''
        try:
            if len(s) > 0:
                self.char(ord(s[0]), x, y)
                for i in range(1, len(s)):
                    self.char(ord(s[i]))
        except Exception as e:
            print(e)
        self.execute()

    def create_charactor(self, ram_position, char):
        '''

        :param position: int, 0-7
        :param char: 8 bytes
        :return:
        '''

        assert len(char)==8
        ram_position &= 0x7;
        set_CGRAM_address = 0x40
        self.add_command(set_CGRAM_address | (ram_position << 3))
        for i in range(8):
            self.add_data(char[i])
        self.execute()

Definice českých znaků

Znaky jsou definovány jednoduše, každý bit odpovídá tečce na displeji. Pokud je bit 1, tečka svítí; pokud je bit 0, tečka nesvítí.

Definice znaku á
# á
znak_a_acute = [
#     ------------- tyto sloupce se neopužívají
#     |||
    0b00000010,    # první  řádek teček
    0b00000100,    # druhý  řádek teček
    0b00001110,    # třetí  řádek teček
    0b00000001,    # čtvrtý řádek teček
    0b00001111,    # pátý   řádek teček
    0b00010001,    # šestý  řádek teček
    0b00001111,    # sedmý a poslední řádek teček
    0b00000000]    # osmý řádek teček se nepoužívá, protože je pod linkou
Znak á na displeji odpovídající výše uvedenému kódu

znak a dlouhe

Můžeme najednou nadefinovat pouze 8 znaků.

Použití definovaného znaku
lcd.create_charactor(0, znak_a_acute) (1)
line1 = "Jirka Chr" + chr(0) + "ska"  (2)
lcd.puts(line1, 0)                    (3)
1 Definujeme znak á pro použití na displeji na pozici 0.
2 Sestavíme řetězec, který chceme zobrazit.
3 Pošleme řetězec na displej (tady na první řádek).
main.py
from machine import Pin, SoftI2C
from lib_lcd1602_2004_with_i2c import LCD
import time
scl_pin = 17 # I2C0
sda_pin = 16 # I2C0
lcd = LCD(SoftI2C(scl=Pin(scl_pin), sda=Pin(sda_pin), freq=100000))
# Definice českých znaků
# á
znak_a_acute = [
    0b00000010,
    0b00000100,
    0b00001110,
    0b00000001,
    0b00001111,
    0b00010001,
    0b00001111,
    0b00000000]
# Á
znak_A_acute = [
    0b00000010,
    0b00000100,
    0b00001010,
    0b00010001,
    0b00011111,
    0b00010001,
    0b00010001,
    0b00000000]
# č
znak_c_caron = [
    0b00001010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00010000,
    0b00010001,
    0b00001110,
    0b00000000]
# Č
znak_C_caron = [
    0b00001010,
    0b00001110,
    0b00010001,
    0b00010000,
    0b00010000,
    0b00010001,
    0b00001110,
    0b00000000]
# ď
znak_d_caron = [
    0b00010101,
    0b00001001,
    0b00001101,
    0b00010011,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000]
# Ď
znak_D_caron = [
    0b00011101,
    0b00010010,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010010,
    0b00011100,
    0b00000000]
# é
znak_e_acute = [
    0b00000010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00011111,
    0b00010000,
    0b00001110,
    0b00000000]
# É
znak_E_acute = [
    0b00000010,
    0b00000100,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00000000]
# ě
znak_e_caron = [
    0b00001010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00011111,
    0b00010000,
    0b00001110,
    0b00000000]
# Ě
znak_E_caron = [
    0b00001010,
    0b00000100,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00000000]
# í
znak_i_acute = [
    0b00000010,
    0b00000100,
    0b00000000,
    0b00001100,
    0b00000100,
    0b00000100,
    0b00001110,
    0b00000000]
# Í
znak_I_acute = [
    0b00000010,
    0b00000101,
    0b00000000,
    0b00001110,
    0b00000100,
    0b00000100,
    0b00001110,
    0b00000000]
# ň
znak_n_caron = [
    0b00001010,
    0b00000100,
    0b00010110,
    0b00011101,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00000000]
# Ň
znak_N_caron = [
    0b00001010,
    0b00000100,
    0b00010001,
    0b00011001,
    0b00010101,
    0b00010011,
    0b00010001,
    0b00000000]
# ó
znak_o_acute = [
    0b00000010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000]
# Ó
znak_O_acute = [
    0b00000001,
    0b00001110,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000]
# ř
znak_r_caron = [
    0b00001010,
    0b00000100,
    0b00010110,
    0b00011001,
    0b00010000,
    0b00010000,
    0b00010000,
    0b00000000]
# Ř
znak_R_caron = [
    0b00001010,
    0b00011110,
    0b00010001,
    0b00010001,
    0b00011110,
    0b00010010,
    0b00010001,
    0b00000000]
# š
znak_s_caron = [
    0b00001010,
    0b00000100,
    0b00001111,
    0b00010000,
    0b00001110,
    0b00000001,
    0b00011110,
    0b00000000]
# Š
znak_S_caron = [
    0b00001010,
    0b00001111,
    0b00010000,
    0b00010000,
    0b00001110,
    0b00000001,
    0b00011110,
    0b00000000]
# ť
znak_t_caron = [
    0b00001101,
    0b00001010,
    0b00011100,
    0b00001000,
    0b00001000,
    0b00001001,
    0b00000110,
    0b00000000]
# Ť
znak_T_caron = [
    0b00001010,
    0b00011111,
    0b00000100,
    0b00000100,
    0b00000100,
    0b00000100,
    0b00000100,
    0b00000000]
# ú
znak_u_acute = [
    0b00000010,
    0b00000100,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010011,
    0b00001101,
    0b00000000]
# Ú
znak_U_acute = [
    0b00000010,
    0b00010101,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000]
# ů
znak_u_ogonek = [
    0b00000100,
    0b00001010,
    0b00010101,
    0b00010001,
    0b00010001,
    0b00010011,
    0b00001101,
    0b00000000]
# Ů
znak_U_ogonek = [
    0b00000100,
    0b00001010,
    0b00010101,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000]
# ý
znak_y_acute = [
    0b00000010,
    0b00000100,
    0b00010001,
    0b00010001,
    0b00001111,
    0b00010001,
    0b00001110,
    0b00000000]
# Ý
znak_Y_acute = [
    0b00000010,
    0b00010101,
    0b00010001,
    0b00001010,
    0b00000100,
    0b00000100,
    0b00001110,
    0b00000000]
# ž
znak_z_caron = [
    0b00001010,
    0b00000100,
    0b00011111,
    0b00000010,
    0b00000100,
    0b00001000,
    0b00011111,
    0b00000000]
# Ž
znak_Z_caron = [
    0b00001010,
    0b00010101,
    0b00000001,
    0b00000010,
    0b00000100,
    0b00001000,
    0b00011111,
    0b00000000]
# °
znak_degree = [
    0b00000110,
    0b00001001,
    0b00000110,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000]
# držtička
znak_drzticka = [
    0b00011111,
    0b00010101,
    0b00011111,
    0b00011011,
    0b00011111,
    0b00010001,
    0b00001110,
    0b00000000]

from machine import ADC
adc = ADC(ADC.CORE_TEMP)
conversion_factor = float(3.3 / (65535))
while True:
    # měření teploty
    result = adc.read_u16() * conversion_factor
    temp = 27 - (result - 0.706)/0.001721
    lcd.create_charactor(0, znak_a_acute)
    lcd.create_charactor(1, znak_degree)
    lcd.create_charactor(2, znak_drzticka)
    line1 = "Jirka Chr" + chr(0) + "ska " + chr(2)
    line2 = f"Teplota: {temp:.1f}" + chr(1) + "C"
    lcd.clear()
    lcd.puts(line1, 0)
    lcd.puts(line2, 1)
    time.sleep(3)
    lcd.create_charactor(0, znak_c_caron)
    lcd.create_charactor(1, znak_y_acute)
    lcd.create_charactor(2, znak_z_caron)
    lcd.create_charactor(3, znak_r_caron)
    # testování znaků
    #line2 = "Maličký ježeček"
    #line3 = "řeže pilčičkou"
    line2  = "Mali" + chr(0) + "k" + chr(1) + " je" + chr(2) + "e" + chr(0) + "ek"
    line3  = chr(3) + "e" + chr(2) + "e pil" + chr(0) + "i" + chr(0) + "kou."
    lcd.clear()
    lcd.puts(line2, 0)
    lcd.puts(line3, 1)
    time.sleep(3)

Konstrukce

Měření teploty

IMG 20250319 231815

Testování českých znaků

IMG 20250319 231819

Zdroje a odkazy