Showing entries tagged as: python

IMDB MKV file renamer: Quick and dirty Python script using IMDbPY and Enzyme.

By isendev.

 Posted on 2014/06/26 23:10.

 Tagged as: programming, python.

This is a quick and dirty Python script to rename video files using IMDb movie info and Matroska meta stream information. It uses my own conventions, but it may be an useful point to start your own script.

The resulting filenames are something like this:

Ocean's Eleven.(2001).x264[1080p].AC3[EN].AC3[ES].SUBS[ES][EN].mkv

To use this script, you must install IMDBpy (to retrieve IMDb movie info) and Enzyme (Matroska meta data parser) Python libraries.

Using pip Python package manager:

sudo pip install IMDbPY

sudo pip install enzyme

<imdbrenamer.py>

#!/usr/bin/python
# IMDB MKV file renamer.
# By: Antonio Perdices.
# Site: https://www.isendev.com
# 26/06/2014

import imdb
import enzyme
import os

# By default access the web.
ia = imdb.IMDb()

# Root directory.
rootdir = '/usbhdd/Unsorted/'

# Get files from directory.
files = os.listdir(rootdir)

# Loop through them.
for file in files:
   
    # Split filename and extension.
    fileName, fileExtension = os.path.splitext(file)
   
    # Process file confirmation.
    inputtext = ''
    while inputtext != 'n' and inputtext != 'y':
        inputtext = raw_input('\nProcessing file ['  + fileName + fileExtension + ']... Continue [y/n]? ')
        # print 'Input text is [' + inputtext + ']'

    # File processing.
    if inputtext == 'y':

        # Set IMBD search string. "Enter" defaults search string to filename.
        f = fileName.split('.')
        searchstring = f[0]
        inputtext = raw_input('IMDB Search String ['  + searchstring + ']: ')
        if len(inputtext) > 0:
            searchstring = inputtext

        # Search.
        print 'Searching IMDB with [' + searchstring + ']...'
        s_result = ia.search_movie(searchstring)

        # Print results.
        index = 1
        print '(0) - ORIGINAL - ' + fileName
        for item in s_result:
            try:
                print '({}) - Year {} - '.format(index, item['year']) + item['title']
            except KeyError:
                print '({}) - '.format(index) + item['title']
            index = index + 1

        # Title selection.
        index = -1
        while index < 0 or index > len(s_result):
            inputtext = raw_input('Select an Title entry [0]: ')
            if len(inputtext) > 0:
                try:
                    index = int(inputtext)
                except ValueError:
                    index = -1
                    # print 'Invalid entry!'
            else:
                index = 0

        # Confirm selected title.
        if index == 0:
            title = f[0]
        else:
            title = s_result[index-1]['title']
            title = title.replace('/', '').replace('\\', '').replace('?', '').replace('*', '')
            title = title.replace('|', '').replace('>', '').replace('<', '').replace(':', '')
        inputtext = raw_input('Title to use ['  + title + ']: ')
        if len(inputtext) > 0:
            title = inputtext
       
        # Confirm selected year.
        year = '2014'
        if index > 0:
            year = s_result[index-1]['year']
        inputtext = raw_input('Year to use [{}]: '.format(year))
        if len(inputtext) > 0:
            year = inputtext

        # Get MKV Info
        streamtags = ''
        try:
            with open(rootdir + file, 'rb') as m:

                print 'Extracting MKV Metadata...'

                mkv = enzyme.MKV(m)

                mkvinfo = ''
               
                # Get video stream info.
                vinfo=''
                if mkv.video_tracks[0].height <= 480:
                    vinfo = '.[DVD]'
                if mkv.video_tracks[0].height > 480:
                    vinfo = '.x264[720p]'
                if mkv.video_tracks[0].height > 720:
                    vinfo = '.x264[1080p]'           

                mkvinfo = 'Video: [' +  mkv.video_tracks[0].codec_id + '][' + '{}'.format(mkv.video_tracks[0].width) + '][' +  '{}'.format(mkv.video_tracks[0].height) + ']'

                # Get audio stream info.
                ainfo = ''
                for atrack in mkv.audio_tracks:
                    ainfo = ainfo + '.' + atrack.codec_id.replace('A_','')               
                    if atrack.language == 'spa' or atrack.language == 'es':
                        ainfo = ainfo + '[ES]'
                    elif atrack.language == 'eng' or atrack.language == 'en':
                        ainfo = ainfo + '[EN]'
                    else:
                        ainfo = ainfo + '[EN]'
                    mkvinfo = mkvinfo + '\nAudio: [' + atrack.codec_id + '][' + (atrack.language if atrack.language else 'None') + ']'


                # Get subtitle stream info.
                sinfo = ''
                for strack in mkv.subtitle_tracks:
                    if sinfo == '':
                        sinfo = '.SUBS'
                    if strack.forced == True:
                        sinfo = sinfo + '[FOR]'
                    elif strack.language == 'spa' or strack.language == 'es':
                        sinfo = sinfo + '[ES]'
                    elif strack.language == 'eng' or strack.language == 'en':
                        sinfo = sinfo + '[EN]'
                    else:
                        sinfo = sinfo + '[EN]'
                    mkvinfo = mkvinfo + '\nSubtitle: [' + strack.codec_id + '][' + (strack.language if strack.language else 'None') + ']'

                # Print stream info.
                print mkvinfo

                # Generate my own stream tags.
                streamtags = vinfo + ainfo + sinfo

                inputtext = raw_input('Use this stream tags ['  + streamtags + ']: ')
                if len(inputtext) > 0:
                    streamtags = '.' + inputtext
       
        except (IOError, enzyme.exceptions.MalformedMKVError):
            print 'No metadata found.'
                   
        # Rename.
        newFileName = title + '.({})'.format(year) + streamtags + fileExtension
        while inputtext != 'n' and inputtext != 'y':
            inputtext = raw_input('Renaming file to ['  + newFileName + ']... Continue [y/n]? ')
        if inputtext == 'y':
            os.rename(rootdir + file, rootdir + newFileName)


