Coder Social home page Coder Social logo

pylcd's Introduction

pyLCD – A library for controlling LCDs on various hardware backends

The instructions and tips below are for HD44780 compatible character LCDs. Using KS0108 compatible graphical LCDs is basically the same, only with different pin names and function names.

License

This program is licensed under the AGPLv3. See the LICENSE file for more information.

Installation

You can easily install the pyLCD lib using the Python Package Index. Just type:

sudo pip install pylcd

Hardware support

This library supports multiple hardware platforms for input and output.

Currently available output backends:

  • Velleman K8055 USB Experiment Interface Board
  • Raspberry Pi GPIO pins
  • Arduino pins using serial communication (Still in development)
  • Debug output showing the states of the interface pins
  • Dummy output that does nothing

Currently available input backends:

  • System standard input (e.g. Keyboard)
  • Raspberry Pi GPIO pins
  • No input

See the usage examples below for examples on how to use them.

Output pinmaps

When instantiating a display, you need to pass it a dictionary containing a mapping from pin names on the LCD to output numbers on the device you're connecting the LCD to. For a K8055, you might want to use this pinmap:

PINMAP = {
	'RS': 1,
	'RW': 2,
	'E': 3,
	'D4': 4,
	'D5': 5,
	'D6': 6,
	'D7': 7,
	'LED': 9,
}

Note that the backlight LED pin is numbered 9 here, even though the K8055 only has 8 digital outputs. But since there are two additional analog outputs, I numbered them 9 and 10 to avoid confusion. Using an analog output for backlight control enables you to dim the backlight by using PWM!

For a Raspberry Pi, you need to use WiringPi's WPI_MODE_GPIO pin numbering scheme. I connected my LCD as follows:

PINMAP = {
	'RS': 2,
	'RW': 3,
	'E': 4,
	'D4': 22,
	'D5': 10,
	'D6': 9,
	'D7': 11,
	'LED': 18,
}

By using pin 18 for the backlight control, it's once again possible to dim the backlight since this pin is the only available hardware PWM pin of the Pi, so I recommend using this one. If you are using the DebugBackend backend, the pin numbers don't matter.

Input pinmaps

If you are using an input module that uses I/O pins, you need to specify a pinmap for that module as well. Currently, only five keys are supported: Up, Left, OK, Right and Down, as well as two LEDs: Ready and Error. My pinmap looks like this:

INPUT_PINMAP = {
	'UP': 23,
	'LEFT': 7,
	'OK': 8,
	'RIGHT': 24,
	'DOWN': 25,
	'READY': 27,
	'ERROR': 22,
}

Character maps

You can also specify a character map to use for defining custom characters. This is a dictionary in the following format:

CHARMAP = {
	0: (
		0b10101,
		0b01010,
		0b10101,
		0b01010,
		0b10101,
		0b01010,
		0b10101,
		0b01010,
	),
}

The keys should be integers from 0 to 7, since the HD44780 can store up to 8 custom characters. The values should be tuples or lists of 8 integers, where each integer represents a line of the custom character. I recommend writing these integers in binary notation, since it's easy to see which pixels will be active and which won't if you do it this way.

You can also specify a single key, dir, to load custom characters from image files:

CHARMAP = {
	'dir': "/path/to/directory",
}

The specified directory should contain up to 8 image files (preferably in PNG format) numbered 0.<suffix> to 7.<suffix>. Each of these files must be 5 pixels wide and 8 pixels tall and should consist of black and white pixels, where a black pixel will translate into an active pixel on the display. To use this feature, you need to have the Python Imaging Library (PIL) installed.

User Interface

This library comes with a DisplayUI class which allows you to create simple text-based user interfaces with just a few lines of code! See the usage examples below. Have a look at the lcd.py file to see what is possible.

Usage examples

To initialize a standard 16x2 character LCD with a blinking cursor on a Raspberry Pi, you would do:

import hd44780
PINMAP = {} # Your pinmap here
display = hd44780.Display(backend = hd44780.GPIOBackend, pinmap = PINMAP, lines = 2, columns = 16)
display.set_display_enable(cursor = True, cursor_blink = True)
display.clear()
display.home()

To display a Yes / No dialog and react to the user's choice on said display, using physical keys attached to the Pi, do the following:

