Raspberry Pi to bardzo ciekawe i ostatnio popularne urządzenie. Ten minikomputer potrafi naprawdę dużo. Dzięki złączu GPIO (General Purpose Input/Output) możemy komunikować się z innymi urządzeniami systemu komputerowego np. z mikroprocesorami czy urządzeniami peryferyjnymi. Umożliwia nam to komunikację dwustronną tzn. zapis i odczyt. Jednym z prostszych zastosowań takiego złącza jest możliwość uruchomienia ekranu LCD i kontrolowaniu go przez Raspberry Pi.

Naszym celem było wyświetlenie prostego tekstu na ekranie oraz napisanie aplikacji, która pozwoli na pokazywanie aktualnej pogody w danym mieście.

Wyświetlacz LCD

Większość z dostępnych na rynku wyświetlaczy LCD 2×16 znaków jest zgodna ze standardem Hitachi HD44780. Model jaki podłączyliśmy to: WC1602A-STBLWHTC-06. Model z niebieskim podświetleniem pasuje do kolorystki naszego serwisu ;-)

Oznaczenie pinów na wyświetlaczu LCD

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Vss Vdd V0 RS R/W E DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7 LED+ LED-
  • Vss (source supply) – służy do podłączenia GND (uziemienie)
  • Vdd (drain supply) – zasilanie układu +5V
  • RS – w zależności od stanu (wysoki, niski) wyświetlacz oczekuje na dane lub instrukcje
  • R/W – stan niski przełącza LCD w tryb odbioru informacji poprzez linie DB0..DB7. Jest to tryb zapisu. Stan wysoki przełącza moduł do wysyłania informacji do zewnętrznego urządzenia. Dzięki R/W ustalamy kierunek komunikacji.
  • E (enable) – podanie impulsu na to wejście powoduje odebranie przez mikrosterownik HD44780 informacji z linii DB0..DB7 oraz RS i R/W.
  • DB0..DB7 – szyna danych.
  • LED+/LED- – są to piny zasilające +5V oraz GND wykorzystywane w LCDkach z podświetleniem.

Do sterowania wyświetlaczem poprzez GPIO wykorzystałem bibliotekę RPi.GPIO, której proces instalacji opisaliśmy w artykule.

Pogodynka na Raspberry Pi

Schemat podłączenia LCD pod Raspberry Pi

Ekran LCD podłączamy do GPIO zgodnie ze schematem zamieszczonym poniżej. Dla wygody możemy skorzystać z płytki uniwersalnej, do której przylutujemy kable. Można również skorzystać z taśmy np. 26pin.

Schemat podłączenia LCD pod Raspberry Pi

Pin: LCD Funkcja LCD PIN: Raspberry Pi Funkcja Raspberry Pi
01 GND (uziemienie) 06 GND (uziemienie)
02 +5V 02 +5V
03 Kontrast 06 GND (uziemienie)
04 RS 26 GPIO7
05 RW 06 GND (uziemienie)
06 E GPIO8 24
07 DB0    
08 DB1    
09 DB2    
10 DB3    
11 DB4 22 GPIO25
12 DB5 18 GPIO24
13 DB6 16 GPIO23
14 DB7 12 GPIO18
15 +5V przez 560 ohm    
16 GND (uziemienie) 06 GND (uziemienie)

Pogodynka w Pythonie

Prosty program napisany w Pythonie służy do wyświetlania znaków na ekranie LCD. Źródła dostępne są również w serwisie GitHub.

[python]#!/usr/bin/python
# -*- coding: utf-8 -*-
# HD44780 LCD Script for Raspberry Pi
#
# Author : Kamil Porembinski
# Site : https://osworld.pl
#
# Based on Matt’s Hawkins script
# Site : http://www.raspberrypi-spy.co.uk
#
# Date : 23/08/2012

#import
import RPi.GPIO as GPIO
import time
import urllib2
import re

# Script options
settings = {
# City to monitor (ex. "Lodz", "Warsaw, Cracow", …)
'city’ : 'Lodz’,
# Language of the conditions (ex. en, pl, fr, …)
'language’ : 'pl’,
}
GOOGLE_WEATHER_URL = 'http://www.google.com/ig/api?weather=%s&hl=%s&oe=utf-8′

# Define GPIO to LCD mapping
LCD_RS = 7
LCD_E = 8
LCD_D4 = 25
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18

# Define some device constants
LCD_WIDTH = 16 # Maximum characters per line
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line

# Timing constants
E_PULSE = 0.00005
E_DELAY = 0.00005
E_TIME = 5