How to install PSUtil python library on the Raspberry Pi.

By isendev.

 Posted on 2014/03/05 22:21.

 Tagged as: programming, python.

As a side note to my previous Raspberry Pi LCD blog entries, these are the steps to install the required PSUtil python package using Pip.

What is PSUtil?

PSUtil is a cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network) in Python.
What is Pip?

Pip is a modern, general purpose installation tool for python packages.
Steps.

Install first the Linux basic build utilities package (already installed in default Raspbian distribution), the Pip package manager and the default python development libraries from the Raspbian repositories:

sudo apt-get install build-essential python-dev python-pip

Then call PIP to install psutil package:

sudo pip install psutil

Check for correct installation. This command must not throw errors.

sudo python -c "import psutil"


Raspberry Pi + LCD + Python (System Information)

By isendev.

 Posted on 2014/01/14 22:07.

 Tagged as: hardware, programming, diy, python.

Here is the Python code to use the HD44780 compatible LCD as a simple, but quite useful, system information monitor. The source has been separated in 3 files, for better understanding (lcd.py, sysinfo.py and lcd.sysinfo.py). It currently shows Memory, CPU, Filesystem and Network information, but can be easily modified to include other information provided by PSUtil (process and netstat information, I/O statistics, etc.).

<lcd.py>

Functions used to manage the 20x4 LCD display through the Raspberry Pi GPIO port.

#!/usr/bin/python
# 20x4 LCD Control Functions.
# Original code by: Matt Hawkins
# Site: http://www.raspberrypi-spy.co.uk
# Modified by: Antonio Perdices.
# Site: https://www.isendev.com
# 14/01/2014

# LCD Wiring.
# 1 : GND                    - TO GROUND
# 2 : 5V                     - TO +5V
# 3 : Contrast (0-5V)        - TO 10K POT OUTPUT
# 4 : RS (Register Select)
# 5 : R/W (Read Write)       - TO GROUND
# 6 : Enable or Strobe
# 7 : Data Bit 0             - NOT USED
# 8 : Data Bit 1             - NOT USED
# 9 : Data Bit 2             - NOT USED
# 10: Data Bit 3             - NOT USED
# 11: Data Bit 4
# 12: Data Bit 5
# 13: Data Bit 6
# 14: Data Bit 7
# 15: Backlight 5V           - NOT USED
# 16: Backlight GND          - NOT USED

# Imports.
import RPi.GPIO as GPIO
import time

# GPIO to LCD Mapping.
# Using Broadcom GPIO numbers
LCD_RS = 7
LCD_E  = 8
LCD_D4 = 25
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18

