CharLCD package

What it is

Pack of HD44780 lcd drivers to be used with Raspberry PI.
It gives functions to quickly control what is displayed and how.
Supports I2C and GPIO wiring.

Use two modes:

– direct – write to lcd asap
– buffered – write to buffer and do flush

Supports LCDs with size: 20×4, 16×2, 40×4 and so.

Supports virtual lcds – ability to join few lcd into one

Include simple game Piader that utilize lcd and show 2 fps :).

Git repository: https://bitbucket.org/kosci/charlcd/overview

Context:

Installation

From PyPi: pip install CharLCD

From bitbucket repository: pip install git+https://bitbucket.org/kosci/charlcd.git

Direct mode

This mode allows you to write chars to screen as needed. When you call write it will display char at once.

Buffered mode

This mode writes chars to buffer. And when you are ready call flush to display. Displaying will do as less work as possible by skipping  chars that are same in buffer and screen.

Basic usage

Before accessing LCD you need to define how it’s plugged. You have two options, by GPIO or I2C bus.

If you need some other way feel free to add new driver.

Lets imagine that you wired everything as I, so we will use default pins.

First imports:

from charlcd import buffered as lcd_buffered 
from charlcd.drivers.gpio import Gpio
from charlcd.drivers.i2c import I2C
from charlcd import direct as lcd_direct 

Create lcds:

lcd = lcd_direct.CharLCD(16, 2, Gpio())
lcd = lcd_buffered.CharLCD(20, 4, Gpio())

Both lcds are using Gpio driver. If you want to use I2C:

lcd = lcd_direct.CharLCD(16, 2, I2C(0x20, 1))

Screen is on address 0x20 on bus 1.

Default Wiring

GPIO 40×4

LCD13 [VSS] ------------ GND
LCD14 [VDD] ------------ +5V
LCD12 [V0] ------/\/\/\ [potentiometer]
                   \---- GND
LCD11 [RS] ------------- GPIO 25
LCD10 [R/W] ------------ GND
LCD9  [E1] ------------- GPIO 24
LCD15 [E2] ------------- GPIO 10
LCD4  [DB4] ------------ GPIO 22
LCD3  [DB5] ------------ GPIO 23
LCD2  [DB6] ------------ GPIO 27
LCD1  [DB7] ------------ GPIO 17
LCD17 [A] ------/\/\/\ [potentiometer]
                   \---- +5V
LCD18 [K] -------------- GND

GPIO 20×4, 16×2

LCD1 [VSS] ------------- GND
LCD2 [VDD] ------------- +5V
LCD3 [V0] ------/\/\/\ [potentiometer]
                   \---- GND
LCD4 [RS] -------------- GPIO 25
LCD5 [R/W] ------------- GND
LCD6 [E] --------------- GPIO 24
LCD7 [DB0]
LCD8 [DB1]
LCD9 [DB2]
LCD10 [DB3]
LCD11 [DB4] ------------ GPIO 22
LCD12 [DB5] ------------ GPIO 23
LCD13 [DB6] ------------ GPIO 27
LCD14 [DB7] ------------ GPIO 17
LCD15 [A] ------/\/\/\ [potentiometer]
                   \---- +5V
LCD16 [K] -------------- GND

I2C 20×4, 16×2

LCD                                           PCF8574
 1 -------- GND                     GND ----- A0   Vcc ---- +5V 
 2 -------- +5V                     GND ----- A1   SDA ---- SDA on RPi
 3 --/\/\ [potentiometer]           GND ----- A2   SCL ---- SCL on RPi
       \--- GND                   LCD11 ----- P0   INT 
 4 [RS]---- P4                    LCD12 ----- P1   P7
 5 -------- GND                   LCD13 ----- P2   P6
 6 [E]----- P5                    LCD14 ----- P3   P5 ----- LCD6
 7                                  GND ----- GND  P4 ----- LCD4
 8
 9
10
11 [DB4]--- P0
12 [DB5]--- P1
13 [DB6]--- P2
14 [DB7]--- P3
15 --/\/\ [potentiometer]
       \--- +5V
16 -------- GND

I2C 40×4

LCD                                           PCF8574
13 -------- GND                     GND ----- A0   Vcc ---- +5V 
14 -------- +5V                     GND ----- A1   SDA ---- SDA on RPi
12 --/\/\ [potentiometer]           GND ----- A2   SCL ---- SCL on RPi
       \--- GND                    LCD4 ----- P0   INT 
11 [RS]---- P4                     LCD3 ----- P1   P7
10 -------- GND                    LCD2 ----- P2   P6 ----- LCD15
 9 [E]----- P5                     LCD1 ----- P3   P5 ----- LCD9
15 [E2] --- P6                      GND ----- GND  P4 ----- LCD11
 4 [DB4]--- P0
 3 [DB5]--- P1
 2 [DB6]--- P2
 1 [DB7]--- P3