def lcd_init():
# Initialise display
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)

def lcd_string(message):
# Send string to display
message = message.ljust(LCD_WIDTH,)

for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):
# Send byte to data pins
# bits = data
# mode = True for character
# False for command

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)

# Toggle 'Enable’ pin
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)

# Toggle 'Enable’ pin
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

def rmpl(text):
pl_tab = {u’ą’:’a’, u’ć’:’c’, u’ę’:’e’, u’ł’:’l’, u’ń’:’n’, u’ó’:’o’, u’ś’:’s’, u’ż’:’z’, u’ź’:’z’,u’Ą’:’A’, u’Ć’:’C’, u’Ę’:’E’, u’Ł’:’L’, u’Ń’:’N’, u’Ó’:’O’, u’Ś’:’S’, u’Ż’:’Z’, u’Ź’:’Z’}
return ”.join( pl_tab.get(char, char) for char in text )

def convert_mph(match):
try:
mph = int(match.group(0).split(’ ’)[0])
kph = mph*1.6
return "%s kph" % (int(round(kph)),)
except:
return match.group(0)

def get_weather_for_city():
from xml.dom.minidom import parseString
from xml.etree import ElementTree as ET

url = GOOGLE_WEATHER_URL % (settings["city"].replace(’ ’, '+’), settings["language"])

try:
source = urllib2.urlopen(url).read()
source = source.decode(’utf-8′, 'ignore’)
source = source.encode(’utf-8′)

etree = ET.fromstring(source)
weather = etree.find(’weather’)
except:
return("There was an error while retrieving data from the server.")

parts = []
out = {}
information = weather.find(’forecast_information’)

city = rmpl(information.find(’city’).get(’data’))
out["city"] = city

conditions = weather.find(’current_conditions’)

temperature = rmpl(conditions.find(’temp_c’).get(’data’) + 'C’)
out["temperature"] = "Temperatura: " + temperature

humidity = rmpl(conditions.find(’humidity’).get(’data’))
out["humidity"] = humidity

wind = rmpl(conditions.find(’wind_condition’).get(’data’))
wind = re.sub(’\d+ mph’, convert_mph, wind)
out["wind"] = wind

condition = rmpl(conditions.find(’condition’).get(’data’))
out["condition"] = condition

return out

def main():

# Main program block
GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers
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

# Initialise display
lcd_init()
while 1 == 1:
out = get_weather_for_city()
# Send some text
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(time.strftime(’ %H:%M:%S ’))
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(time.strftime(’ %d-%m-%Y ’))
time.sleep(E_TIME)
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(out["city"])
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(out["temperature"])
time.sleep(E_TIME)
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(out["humidity"])
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(out["condition"])
time.sleep(E_TIME)

if __name__ == '__main__’:
main()[/python]

Z racji tego, że jest to pierwszy mój program w Pythonie, liczę na poprawki do kodu ;-)

Poprzedni artykułSmuxi 0.8.10 Tracy
Następny artykułJądra Linux 3.0.42, 3.4.10 i 3.5.3

35 KOMENTARZE

  1. Bardzo fajnie i przejrzyście opisane oraz zilustrowane! Szkoda, że jestem antytalentem w lutowaniu i tego typu pracach – bo chętnie bym coś takiego chciał mieć. Może sprzedacie albo zrobicie mi takie coś? :P

  2. Jesteś pewny, że nie powinno tam być buforów konwertujących napięcia? RPi nie toleruje na GPIO więcej niż 3,3V. Co prawda w tej aplikacji zapisujesz dane do wyświetlacza, jednak z różnych przyczyn, na przykład zakłóceń w zasilaniu czy przypadkowym ustawieniu linii r/w na odczyt danych z LCD, może się zdarzyć, że ten wysteruje którąś z linii danych w stan wysoki (a jest zasilany z 5V) i z RPi – nie daj! – poleci "magiczny dymek".

  3. Wątek dość stary ale doszedłem do momentu kiedy przy próbie uruchomienia wyświetla się data i godzina i po dwóch sekundach pojawia się komunikat z pythona
    „Traceback (most recent call last):

    File „weather_lcd2.py”, line 200, in

    main()

    File „weather_lcd2.py”, line 189, in main

    lcd_string(out[„city”])

    TypeError: string indices must be integers, not str”

    I kompletnie nie mam pojęcia co to za babol..

ZOSTAW ODPOWIEDŹ

Proszę wpisać swój komentarz!
Proszę podać swoje imię tutaj