# Constants.

# Max chars per line.
LCD_WIDTH = 20

# LCD Byte Mode. 'Character' or 'Command'.
LCD_CHR = True
LCD_CMD = False

# 1st Line LCD RAM address.
LCD_LINE_1 = 0x80
# 2nd Line LCD RAM address.
LCD_LINE_2 = 0xC0
# 3rd Line LCD RAM address.
LCD_LINE_3 = 0x94
# 4th Line LCD RAM address.
LCD_LINE_4 = 0xD4

# Timing constants.
E_PULSE = 0.00005
E_DELAY = 0.00005

# Enable GPIO.
def lcd_gpio_enable():

    # Disable warnings.
    GPIO.setwarnings(False)

    # Use Broadcom GPIO numbers.
    GPIO.setmode(GPIO.BCM)

    # Enable GPIO outputs.
    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

# Init display function.
def lcd_init():

    # Init commands.
    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)

# Send byte data to display.
# bits = data.
# mode = 'True' for character or 'False' for command.
def lcd_byte(bits, mode):

    # Register Select.
    GPIO.output(LCD_RS, mode)

    # Send 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)

# Send string to display.
# Style parameter:
# 1 = Left justified.
# 2 = Centred.
# 3 = Right justified.
def lcd_string(message,style):

    if style==1:
        message = message.ljust(LCD_WIDTH," ")
    elif style==2:
        message = message.center(LCD_WIDTH," ")
    elif style==3:
        message = message.rjust(LCD_WIDTH," ")

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

# Blank LCD.
def lcd_clear():

    lcd_byte(LCD_LINE_1, LCD_CMD)
    lcd_string("",2)
    lcd_byte(LCD_LINE_2, LCD_CMD)
    lcd_string("",2)
    lcd_byte(LCD_LINE_3, LCD_CMD)
    lcd_string("",2)
    lcd_byte(LCD_LINE_4, LCD_CMD)
    lcd_string("",2)

<sysinfo.py>

Functions to get system information using PSUtil, a cross-platform process and system utilities module for Python.

#!/usr/bin/python
# System Information Functions.
# Author: Antonio Perdices.
# Site: https://www.isendev.com
# 14/01/2014

# Imports.
import lcd
import psutil
import subprocess

# Show memory info.
def lcd_show_mem():

    MEM_TOTAL_LABEL = "MEM Total:"
    MEM_TOTAL = "%(mem).2fMB" % {'mem': psutil.virtual_memory().total/1024.0/1024.0}
    MEM_TOTAL = MEM_TOTAL.rjust(lcd.LCD_WIDTH - len(MEM_TOTAL_LABEL)," ")

    MEM_FREE_LABEL = "MEM Free:"
    MEM_FREE = "%(mem).2fMB" % {'mem': psutil.virtual_memory().free/1024.0/1024.0}
    MEM_FREE = MEM_FREE.rjust(lcd.LCD_WIDTH - len(MEM_FREE_LABEL)," ")

    SWAP_TOTAL_LABEL = "SWAP Total:"
    SWAP_TOTAL = "%(mem).2fMB" % {'mem': psutil.swap_memory().total/1024.0/1024.0}
    SWAP_TOTAL = SWAP_TOTAL.rjust(lcd.LCD_WIDTH - len(SWAP_TOTAL_LABEL)," ")

    SWAP_FREE_LABEL = "SWAP Free:"
    SWAP_FREE = "%(mem).2fMB" % {'mem': psutil.swap_memory().free/1024.0/1024.0}
    SWAP_FREE = SWAP_FREE.rjust(lcd.LCD_WIDTH - len(SWAP_FREE_LABEL)," ")

    lcd.lcd_byte(lcd.LCD_LINE_1, lcd.LCD_CMD)
    lcd.lcd_string(MEM_TOTAL_LABEL + MEM_TOTAL, 1)
    lcd.lcd_byte(lcd.LCD_LINE_2, lcd.LCD_CMD)
    lcd.lcd_string(MEM_FREE_LABEL + MEM_FREE, 1)
    lcd.lcd_byte(lcd.LCD_LINE_3, lcd.LCD_CMD)
    lcd.lcd_string(SWAP_TOTAL_LABEL + SWAP_TOTAL, 1)
    lcd.lcd_byte(lcd.LCD_LINE_4, lcd.LCD_CMD)
    lcd.lcd_string(SWAP_FREE_LABEL + SWAP_FREE, 1)

