Question: Ok so I have code to work with the adafruit lcd for the raspberry pi but I don't know the packages that I need to
Ok so I have code to work with the adafruit lcd for the raspberry pi but I don't know the packages that I need to include to make it work for the lcd. What I did was copy the I2C.py file for the adafruit and deleted the code portion and added mine. My question is what do I need to change/delete/alter on the file to make it work correctly, any help would be greatly appreciated.
#!/usr/bin/python
# Python library for Adafruit RGB-backlit LCD plate for Raspberry Pi.
# Written by Adafruit Industries. MIT license.
# This is essentially a complete rewrite, but the calling syntax
# and constants are based on code from lrvick and LiquidCrystal.
# lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py
# LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp
from Adafruit_I2C import Adafruit_I2C
from time import sleep
class Adafruit_CharLCDPlate(Adafruit_I2C):
# ----------------------------------------------------------------------
# Constants
# Port expander registers
MCP23017_IOCON_BANK0 = 0x0A # IOCON when Bank 0 active
MCP23017_IOCON_BANK1 = 0x15 # IOCON when Bank 1 active
# These are register addresses when in Bank 1 only:
MCP23017_GPIOA = 0x09
MCP23017_IODIRB = 0x10
MCP23017_GPIOB = 0x19
# Port expander input pin definitions
SELECT = 0
RIGHT = 1
DOWN = 2
UP = 3
LEFT = 4
# LED colors
OFF = 0x00
RED = 0x01
GREEN = 0x02
BLUE = 0x04
YELLOW = RED + GREEN
TEAL = GREEN + BLUE
VIOLET = RED + BLUE
WHITE = RED + GREEN + BLUE
ON = RED + GREEN + BLUE
# LCD Commands
LCD_CLEARDISPLAY = 0x01
LCD_RETURNHOME = 0x02
LCD_ENTRYMODESET = 0x04
LCD_DISPLAYCONTROL = 0x08
LCD_CURSORSHIFT = 0x10
LCD_FUNCTIONSET = 0x20
LCD_SETCGRAMADDR = 0x40
LCD_SETDDRAMADDR = 0x80
# Flags for display on/off control
LCD_DISPLAYON = 0x04
LCD_DISPLAYOFF = 0x00
LCD_CURSORON = 0x02
LCD_CURSOROFF = 0x00
LCD_BLINKON = 0x01
LCD_BLINKOFF = 0x00
# Flags for display entry mode
LCD_ENTRYRIGHT = 0x00
LCD_ENTRYLEFT = 0x02
LCD_ENTRYSHIFTINCREMENT = 0x01
LCD_ENTRYSHIFTDECREMENT = 0x00
# Flags for display/cursor shift
LCD_DISPLAYMOVE = 0x08
LCD_CURSORMOVE = 0x00
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00
# Line addresses for up to 4 line displays. Maps line number to DDRAM address for line.
LINE_ADDRESSES = { 1: 0xC0, 2: 0x94, 3: 0xD4 }
# Truncation constants for message function truncate parameter.
NO_TRUNCATE = 0
TRUNCATE = 1
TRUNCATE_ELLIPSIS = 2
# ----------------------------------------------------------------------
# Constructor
def __init__(self, busnum=-1, addr=0x20, debug=False, backlight=ON):
self.i2c = Adafruit_I2C(addr, busnum, debug)
# I2C is relatively slow. MCP output port states are cached
# so we don't need to constantly poll-and-change bit states.
self.porta, self.portb, self.ddrb = 0, 0, 0b00000010
# Set initial backlight color.
c = ~backlight
self.porta = (self.porta & 0b00111111) | ((c & 0b011) << 6)
self.portb = (self.portb & 0b11111110) | ((c & 0b100) >> 2)
# Set MCP23017 IOCON register to Bank 0 with sequential operation.
# If chip is already set for Bank 0, this will just write to OLATB,
# which won't seriously bother anything on the plate right now
# (blue backlight LED will come on, but that's done in the next
# step anyway).
self.i2c.bus.write_byte_data(
self.i2c.address, self.MCP23017_IOCON_BANK1, 0)
# Brute force reload ALL registers to known state. This also
# sets up all the input pins, pull-ups, etc. for the Pi Plate.
self.i2c.bus.write_i2c_block_data(
self.i2c.address, 0,
[ 0b00111111, # IODIRA R+G LEDs=outputs, buttons=inputs
self.ddrb , # IODIRB LCD D7=input, Blue LED=output
0b00111111, # IPOLA Invert polarity on button inputs
0b00000000, # IPOLB
0b00000000, # GPINTENA Disable interrupt-on-change
0b00000000, # GPINTENB
0b00000000, # DEFVALA
0b00000000, # DEFVALB
0b00000000, # INTCONA
0b00000000, # INTCONB
0b00000000, # IOCON
0b00000000, # IOCON
0b00111111, # GPPUA Enable pull-ups on buttons
0b00000000, # GPPUB
0b00000000, # INTFA
0b00000000, # INTFB
0b00000000, # INTCAPA
0b00000000, # INTCAPB
self.porta, # GPIOA
self.portb, # GPIOB
self.porta, # OLATA
self.portb ]) # OLATB
# Switch to Bank 1 and disable sequential operation.
# From this point forward, the register addresses do NOT match
# the list immediately above. Instead, use the constants defined
# at the start of the class. Also, the address register will no
# longer increment automatically after this -- multi-byte
# operations must be broken down into single-byte calls.
self.i2c.bus.write_byte_data(
self.i2c.address, self.MCP23017_IOCON_BANK0, 0b10100000)
self.displayshift = (self.LCD_CURSORMOVE |
self.LCD_MOVERIGHT)
self.displaymode = (self.LCD_ENTRYLEFT |
self.LCD_ENTRYSHIFTDECREMENT)
self.displaycontrol = (self.LCD_DISPLAYON |
self.LCD_CURSOROFF |
self.LCD_BLINKOFF)
self.write(0x33) # Init
self.write(0x32) # Init
self.write(0x28) # 2 line 5x8 matrix
self.write(self.LCD_CLEARDISPLAY)
self.write(self.LCD_CURSORSHIFT | self.displayshift)
self.write(self.LCD_ENTRYMODESET | self.displaymode)
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
self.write(self.LCD_RETURNHOME)
# ----------------------------------------------------------------------
# Write operations
# The LCD data pins (D4-D7) connect to MCP pins 12-9 (PORTB4-1), in
# that order. Because this sequence is 'reversed,' a direct shift
# won't work. This table remaps 4-bit data values to MCP PORTB
# outputs, incorporating both the reverse and shift.
flip = ( 0b00000000, 0b00010000, 0b00001000, 0b00011000,
0b00000100, 0b00010100, 0b00001100, 0b00011100,
0b00000010, 0b00010010, 0b00001010, 0b00011010,
0b00000110, 0b00010110, 0b00001110, 0b00011110 )
# Low-level 4-bit interface for LCD output. This doesn't actually
# write data, just returns a byte array of the PORTB state over time.
# Can concatenate the output of multiple calls (up to 8) for more
# efficient batch write.
def out4(self, bitmask, value):
hi = bitmask | self.flip[value >> 4]
lo = bitmask | self.flip[value & 0x0F]
return [hi | 0b00100000, hi, lo | 0b00100000, lo]
# The speed of LCD accesses is inherently limited by I2C through the
# port expander. A 'well behaved program' is expected to poll the
# LCD to know that a prior instruction completed. But the timing of
# most instructions is a known uniform 37 mS. The enable strobe
# can't even be twiddled that fast through I2C, so it's a safe bet
# with these instructions to not waste time polling (which requires
# several I2C transfers for reconfiguring the port direction).
# The D7 pin is set as input when a potentially time-consuming
# instruction has been issued (e.g. screen clear), as well as on
# startup, and polling will then occur before more commands or data
# are issued.
pollables = ( LCD_CLEARDISPLAY, LCD_RETURNHOME )
# Write byte, list or string value to LCD
def write(self, value, char_mode=False):
""" Send command/data to LCD """
# If pin D7 is in input state, poll LCD busy flag until clear.
if self.ddrb & 0b00000010:
lo = (self.portb & 0b00000001) | 0b01000000
hi = lo | 0b00100000 # E=1 (strobe)
self.i2c.bus.write_byte_data(
self.i2c.address, self.MCP23017_GPIOB, lo)
while True:
# Strobe high (enable)
self.i2c.bus.write_byte(self.i2c.address, hi)
# First nybble contains busy state
bits = self.i2c.bus.read_byte(self.i2c.address)
# Strobe low, high, low. Second nybble (A3) is ignored.
self.i2c.bus.write_i2c_block_data(
self.i2c.address, self.MCP23017_GPIOB, [lo, hi, lo])
if (bits & 0b00000010) == 0: break # D7=0, not busy
self.portb = lo
# Polling complete, change D7 pin to output
self.ddrb &= 0b11111101
self.i2c.bus.write_byte_data(self.i2c.address,
self.MCP23017_IODIRB, self.ddrb)
bitmask = self.portb & 0b00000001 # Mask out PORTB LCD control bits
if char_mode: bitmask |= 0b10000000 # Set data bit if not a command
# If string or list, iterate through multiple write ops
if isinstance(value, str):
last = len(value) - 1 # Last character in string
data = [] # Start with blank list
for i, v in enumerate(value): # For each character...
# Append 4 bytes to list representing PORTB over time.
# First the high 4 data bits with strobe (enable) set
# and unset, then same with low 4 data bits (strobe 1/0).
data.extend(self.out4(bitmask, ord(v)))
# I2C block data write is limited to 32 bytes max.
# If limit reached, write data so far and clear.
# Also do this on last byte if not otherwise handled.
if (len(data) >= 32) or (i == last):
self.i2c.bus.write_i2c_block_data(
self.i2c.address, self.MCP23017_GPIOB, data)
self.portb = data[-1] # Save state of last byte out
data = [] # Clear list for next iteration
elif isinstance(value, list):
# Same as above, but for list instead of string
last = len(value) - 1
data = []
for i, v in enumerate(value):
data.extend(self.out4(bitmask, v))
if (len(data) >= 32) or (i == last):
self.i2c.bus.write_i2c_block_data(
self.i2c.address, self.MCP23017_GPIOB, data)
self.portb = data[-1]
data = []
else:
# Single byte
data = self.out4(bitmask, value)
self.i2c.bus.write_i2c_block_data(
self.i2c.address, self.MCP23017_GPIOB, data)
self.portb = data[-1]
# If a poll-worthy instruction was issued, reconfigure D7
# pin as input to indicate need for polling on next call.
if (not char_mode) and (value in self.pollables):
self.ddrb |= 0b00000010
self.i2c.bus.write_byte_data(self.i2c.address,
self.MCP23017_IODIRB, self.ddrb)
# ----------------------------------------------------------------------
# Utility methods
def begin(self, cols, lines):
self.currline = 0
self.numlines = lines
self.numcols = cols
self.clear()
# Puts the MCP23017 back in Bank 0 + sequential write mode so
# that other code using the 'classic' library can still work.
# Any code using this newer version of the library should
# consider adding an atexit() handler that calls this.
def stop(self):
self.porta = 0b11000000 # Turn off LEDs on the way out
self.portb = 0b00000001
sleep(0.0015)
self.i2c.bus.write_byte_data(
self.i2c.address, self.MCP23017_IOCON_BANK1, 0)
self.i2c.bus.write_i2c_block_data(
self.i2c.address, 0,
[ 0b00111111, # IODIRA
self.ddrb , # IODIRB
0b00000000, # IPOLA
0b00000000, # IPOLB
0b00000000, # GPINTENA
0b00000000, # GPINTENB
0b00000000, # DEFVALA
0b00000000, # DEFVALB
0b00000000, # INTCONA
0b00000000, # INTCONB
0b00000000, # IOCON
0b00000000, # IOCON
0b00111111, # GPPUA
0b00000000, # GPPUB
0b00000000, # INTFA
0b00000000, # INTFB
0b00000000, # INTCAPA
0b00000000, # INTCAPB
self.porta, # GPIOA
self.portb, # GPIOB
self.porta, # OLATA
self.portb ]) # OLATB
def clear(self):
self.write(self.LCD_CLEARDISPLAY)
def home(self):
self.write(self.LCD_RETURNHOME)
row_offsets = ( 0x00, 0x40, 0x14, 0x54 )
def setCursor(self, col, row):
if row > self.numlines: row = self.numlines - 1
elif row < 0: row = 0
self.write(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))
def display(self):
""" Turn the display on (quickly) """
self.displaycontrol |= self.LCD_DISPLAYON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def noDisplay(self):
""" Turn the display off (quickly) """
self.displaycontrol &= ~self.LCD_DISPLAYON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def cursor(self):
""" Underline cursor on """
self.displaycontrol |= self.LCD_CURSORON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def noCursor(self):
""" Underline cursor off """
self.displaycontrol &= ~self.LCD_CURSORON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def ToggleCursor(self):
""" Toggles the underline cursor On/Off """
self.displaycontrol ^= self.LCD_CURSORON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def blink(self):
""" Turn on the blinking cursor """
self.displaycontrol |= self.LCD_BLINKON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def noBlink(self):
""" Turn off the blinking cursor """
self.displaycontrol &= ~self.LCD_BLINKON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def ToggleBlink(self):
""" Toggles the blinking cursor """
self.displaycontrol ^= self.LCD_BLINKON
self.write(self.LCD_DISPLAYCONTROL | self.displaycontrol)
def scrollDisplayLeft(self):
""" These commands scroll the display without changing the RAM """
self.displayshift = self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT
self.write(self.LCD_CURSORSHIFT | self.displayshift)
def scrollDisplayRight(self):
""" These commands scroll the display without changing the RAM """
self.displayshift = self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT
self.write(self.LCD_CURSORSHIFT | self.displayshift)
def leftToRight(self):
""" This is for text that flows left to right """
self.displaymode |= self.LCD_ENTRYLEFT
self.write(self.LCD_ENTRYMODESET | self.displaymode)
def rightToLeft(self):
""" This is for text that flows right to left """
self.displaymode &= ~self.LCD_ENTRYLEFT
self.write(self.LCD_ENTRYMODESET | self.displaymode)
def autoscroll(self):
""" This will 'right justify' text from the cursor """
self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
self.write(self.LCD_ENTRYMODESET | self.displaymode)
def noAutoscroll(self):
""" This will 'left justify' text from the cursor """
self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
self.write(self.LCD_ENTRYMODESET | self.displaymode)
def createChar(self, location, bitmap):
self.write(self.LCD_SETCGRAMADDR | ((location & 7) << 3))
self.write(bitmap, True)
self.write(self.LCD_SETDDRAMADDR)
def message(self, text, truncate=NO_TRUNCATE):
""" Send string to LCD. Newline wraps to second line"""
lines = str(text).split(' ') # Split at newline(s)
for i, line in enumerate(lines): # For each substring...
address = self.LINE_ADDRESSES.get(i, None)
if address is not None: # If newline(s),
self.write(address) # set DDRAM address to line
# Handle appropriate truncation if requested.
linelen = len(line)
if truncate == self.TRUNCATE and linelen > self.numcols:
# Hard truncation of line.
self.write(line[0:self.numcols], True)
elif truncate == self.TRUNCATE_ELLIPSIS and linelen > self.numcols:
# Nicer truncation with ellipses.
self.write(line[0:self.numcols-3] + '...', True)
else:
self.write(line, True)
def backlight(self, color):
c = ~color
self.porta = (self.porta & 0b00111111) | ((c & 0b011) << 6)
self.portb = (self.portb & 0b11111110) | ((c & 0b100) >> 2)
# Has to be done as two writes because sequential operation is off.
self.i2c.bus.write_byte_data(
self.i2c.address, self.MCP23017_GPIOA, self.porta)
self.i2c.bus.write_byte_data(
self.i2c.address, self.MCP23017_GPIOB, self.portb)
# Read state of single button
def buttonPressed(self, b):
return (self.i2c.readU8(self.MCP23017_GPIOA) >> b) & 1
# Read and return bitmask of combined button state
def buttons(self):
return self.i2c.readU8(self.MCP23017_GPIOA) & 0b11111
import time
from time import time
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
# Adafruit object
LCD_disp = Adafruit_CharLCDPlate()
# declare the required variables
Inp_NICKEL = 5
Inp_DIME = 10
Inp_QUARTER = 25
tot = 0
# method to print the total
def print_total():
LCD_disp.clear()
LCD_disp.message(' Total: $.')
LCD_disp.message(tot)
# loop code to continuously process input
while (tot<=30):
# code to represent switches on the Adafruit LCD
LCD_disp.message("Todays Paper Only 30 Cents.")
if LCD_disp.buttonPressed(LCD_disp.LEFT):
tot = tot + Inp_NICKEL
print_total()
sleep(1)
'elif LCD_disp.buttonPressed(LCD_disp.RIGHT):'
tot = tot + Inp_DIME
print_total()
sleep(1)
'elif LCD_disp.buttonPressed(LCD_disp.DOWN):'
tot = tot + Inp_QUARTER
print_total()
sleep(1)
LCD_disp.message('Enjoy')
LCD_disp.message('Your Paper')