17 --/\/\ [potentiometer]
       \--- +5V
18 -------- GND

Custom wiring

There is an easy way to use own wiring and own pins. See:

    g = Gpio()
    g.pins = {
        'RS': 24,
        'E': 17,
        'DB4': 27,
        'DB5': 25,
        'DB6': 23,
        'DB7': 22
    }

    i2c = I2C(0x20, 1)
    i2c.pins = {
        'RS': 4,
        'E': 5,
        'DB4': 0,
        'DB5': 1,
        'DB6': 2,
        'DB7': 3
    }

and call:

l = lcd.CharLCD(20, 4, g)
l = lcd.CharLCD(20, 4, i2c)

What is virtual lcd (vlcd)

Imagine you have two LCDs, one 16×2 and second 20×4.  Next imagine that you want to have both of them stacked one top second bottom – so it would give you 20×6 or 16×6.

You can do it manually and do lots of ifs but much better way is to use vLCD.

How it works ? See code:

lcd_1 = lcd.CharLCD(16, 2, I2C(0x20, 1))
lcd_2 = lcd.CharLCD(20, 4, Gpio(), 0, 0)

We are creating two LCDs.

vlcd_1 = vlcd.CharLCD(16, 6)
vlcd_1.add_display(0, 0, lcd_2, 4, 0)
vlcd_1.add_display(0, 4, lcd_1)
vlcd_1.init()

We are creating one vlcd and adds both lcds to it. We are also using offset ability. It will give us such configuration:

layout_right

Now you can access it as normal lcd using write, set_xy or stream. Buffered has flush just like normal lcd. You don’t have to worry about where to display each char.

Big 40×4 lcd

This one require second enable signal. No problem:

    g = Gpio()
    g.pins = {
        'RS': 24,
        'E': 17,
        'E2': 10,
        'DB4': 27,
        'DB5': 25,
        'DB6': 23,
        'DB7': 22
    }

    i2c = I2C(0x20, 1)
    i2c.pins = {
        'RS': 4,
        'E': 5,
        'E2': 6,
        'DB4': 0,
        'DB5': 1,
        'DB6': 2,
        'DB7': 3
    }

and call:

l = lcd.CharLCD(40, 4, g)
l = lcd.CharLCD(40, 4, i2c)

Functions

CharLCD(width, height, driver, cursor_visible=1, cursor_blink=1) – initialize, lcd size, cursor options

write(self, string, pos_x=None, pos_y=None) – print string on lcd


lcd.write('- Blarg !')
lcd.write('- Grarg !', 0, 1)

set_xy(pos_x, pos_y) – move cursor to position

lcd.set_xy(10, 0)

get_xy() – get cursor position

stream(string) – stream string, breaks on line ends and after reaching end of display starts from top

lcd.stream("1234567890qwertyuiopasdfghjkl")

buffer_clear() – clears buffer (only buffered)

flush() – flush buffer to display (only buffered)

get_width() – display width

get_height() – display height

get_display_mode() – return direct or buffered

shutdown() – calls driver shutdown

Demos

Look into charlcd/demos on git.

Piader game

Simple game. Play with a, d and space.

Two lcds. One 20×4 and second 16×2.
From this two vlcds are made. One 16×6 for game and 4×4 for score.

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""Game launcher"""

__author__ = 'Bartosz Kościów'

import sys
sys.path.append("../")
import RPi.GPIO as GPIO #pylint: disable=I0011,F0401
from charlcd import buffered
from charlcd.drivers.gpio import Gpio
from charlcd.drivers.i2c import I2C
from charlcd import virtual_buffered
import piader_1_1.game as game

GPIO.setmode(GPIO.BCM)


def main():
    """set lcds and start game"""
    lcd_two = buffered.CharLCD(16, 2, I2C(0x20, 1), 0, 0)
    lcd_one = buffered.CharLCD(20, 4, Gpio(), 0, 0)

    vlcd_main = virtual_buffered.CharLCD(16, 6)
    vlcd_main.add_display(0, 0, lcd_one, 4, 0)
    vlcd_main.add_display(0, 4, lcd_two)
    vlcd_main.init()

    vlcd_support = virtual_buffered.CharLCD(4, 4)
    vlcd_support.add_display(0, 0, lcd_one)
    vlcd_support.init()

    my_game = game.Piader([vlcd_main, vlcd_support])
    my_game.game()


main()

Use 40×4 as game lcd:

    drv = I2C(0x3a, 1)
    drv.pins['E2'] = 6
    lcd_three = buffered.CharLCD(40, 4, drv, 0, 0)
    lcd_three.init()
    
    my_game = game.Piader([lcd_three, None])

Use 20×4 as game lcd:

    lcd_one.init()
    my_game = game.Piader([lcd_one, None])