# Show cpu info.
def lcd_show_cpu():

    CPU_READ = psutil.cpu_times_percent(interval=1, percpu=False)

    CPU_USER_LABEL = "CPU User:"
    CPU_USER = "%(cpu).2f%%" % {'cpu': CPU_READ.user}
    CPU_USER = CPU_USER.rjust(lcd.LCD_WIDTH - len(CPU_USER_LABEL)," ")

    CPU_NICE_LABEL = "CPU Nice:"
    CPU_NICE = "%(cpu).2f%%" % {'cpu': CPU_READ.nice}
    CPU_NICE = CPU_NICE.rjust(lcd.LCD_WIDTH - len(CPU_NICE_LABEL)," ")

    CPU_SYSTEM_LABEL = "CPU System:"
    CPU_SYSTEM = "%(cpu).2f%%" % {'cpu': CPU_READ.system}
    CPU_SYSTEM = CPU_SYSTEM.rjust(lcd.LCD_WIDTH - len(CPU_SYSTEM_LABEL)," ")

    CPU_IDLE_LABEL = "CPU Idle:"
    CPU_IDLE = "%(cpu).2f%%" % {'cpu': CPU_READ.idle}
    CPU_IDLE = CPU_IDLE.rjust(lcd.LCD_WIDTH - len(CPU_IDLE_LABEL)," ")

    lcd.lcd_byte(lcd.LCD_LINE_1, lcd.LCD_CMD)
    lcd.lcd_string(CPU_USER_LABEL + CPU_USER, 1)
    lcd.lcd_byte(lcd.LCD_LINE_2, lcd.LCD_CMD)
    lcd.lcd_string(CPU_NICE_LABEL + CPU_NICE, 1)
    lcd.lcd_byte(lcd.LCD_LINE_3, lcd.LCD_CMD)
    lcd.lcd_string(CPU_SYSTEM_LABEL + CPU_SYSTEM, 1)
    lcd.lcd_byte(lcd.LCD_LINE_4, lcd.LCD_CMD)
    lcd.lcd_string(CPU_IDLE_LABEL + CPU_IDLE, 1)

# Show filesystem info.
def lcd_show_fsinfo():

    FS_READ = psutil.disk_usage('/')

    FS_TOTAL_LABEL = "SD Total:"
    FS_TOTAL = "%(disk).2fGB" % {'disk': FS_READ.total/1024.0/1024.0/1024.0}
    FS_TOTAL = FS_TOTAL.rjust(lcd.LCD_WIDTH - len(FS_TOTAL_LABEL)," ")

    FS_FREE_LABEL = "SD Free:"
    FS_FREE = "%(disk).2fGB" % {'disk': FS_READ.free/1024.0/1024.0/1024.0}
    FS_FREE = FS_FREE.rjust(lcd.LCD_WIDTH - len(FS_FREE_LABEL)," ")

    FS_USED_LABEL = "SD Used:"
    FS_USED = "%(disk).2fGB" % {'disk': FS_READ.used/1024.0/1024.0/1024.0}
    FS_USED = FS_USED.rjust(lcd.LCD_WIDTH - len(FS_USED_LABEL)," ")

    FS_PERCENT_LABEL = "SD Used %:"
    FS_PERCENT = "%(disk).2f%%" % {'disk': FS_READ.percent}
    FS_PERCENT = FS_PERCENT.rjust(lcd.LCD_WIDTH - len(FS_PERCENT_LABEL)," ")

    lcd.lcd_byte(lcd.LCD_LINE_1, lcd.LCD_CMD)
    lcd.lcd_string(FS_TOTAL_LABEL + FS_TOTAL, 1)
    lcd.lcd_byte(lcd.LCD_LINE_2, lcd.LCD_CMD)
    lcd.lcd_string(FS_FREE_LABEL + FS_FREE, 1)
    lcd.lcd_byte(lcd.LCD_LINE_3, lcd.LCD_CMD)
    lcd.lcd_string(FS_USED_LABEL + FS_USED, 1)
    lcd.lcd_byte(lcd.LCD_LINE_4, lcd.LCD_CMD)
    lcd.lcd_string(FS_PERCENT_LABEL + FS_PERCENT, 1)