INPUT_PINMAP = {} # Your pinmap here
ui = hd44780.DisplayUI(display, hd44780.GPIOInput, input_kwargs = {'pinmap': INPUT_PINMAP})
selected_index, selected_text = ui.dialog("Proceed?", buttons = ("Yes", "No"))
if selected_index == 0:
	ui.message("Doing stuff...")
else:
	ui.message("Aborted.")

Note that if you are using the SystemInput input backend you need to be able to send keypresses to the terminal running the script, or else it won't be able to react to your input. For more examples I would suggest looking at the included example scripts.

pylcd's People

Contributors

catolynx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pylcd's Issues

RPi is getting stuck instead of running program

I am still unable to get any sort of output using this library with my 128x64 glcd (ks0108 driver). I tried using this really simple program:

PINMAP = {
	'RS': 2,
	'RW': 3,
	'E': 4,
  'D0': 26,
  'D1': 19,
  'D2': 13,
  'D3': 6,
	'D4': 5,
	'D5': 11,
	'D6': 9,
	'D7': 10,
  'CS1': 21,
  'CS2': 20,
  'RST': 16,
	'LED': 18
}

def main():
  print('Inside main()')
  display = pylcd.ks0108.Display(backend = pylcd.GPIOBackend, pinmap = PINMAP, debug = True)
  print('Initialized Display')
  draw = pylcd.ks0108.DisplayDraw(display)
  print('Drew Display')
  display.commit(full = True)
  print('Committed to Display')
  display.clear()
  print('Cleared Display')
  draw.line(64, 18, 127, 18)
  print('Drew line')
  display.commit()
  print('Committed')

if __name__ == '__main__':
  main()

However, I get the print statement of 'Inside main()', and then the entire RPi 0 gets stuck, it disconnects from wifi and ssh stops working, and the power led stops glowing. Please help me to at least get some sort of text/image on my lcd!

Unable to install pylcd with pip

I'm trying to install pylcd on a Raspberry Pi 4 with pip but it fails stating that hd44780 module is missing. Is this project supposed to be standalone, or do I need to install a dependency?

Log:

