Malinowy wyświetlacz, a polske szlaczki

Ostatni mój wpis na temat małżeństwa Raspberry Pi z LCD Hitachi HD44780 został przyjęty z entuzjazmem, dlatego idąc jednocześnie za ciosem i prośbą niezalogowanego czytelnika @mielu007 pokusiłem się o sprawdzenie, czy na owym HD44780 możemy wyświetlić polskie znaki? Odpowiedź była prosta – na pewno się da, tylko jak?

Aby to zrobić musiałem troszeczkę zmodyfikować kod, który zamieściłem w poprzednim wypisie, ale na początek trochę teorii…

Teoria

Wyświetlacz HD44780 w swojej tablicy znaków nie posiada polskich liter, ale daje nam możliwość zdefiniowania 8 własnych znaków (8 wolnych bajtów w tablicy), które później musimy załadować do pamięci CGRAM. Ktoś zaraz powie… tylko osiem, ale lipa! otóż Panie/Panowie tak nie jest, wgrywać nowe znaki możemy na bieżąco (dynamicznie), ale sęk w tym że jednocześnie możemy korzystać tylko z tych 8 zdefiniowanych.Tyle teorii wystarczy 😉

Wykonie – definicja własnych znaków

Jak już pisałem wcześniej matryca tych znaków zapisywana jest w pamięci CGRAM o rozmiarze 8×8 bajtów. Jeden bajt definiuje jedną linię znaku. Osiem następnych bajtów definiuje cały znak – kolejność od góry. Do zaprojektowania swoich znaków użyłem programu „HD44780 – Generator własnych znaków” z strony bastek79.com, dzięki któremu namazałem 4 literki z ogonkami: ą, ę, ł, ó.

W moim przypadku interesuje mnie zapis heksadecymalny, bo takiego użyłem w swoim programie.

Wykonie – trochę węża

Poniżej znajdziecie mój kod rozszerzony o opisywaną funkcjonalność (zwrócie uwagę na komentarze):

#!/usr/bin/python
# definicja kodowania znakow
#-*- coding: utf-8 -*-
 
#Importujemy zainstalowana wczesniej biblioteke i biblioteke time
import RPi.GPIO as GPIO
import time
 
#Prze mapowanie pinow RPi na zmienne odpowiadajace nazwą pinow wyswietlacza
LCD_RS = 7
LCD_E  = 8
LCD_D4 = 25
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18
 
# Definicja stalych dla LCD
LCD_WIDTH = 24    # Maksymalna ilosc znakow na linie
LCD_CHR = True
LCD_CMD = False
 
LCD_LINE_1 = 0x80 # LCD RAM adres dla 1 linii
LCD_LINE_2 = 0xC0 # LCD RAM adres dla 2 linii
 
# Stale czasowe
E_PULSE = 0.00005
E_DELAY = 0.00005
 
# tablica adresow (pozycji) znakow dodatkowych
LCD_TAB_CHARS = [0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78]
########## Funkcja wpisujaca znak do tablicy CGRAM
def lcd_custom(pos,charDefHex):
  lcd_byte(LCD_TAB_CHARS[pos],LCD_CMD)
  for i in charDefHex:
    lcd_byte(i,LCD_CHR)
 
########## Funkcja glowna programu
def main():
 
  GPIO.setmode(GPIO.BCM)
  GPIO.setwarnings(False) #wylaczenie warningow
  GPIO.setup(LCD_E, GPIO.OUT)  # E
  GPIO.setup(LCD_RS, GPIO.OUT) # RS
  GPIO.setup(LCD_D4, GPIO.OUT) # DB4
  GPIO.setup(LCD_D5, GPIO.OUT) # DB5
  GPIO.setup(LCD_D6, GPIO.OUT) # DB6
  GPIO.setup(LCD_D7, GPIO.OUT) # DB7
 
  # Inicjalizacja wyswietlacza
  lcd_init()
  # definicja poszczegolnych liter - kolejno: spacja, ą, ę, ł, ó
  lcd_custom(0,[0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0F, 0x04, 0x06])
  lcd_custom(1,[0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E, 0x04, 0x06])
  lcd_custom(2,[0x0C, 0x04, 0x06, 0x0C, 0x04, 0x04, 0x0E, 0x00])
  lcd_custom(3,[0x02, 0x04, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x0])
 
  # wyslanie tekstu na pierwsza linie
  lcd_byte(LCD_LINE_1, LCD_CMD)
  lcd_string("dobreprogramy.pl")
  #wyslanie tekstu nadruga linie
  lcd_byte(LCD_LINE_2, LCD_CMD)
  lcd_string(u"i mamy PL znaki: ą ę ł ó")
 
########## Funkcja inicjalizujaca wyswietlacz
 
def lcd_init():
  lcd_byte(0x33,LCD_CMD)
  lcd_byte(0x32,LCD_CMD)
  lcd_byte(0x28,LCD_CMD)
  lcd_byte(0x0C,LCD_CMD)
  lcd_byte(0x06,LCD_CMD)
  lcd_byte(0x01,LCD_CMD)
 
# funkcja zmieniajaca litere z ogonkiem na zdefiniowany znak
def lcd_custom_rep( str ):
    new_str=u""
    for i in str:
        if i==u"ą":
            new_str+= chr(0)
        elif i==u"ę":
            new_str+= chr(1)
        elif i==u"ł":
            new_str+= chr(2)
        elif i==u"ó":
            new_str+= chr(3)
        else:
            new_str+=i
    return new_str
######### Funkcja wysylajaca string na konkretna linie i zmieniajaca ogonki
 
def lcd_string(message):
  message = lcd_custom_rep(message)
  message = message.ljust(LCD_WIDTH," ")
 
  for i in range(LCD_WIDTH):
    lcd_byte(ord(message{i}),LCD_CHR)
                     # literka "i" powinna byc w kwadratowym nawiasie!!!
                     #musialem to zmienic bo blogowy edytor sie gubil...
########## Funkcja wysylajaca dane do pinow
def lcd_byte(bits, mode):
  GPIO.output(LCD_RS, mode) # RS
 
  # High bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x10==0x10:
    GPIO.output(LCD_D4, True)
  if bits&0x20==0x20:
    GPIO.output(LCD_D5, True)
  if bits&0x40==0x40:
    GPIO.output(LCD_D6, True)
  if bits&0x80==0x80:
    GPIO.output(LCD_D7, True)
 
  # Przelaczenie pinu 6E
  time.sleep(E_DELAY)  
  GPIO.output(LCD_E, True)
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)
  time.sleep(E_DELAY)    
 
  # Low bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x01==0x01:
    GPIO.output(LCD_D4, True)
  if bits&0x02==0x02:
    GPIO.output(LCD_D5, True)
  if bits&0x04==0x04:
    GPIO.output(LCD_D6, True)
  if bits&0x08==0x08:
    GPIO.output(LCD_D7, True)
 
  # Przelaczenie pinu 6E
  time.sleep(E_DELAY)  
  GPIO.output(LCD_E, True)
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)
  time.sleep(E_DELAY) 
 
if __name__ == '__main__':
  main()

Finał…