# Show network info.
def lcd_show_netinfo(interface):

    IP_READ = subprocess.check_output(["/sbin/ifconfig", interface])

    IP_ADDRESS_LABEL = "ADD:"
    if not "addr:" in IP_READ:
        IP_ADDRESS = "0.0.0.0"
    else:
        IP_ADDRESS = IP_READ.split("\n")[1].split()[1][5:]
    IP_ADDRESS = IP_ADDRESS.rjust(lcd.LCD_WIDTH - len(IP_ADDRESS_LABEL)," ")

    IP_MASK_LABEL = "MSK:"
    if not "addr:" in IP_READ:
        IP_MASK = "0.0.0.0"
    else:
        IP_MASK = IP_READ.split("\n")[1].split()[3][5:]
    IP_MASK = IP_MASK.rjust(lcd.LCD_WIDTH - len(IP_MASK_LABEL)," ")

    IP_READ = subprocess.check_output(["/sbin/ip", "route"])

    IP_GW_LABEL = "GTW:"
    if not "default" in IP_READ:
        IP_GW = "0.0.0.0"
    else:
        IP_GW = IP_READ.split("\n")[0].split()[2]
    IP_GW = IP_GW.rjust(lcd.LCD_WIDTH - len(IP_GW_LABEL)," ")

    IP_NET_LABEL = "NET:"
    if not "default" in IP_READ:
        IP_NET = "0.0.0.0"
    else:
        IP_NET = IP_READ.split("\n")[1].split()[0]
    IP_NET = IP_NET.rjust(lcd.LCD_WIDTH - len(IP_NET_LABEL)," ")

    lcd.lcd_byte(lcd.LCD_LINE_1, lcd.LCD_CMD)
    lcd.lcd_string(IP_ADDRESS_LABEL + IP_ADDRESS, 1)
    lcd.lcd_byte(lcd.LCD_LINE_2, lcd.LCD_CMD)
    lcd.lcd_string(IP_MASK_LABEL + IP_MASK, 1)
    lcd.lcd_byte(lcd.LCD_LINE_3, lcd.LCD_CMD)
    lcd.lcd_string(IP_GW_LABEL + IP_GW, 1)
    lcd.lcd_byte(lcd.LCD_LINE_4, lcd.LCD_CMD)
    lcd.lcd_string(IP_NET_LABEL + IP_NET, 1)

<lcd.sysinfo.py>

Main program.

#!/usr/bin/python
# 20x4 LCD System Information Script for Raspberry Pi.
# Author: Antonio Perdices.
# Site: https://www.isendev.com
# 14/01/2014

# Imports.
import time
import lcd
import sysinfo

LOOP_TIME = 5

# Main program.
def main():

    # Enable GPIO.
    lcd.lcd_gpio_enable()

    # Init display.
    lcd.lcd_init()

    # Write message to console.
    # print("Press Ctrl+C to exit...")

    COUNTER = 1

    # Main loop.
    while True:

        if (COUNTER % 4 == 0):
            sysinfo.lcd_show_mem()
            COUNTER = COUNTER + 1
        elif (COUNTER % 4 == 1):
            sysinfo.lcd_show_cpu()
            COUNTER = COUNTER + 1
        elif (COUNTER % 4 == 2):
            sysinfo.lcd_show_netinfo("eth0")
            COUNTER = COUNTER + 1
        else:
            sysinfo.lcd_show_fsinfo()
            COUNTER = 0

        time.sleep(LOOP_TIME)

# Execute main program.
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("\nKeyboard interrupt detected... Bye!")
        lcd.lcd_clear()
        pass

<lcd.init>

If you want to run the display program at startup, here is an init script for Debian.

### BEGIN INIT INFO
# Provides: LCD - CPU / Memory / Filesystem / Network
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Liquid Crystal Display
# Description: LCD - CPU / Memory / Filesystem / Network
### END INIT INFO

#! /bin/sh
# /etc/init.d/lcd

export HOME
case "$1" in
    start)
        echo "Starting LCD..."
        /root/Dev.LCD/lcd.sysinfo/lcd.sysinfo.py 2>&1 &
    ;;
    stop)
        echo "Stopping LCD..."
        LCD_PID=`ps auxwww | grep lcd.sysinfo.py | head -1 | awk '{print $2}'`
        kill -9 $LCD_PID
    ;;
    *)
        echo "Usage: /etc/init.d/lcd {start|stop}"
        exit 1
    ;;