# pip install pylcd
Collecting pylcd
  Using cached pyLCD-1.1.3.tar.gz (72 kB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  error: subprocess-exited-with-error
  
  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> [22 lines of output]
      Traceback (most recent call last):
        File "/root/display_venv/lib64/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
          main()
        File "/root/display_venv/lib64/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/root/display_venv/lib64/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 118, in get_requires_for_build_wheel
          return hook(config_settings)
                 ^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-gu9n7gmt/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 325, in get_requires_for_build_wheel
          return self._get_build_requires(config_settings, requirements=['wheel'])
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-gu9n7gmt/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 295, in _get_build_requires
          self.run_setup()
        File "/tmp/pip-build-env-gu9n7gmt/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 487, in run_setup
          super().run_setup(setup_script=setup_script)
        File "/tmp/pip-build-env-gu9n7gmt/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 311, in run_setup
          exec(code, locals())
        File "<string>", line 5, in <module>
        File "/tmp/pip-install-6mwrc4y3/pylcd_b27ca0eeb13a4db298f8e31a2776be32/pylcd/__init__.py", line 4, in <module>
          import hd44780
      ModuleNotFoundError: No module named 'hd44780'
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

[notice] A new release of pip is available: 23.2.1 -> 24.0
[notice] To update, run: pip install --upgrade pip

ImportError: No module named PIL

I had a clean installation of (a raspberryPI running) raspbian. During the mentioned installation procedure pip came up with that error message:
ImportError: No module named PIL

The following worked for me:

  • apt-get install python-dev python-imaging
  • apt-get install libjpeg-dev libfreetype6 libfreetype6-dev zlib1g-dev - not sure if you need that step
  • pip install pylcd

IOError @ ks0108.py

Hi,
after running a modified version of glcd_countdown.py for over 24hours successfully, it ran into an exception.

...
[24.08. 23:44:31] root      -DEBUG main                    :93   2.37 seconds needed to redraw
Traceback (most recent call last):
  File "glcd_countdown.py", line 97, in <module>
  File "glcd_countdown.py", line 74, in main
  File "/usr/local/lib/python2.7/dist-packages/pylcd/ks0108.py", line 378, in text
  File "/usr/lib/python2.7/dist-packages/PIL/ImageFont.py", line 218, in truetype
  File "/usr/lib/python2.7/dist-packages/PIL/ImageFont.py", line 134, in __init__
IOError: cannot open resource

And my glcd_countdown.py:74-97 looks like the following:

74:                draw.text(nowPlusDelta.strftime("%H:%M"), ('center', 0, 56), 34, 20, font=const_default_font)
75:                draw.text(nowPlusDelta.strftime("%d.%m.%y"), ('center', 0, 56), 52, 12, font=const_default_font)
76:
77:                # fill the right box
78:                #draw.image("/home/pi/projects/pyLCD/ef20.png", 'left', 'top')
79:                draw.text("PV real: %s W" % nutDataHub.get_specific_var("pv2.input.power"), x=('center', 58, 127), y=1, size=9, font=const_default_font)
80:                draw.text("PV inp: %s W" % nutDataHub.get_specific_var("pv1.input.power"), x=('center', 58, 127), y=10, size=9, font=const_default_font)
81:                draw.text("Output: %s W" % nutDataHub.get_specific_var("output.power"), x=('center', 58, 127), y=19, size=9, font=const_default_font)
82:                draw.text("Batt: %s %%" % nutDataHub.get_specific_var("battery.charge"), x=('center', 58, 127), y=28, size=9, font=const_default_font)
83:                draw.text("Day: %s Wh" % nutDataHub.get_specific_var("energy.day"), x=('center', 58, 127), y=40, size=9, font=const_default_font)
84:
85:
86:                draw.line(56, 0, 56, 64)
87:                draw.line(57, 0, 57, 64)
88:                draw.line(0, 31, 57, 31)
89:                draw.line(0, 32, 57, 32)
90:
91:                display.commit()
92:                time_needed = (datetime.now() - now).total_seconds()
93:                logging.debug("%.2f seconds needed to redraw" % time_needed)
94:                sleep(7)
95:
96: if __name__ == "__main__":
97:         main()

Do you have any clue? Best

MCP23017 IO Expander

Hi,

I've just done a quick clone/convert for a backend for the MCP23017 GPI expander chip, use it as you will. It's not been tested or checked in any way yet as I'm not near my pi - just came across your code and liked it, so will be using it for my project, plus my little addition!

Notes: Needs some code to read and set individual pins as input/output instead of all at once, and there is unfortunately no PWM available AFAIK for the chip.

class MCP23017Backend:
    # For the 16 pin MCP23017 (can also be used for the 8 pin version, but need to check for lack of pins
    # useful quick reference for the pin definitions that you can use in the pinmap
    a = [(0x12, 0), (0x12, 1), (0x12, 2), (0x12, 3), (0x12, 4), (0x12, 5), (0x12, 6), (0x12, 7)]
    b = [(0x13, 0), (0x13, 1), (0x13, 2), (0x13, 3), (0x13, 4), (0x13, 5), (0x13, 6), (0x13, 7)]

    def __init__(self, display, pinmap, bus_id, address):       # bus_id is the i2c interface, address is 0x20/21/22 etc. (hex address of i2c address )
        self.display = display
        try:
            import smbus
            from time import sleep
            self.bus = smbus.SMBus(bus_id)
        except:
            raise IOError("Could not export the MCP23017. Make sure that you have the smbus library installed, run as root and are on a Raspberry Pi.")
        self.address = address.

        self.reverse_pinmap = dict([(value, key) for key, value in pinmap.iteritems()])
        self.bus.write_byte_data(self.address, 0x00, 0)    # 1 is for input
        self.bus.write_byte_data(self.address, 0x01, 0)    # 1 is for input

    def high(self, output):
        value = self.bus.read_byte_data(self.address, register)
        value |= (1 << pin)
        self.bus.write_byte_data(self.address, register, value)

    def low(self, output):
        value = self.bus.read_byte_data(self.address, register)
        value &= ~(1 << pin)
        self.bus.write_byte_data(self.address, register, value)

    def pulse(self, output):
        self.high(output)
        time.sleep(0.001)
        self.low(output)

    def all_low(self):
        for output in self.reverse_pinmap.keys():
            self.low(output)

    def write_nibble(self, nibble, data = True):
        self.write_bit(self.PIN_RS, data)
        self.write_bit(self.PIN_D4, nibble[3])
        self.write_bit(self.PIN_D5, nibble[2])
        self.write_bit(self.PIN_D6, nibble[1])
        self.write_bit(self.PIN_D7, nibble[0])

    def write_bit(self, pin, bit):
        if (bit):
            self.high(pin)
        else:
            self.low(pin)

    def write_byte(self, byte, data = True):
        self.write_bit(self.PIN_RS, data)
        for i in range(8):
            self.write_bit(getattr(self, "PIN_D%i" % i), byte[i])


    def set_brightness(self, level):
        assert level >= 0
        assert level <= 1023
        self.display.brightness = level
        self.write_bit(self.PIN_LED, level > 0)

KS0108 display GLCD is not working

I installed pyLCD and followed the current issues to see if my problem would be described in any of them and I have yet to get this working..

I had to change the pinout of the glcd_*.py scripts, I will show my PINMAP below..

The error I have been getting on my Raspberry Pi Zero SSH output:

pi@raspberrypi:~/pyLCD $ sudo python examples/glcd_countdown.py Traceback (most recent call last): File "examples/glcd_countdown.py", line 106, in <module> main() File "examples/glcd_countdown.py", line 52, in main draw = pylcd.ks0108.DisplayDraw(display) AttributeError: 'module' object has no attribute 'DisplayDraw' pi@raspberrypi:~/pyLCD $

And my PINMAP:

`PINMAP = {
'RS': 4,
'RW': 7,
'E': 8,
'D0': 9,
'D1': 10,
'D2': 11,
'D3': 14,
'D4': 15,
'D5': 17,
'D6': 18,
'D7': 25,
'CS1': 22,
'CS2': 23,
'RST': 24,

'LED': 7,

}`

I'm really stuck on this part, as there is little KS0108 documentation as the GitHub repo claims..
Any help would be greatly appreciated!

pip could not find/download PIL

Hi (again),
seems like PIL has been replaced by its successor pillow, in the pip repository for raspberry's.

Now pip tries to fulfill this dependency by unsuccessfully trying to install it, with the following error:

Downloading/unpacking PIL (from pylcd)
  Could not find any downloads that satisfy the requirement PIL (from pylcd)

I successfully used the following as a workaround sudo pip install pylcd --no-deps after issuing a apt-get install python-dev python-imaging libjpeg-dev libfreetype6 libfreetype6-dev zlib1g-dev

KS0108 GLCD with 3 chip select pins is not working

Hello.

I am having an issue with a KS0108 (192x64 with 3 chip select pins) and pyLCD.

I am using the 'glcd_system_monitor_threaded.py' and 'glcd_system_monitor.py' example scripts.
The scripts run fine, however the image on the GLCD is not working as I'd assume it might..
I had to disable the UART inside of my '/boot/config.txt' with the directive 'enable_uart=0' due to the lack of output pins on the Raspberry Pi Zero unit.
I am using the 'gpio readall' command to compare my wiring from the BCM pins to the pins inside of my pinmap configuration section of each script.

Am I perhaps missing something, or doing something incorrectly to cause this?
Or is there a limitation to pyLCD which only allows support for GLCD's with only 2 chip select pins?
If so how simple would it be to possibly implement a patch so that it can support a 3 chip KS0108 device?

My pin configuration is as follows:
PINMAP = {
'RW': 14,
'RS': 7,
'E': 8,
'D0': 25,
'D1': 24,
'D2': 11,
'D3': 9,
'D4': 10,
'D5': 22,
'D6': 27,
'D7': 17,
'CS1': 3,
'CS2': 4,
'CS3': 15,
'RST': 2,
'LED': 18,
}

Kind regards

BeagleBone

Hello! Can i use this code in a BeagleBoneBlack? Im searching for some Graphical LCD library, and this is the only one that i found that maybe can solve my problem

Wiringpi & raspberry pi problem

Hi! Please, if you could help me, I am trying to use a KS0108 glcd display (model on this link: http://pdf.datasheetcatalog.com/datasheet_pdf/wstar/WG12864A.pdf), I used the same pinmap of your script of the countdown (glcd_countdown.py) but when I try to run that example it raises that exception about not connecting to the GPIO pins and asking for installing wiringpi. I have installed Gordon's wiringpi and Python's module on this link (https://github.com/WiringPi/WiringPi-Python), but the error still persists, please, can you help me? My Pi is a model B.

Thank you

Help to display data in both CS1 and CS2 of GLCD JHD128X64E

hey @Mezgrman,

I need some help regarding displaying so basically i wrote a program from scratch to drive the KS0108 based glcd and i'm able to display data in CS1 and CS2 separately but i'm not able to write a long string it break on pixel 63 and starts to rewrite from 0 how do make it to continuously write by making use of both chips at once

Sorry for raising this as an issue i didn't know how else to contact you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.