esac
exit 0


Raspberry Pi + LCD + Python (Clock)

By isendev.

 Posted on 2014/01/01 18:56.

 Tagged as: hardware, programming, diy, python.

I've been playing a bit with my Raspberry PI - LCD combo, and I've come with this code. It shows a simple clock that refreshes every second. Nothing really fancy here, just a proof of concept. What I really want is to show some Raspberry Pi system information on the display. Something relatively easy using the psutil python library.

#!/usr/bin/python
# 20x4 LCD Clock Script for Raspberry Pi.
# Original code by: Matt Hawkins
# Site: http://www.raspberrypi-spy.co.uk
# Modified by: Antonio Perdices.
# Site: https://www.isendev.com
# 01/01/2014

# LCD Wiring.
# 1 : GND                    - TO GROUND
# 2 : 5V                     - TO +5V
# 3 : Contrast (0-5V)        - TO 10K POT OUTPUT
# 4 : RS (Register Select)
# 5 : R/W (Read Write)       - TO GROUND
# 6 : Enable or Strobe
# 7 : Data Bit 0             - NOT USED
# 8 : Data Bit 1             - NOT USED
# 9 : Data Bit 2             - NOT USED
# 10: Data Bit 3             - NOT USED
# 11: Data Bit 4
# 12: Data Bit 5
# 13: Data Bit 6
# 14: Data Bit 7
# 15: Backlight 5V           - NOT USED
# 16: Backlight GND          - NOT USED

# Imports.
import RPi.GPIO as GPIO
import time
import datetime

# GPIO to LCD Mapping.
# Using Broadcom GPIO numbers
LCD_RS = 7
LCD_E  = 8
LCD_D4 = 25
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18

# Constants.

# Max chars per line.
LCD_WIDTH = 20

# LCD Byte Mode. 'Character' or 'Command'.
LCD_CHR = True
LCD_CMD = False

# 1st Line LCD RAM address.
LCD_LINE_1 = 0x80
# 2nd Line LCD RAM address.
LCD_LINE_2 = 0xC0
# 3rd Line LCD RAM address.
LCD_LINE_3 = 0x94
# 4th Line LCD RAM address.
LCD_LINE_4 = 0xD4

# Timing constants.
E_PULSE = 0.00005
E_DELAY = 0.00005

# Main program.
def main():

    # Disable warnings.
    GPIO.setwarnings(False)

    # Use Broadcom GPIO numbers.
    GPIO.setmode(GPIO.BCM)

    # Enable GPIO outputs.
    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

    # Init display.
    lcd_init()

    # Write blank lines.
    lcd_byte(LCD_LINE_1, LCD_CMD)
    lcd_string("",2)
    lcd_byte(LCD_LINE_4, LCD_CMD)
    lcd_string("",2)

    # Write message to console.
    print("Press Ctrl+C to exit...")

    # Main loop.
    while True:
        lcd_byte(LCD_LINE_2, LCD_CMD)
        lcd_string(datetime.datetime.now().strftime('%d/%B/%Y'),2)
        lcd_byte(LCD_LINE_3, LCD_CMD)
        lcd_string(datetime.datetime.now().strftime('%H:%M:%S'),2)
        time.sleep(1)

    # Cleaning Up.
    # GPIO.cleanup()

# Init display function.
def lcd_init():

    # Init commands.
    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)

# Send byte data to display.
# bits = data.
# mode = 'True' for character or 'False' for command.
def lcd_byte(bits, mode):

    # Register Select.
    GPIO.output(LCD_RS, mode)

    # Send 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)

# Send string to display.
# Style parameter:
# 1 = Left justified.
# 2 = Centred.
# 3 = Right justified.
def lcd_string(message,style):

    if style==1:
        message = message.ljust(LCD_WIDTH," ")
    elif style==2:
        message = message.center(LCD_WIDTH," ")
    elif style==3:
        message = message.rjust(LCD_WIDTH," ")

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

# Execute main program.
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("\nKeyboard interrupt detected... Bye!")
        lcd_byte(LCD_LINE_2, LCD_CMD)
        lcd_string("",2)
        lcd_byte(LCD_LINE_3, LCD_CMD)
        lcd_string("",2)
        pass


Tags
Archives