diff --git a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py index 06b9300c..7c6a5c5e 100644 --- a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py +++ b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py @@ -260,6 +260,7 @@ def write(self, value, char_mode=False): def begin(self, cols, lines): self.currline = 0 self.numlines = lines + self.numcols = cols self.clear() @@ -404,13 +405,35 @@ def createChar(self, location, bitmap): self.write(self.LCD_SETDDRAMADDR) - def message(self, text): - """ Send string to LCD. Newline wraps to second line""" - lines = str(text).split('\n') # Split at newline(s) - for i, line in enumerate(lines): # For each substring... - if i > 0: # If newline(s), - self.write(0xC0) # set DDRAM address to 2nd line - self.write(line, True) # Issue substring + def message(self, text, limitMode = 0): + """ Send string to LCD. Newline wraps to next line""" + lines = str(text).split('\n') # Split at newline(s) + for i, line in enumerate(lines): # For each substring... + if i == 1: # If newline(s), + self.write(0xC0) # set DDRAM address to 2nd line + elif i == 2: + self.write(0x94) + elif i >= 3: + self.write(0xD4) + """Now depending on the limit mode set by the function call this will handle """ + lineLength = len(line) + limit = self.numcols + if limitMode <= 0: + self.write(line, True) + elif lineLength >= limit and limitMode == 1: + '''With the limit mode set to 1 the line is truncated + at the number of columns available on the display''' + limitedLine = line[0:self.numcols] + self.write(limitedLine, True) + elif lineLength >= limit and limitMode == 2: + '''With the limit mode set to 2 the line is truncated + at the number of columns minus 3 to add in an elipse''' + limitedLine = line[0:self.numcols-3]+'...' + self.write(limitedLine, True) + elif lineLength >= limit and limitMode >= 3: + '''Future todo, add in proper, "line after line" cariage return''' + else: + self.write(line, True) def backlight(self, color): diff --git a/Adafruit_CharLCDPlate/LCD_ DataTable.py b/Adafruit_CharLCDPlate/LCD_ DataTable.py new file mode 100644 index 00000000..0d52f745 --- /dev/null +++ b/Adafruit_CharLCDPlate/LCD_ DataTable.py @@ -0,0 +1,185 @@ +#!/usr/bin/python +#---------------------------------------------------------------- +# Author: Chris Crumpacker +# Date: May 2013 +# +# Testing a data table on an 20x4 LCD, +# using a RaspberyPi and an MCP23017 I2C port expander +# +# Using Adafruit_CharLCD code with the I2C and MCP230xx code as well +#---------------------------------------------------------------- + +from time import sleep +from Adafruit_CharLCDPlate4line import Adafruit_CharLCDPlate +from LCD_EoL_HandlingAnd4LineSupport import LCD_EoL_Handling + +class LCD_DataTable(Adafruit_CharLCDPlate): + # Limited to 4 characters, + # position is left or right, + # line is 1-4 + def updateHalfLabel(self, text, position, line): + self.clearHalfDataSet(position,line) + if position == "left": + lcd.setCursor(0,line) + eol.message(text[0:4]+':') + elif position == "right": + lcd.setCursor(10,line) + eol.message('|'+text[0:4]+':') + + # Limited to 4 characters, + # position is left or right, + # line is 1-4 + def updateHalfValue(self, text, position, line): + if position == "left": + lcd.setCursor(5,line) + eol.message(" ") + lcd.setCursor(5,line) + eol.message(text[0:4]) + elif position == "right": + lcd.setCursor(16,line) + eol.message(" ") + lcd.setCursor(16,line) + eol.message(text[0:4]) + + # Writes up to a 9 character lable and value to a full line + def updateWholeLineLabel(self, label, line): + self.clearWholeLine(line) + lcd.setCursor(0,line) + eol.message(label[0:9] + ': ') + + # Writes up to a 9 character lable and value to a full line + def updateWholeLineValue(self, value, line): + lcd.setCursor(10,line) + eol.message(value[0:10]) + + #Clears an entire line + def clearWholeLine(self, line): + lcd.setCursor(0,line) + eol.message(" " * columns) + + #Clears an entire line + def clearWholeLineValue(self, line): + lcd.setCursor(10,line) + eol.message(" " * 10) + + # Clears just a half data set, label and value + def clearHalfDataSet(self, position,line): + if position == "left": + lcd.setCursor(0,line) + eol.message(" " * 10) + elif position == "right": + lcd.setCursor(10,line) + eol.message(" " * 10) + + # Clears just the value portion for a half data set + def clearHalfValue(self, position,line): + if position == "left": + lcd.setCursor(5,line) + eol.message(" ") + elif position == "right": + lcd.setCursor(16,line) + eol.message(" ") + +#---------------------------------------------------------------- +# Main program, just trowing bogus data "against the wall" +#---------------------------------------------------------------- +if __name__ == '__main__': + + #lcd size reference + columns = 20 + rows = 4 + + eol = LCD_EoL_Handling() + lcd = Adafruit_CharLCDPlate() + dt = LCD_DataTable() + + lcd.begin(columns, rows) + lcd.backlight(lcd.ON) + lcd.clear() + + lcd.message("20x4 Table Testing") + sleep(2) + + #Filling the table with bogus info + lcd.clear() + dt.updateHalfLabel("Temp","left",0) + dt.updateHalfLabel("Mode","right",0) + dt.updateHalfLabel("Targ","left",1) + dt.updateHalfLabel("Fan","right",1) + dt.updateHalfValue("Cool","right",0) + dt.updateHalfValue("75.5","left",0) + dt.updateHalfValue("Auto","right",1) + dt.updateHalfValue("74.0","left",1) + dt.updateWholeLineLabel("Tempurature",2) + dt.updateWholeLineValue("Too Hot!!!",2) + dt.updateWholeLineLabel("Humidity",3) + dt.updateWholeLineValue("100%!!!",3) + + #Start testing updating and clearing parts + + # Clearing entire lines + sleep(2) + dt.clearWholeLine(0) + sleep(1) + dt.clearWholeLine(3) + sleep(1) + + # Repopulating the lines just cleared + dt.updateHalfLabel("Temp","left",0) + dt.updateHalfValue("75.3","left",0) + dt.updateHalfLabel("Mode","right",0) + dt.updateHalfValue("Cool","right",0) + dt.updateWholeLineLabel("Humidity",3) + dt.updateWholeLineValue("100%!!!",3) + sleep(2) + + # Clearing the entire Data set, both Label and Value + dt.clearHalfDataSet("left",0) + sleep(1) + dt.clearHalfDataSet("right",0) + sleep(1) + dt.clearHalfDataSet("left",1) + sleep(1) + dt.clearHalfDataSet("right",1) + sleep(2) + + # Repopulating the half labels and values just removed + dt.updateHalfLabel("Temp","left",0) + dt.updateHalfLabel("Mode","right",0) + dt.updateHalfLabel("Targ","left",1) + dt.updateHalfLabel("Fan","right",1) + + dt.updateHalfValue("75.5","left",0) + dt.updateHalfValue("Cool","right",0) + dt.updateHalfValue("74.0","left",1) + dt.updateHalfValue("On","right",1) + sleep(2) + + # Clearing the values in the half data sets + dt.clearHalfValue("left",0) + sleep(1) + dt.clearHalfValue("right",0) + sleep(1) + dt.clearHalfValue("left",1) + sleep(1) + dt.clearHalfValue("right",1) + sleep(2) + + # Repopulating half data set values + dt.updateHalfValue("74.7","left",0) + sleep(1) + dt.updateHalfValue("Auto","right",0) + sleep(1) + dt.updateHalfValue("74.0","left",1) + sleep(1) + dt.updateHalfValue("On","right",1) + sleep(2) + + # Clearing the value on a full line entry + dt.clearWholeLineValue(2) + dt.clearWholeLineValue(3) + sleep(2) + + # Repopulating the values that was just removed + dt.updateWholeLineValue("Still Hot",2) + dt.updateWholeLineValue("90%",3) diff --git a/Adafruit_CharLCDPlate/LCD_EoL_HandlingAnd4LineSupport.py b/Adafruit_CharLCDPlate/LCD_EoL_HandlingAnd4LineSupport.py new file mode 100644 index 00000000..0ae8f18f --- /dev/null +++ b/Adafruit_CharLCDPlate/LCD_EoL_HandlingAnd4LineSupport.py @@ -0,0 +1,110 @@ +######################################################################## +#### OLD!!!!! This change had been rolled into the main plate sciprt ### +######################################################################## + +#---------------------------------------------------------------- +# Author: Chris Crumpacker +# Date: May 2013 +# +# Heavily modified version of the "message" function from Adafruit's +# CharLCD code as written for the RaspberryPi LCD Plate. This handles +# the end of row/line So that it is actually is cut off and does not +# overflow into the buffer on the 16x2 displays and worse onto +# line 3 on the 20x4 displays +# +# All orginal functionality is retained with the addition of handling the +# \n's Cariage returns for all 4 lines on the 20x4 +# +# When calling the message function you can add a "mode" variable to the end +# to describe how to handle strings over the length of the display. +# +# MODE: +# 0 or empty = Normal handling as it was from Adafruit +# 1 = Truncates the string right at the display's limit +# 2 = Truncates the string 3 short of the limit and adds an elipse +# +# Future plans will be to both handle proper cariage returns and to +# cut at the spaces as to not leave partial words. +# +# Orginal was written by Adafruit Industries. +# Under 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_CharLCDPlate import Adafruit_CharLCDPlate + +lcd = Adafruit_CharLCDPlate() + +class LCD_EoL_Handling(Adafruit_CharLCDPlate): + + def __init__(self, cols=20, rows=4): # Defaulted to 20x4 displays + self.numrows = rows + self.numcols = cols # Added a var for the column count to act as the line length limit (say that 10x fast) + + + def message(self, text, limitMode = 0): + """ Send string to LCD. Newline wraps to next line""" + lines = str(text).split('\n') # Split at newline(s) + for i, line in enumerate(lines): # For each substring... + if i == 1: # If newline(s), + lcd.write(0xC0) # set DDRAM address to 2nd line + elif i == 2: + lcd.write(0x94) + elif i >= 3: + lcd.write(0xD4) + """Now depending on the limit mode set by the function call this will handle """ + lineLength = len(line) + limit = self.numcols + if limitMode == 0: + lcd.write(line, True) + elif lineLength >= limit and limitMode == 1: + '''With the limit mode set to 1 the line is truncated + at the number of columns available on the display''' + limitedLine = line[0:self.numcols] + lcd.write(limitedLine, True) + elif lineLength >= limit and limitMode == 2: + '''With the limit mode set to 2 the line is truncated + at the number of columns minus 3 to add in an elipse''' + limitedLine = line[0:self.numcols-3]+'...' + lcd.write(limitedLine, True) + elif lineLength >= limit and limitMode == 3: + '''Future todo, add in proper line after line cariage return''' + print lines + else: + lcd.write(line, True) + +#!/usr/bin/python + +if __name__ == '__main__': + from time import sleep + + numcolumns = 20 + numrows = 4 + + eol = LCD_EoL_Handling(numcolumns, numrows) + + lcd.backlight(lcd.ON) + lcd.begin(numcolumns, numrows) + + eol.message("CharLCD\nEnd of Line Handling\nWith Forced\nCarriage Returns") + sleep(2) + + lcd.clear() + eol.message("Short String") + sleep(2) + + lcd.clear() + eol.message("Longer string then can't fit in one line",0) + sleep(2) + + lcd.clear() + eol.message("Longer string then can't fit in one line",1) + sleep(2) + + lcd.clear() + eol.message("Longer string then can't fit in one line",2) + sleep(2) diff --git a/Adafruit_CharLCDPlate/LCD_examples_w4LineSupport.py b/Adafruit_CharLCDPlate/LCD_examples_w4LineSupport.py new file mode 100644 index 00000000..792cd07e --- /dev/null +++ b/Adafruit_CharLCDPlate/LCD_examples_w4LineSupport.py @@ -0,0 +1,156 @@ +#!/usr/bin/python + +#---------------------------------------------------------------- +# Author: Chris Crumpacker +# Date: May 2013 +# +# A demo of some of the built in helper functions of +# the Adafruit_CharLCDPlate.py and Using the EoL_HandlingAnd4LineSupport.py +# +# Using Adafruit_CharLCD code with the I2C and MCP230xx code as well +#---------------------------------------------------------------- + +numcolumns = 20 +numrows = 4 + +from time import sleep +from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate + +lcd = Adafruit_CharLCDPlate() + +lcd.begin(numcolumns, numrows) + +lcd.backlight(lcd.ON) +lcd.message("LCD 20x4\nDemonstration") +sleep(2) + +while True: + #Text on each line alone. + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Line 1") + sleep(1) + + lcd.clear() + lcd.setCursor(0,1) + lcd.message("Line 2") + sleep(1) + + lcd.clear() + lcd.setCursor(0,2) + lcd.message("Line 3") + sleep(1) + + lcd.clear() + lcd.setCursor(0,3) + lcd.message("Line 4") + sleep(1) + + # Using the "\n" new line marker + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Line 1") + sleep(1) + + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Line 1\nLine 2") + sleep(1) + + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Line 1\nLine 2\nLine 3") + sleep(1) + + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Line 1\nLine 2\nLine 3\nLine 4") + sleep(1) + + # Auto line limiting by length as to not overflow the display + # This is line by line and does not to any caraige returns + lcd.clear() + lcd.setCursor(0,0) + lcd.message("This String is 33 Characters long",1) + sleep(2) + + lcd.clear() + lcd.setCursor(0,0) + lcd.message("This String has elpise",2) + sleep(2) + + #Scroll text to the right + messageToPrint = "Scrolling Right" + i=0 + while i<20: + lcd.clear() + lcd.setCursor(0,0) + suffix = " " * i + lcd.message(suffix + messageToPrint,1) + sleep(.25) + i += 1 + + # Scroll test in from the Left + messageToPrint = "Scrolling Left" + i=20 + while i>=0: + lcd.clear() + lcd.setCursor(0,0) + suffix = " " * i + lcd.message(suffix + messageToPrint,1) + sleep(.25) + i -= 1 + sleep(2) + + # Printing text backwards, NOT right justified + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Right to left:") + lcd.setCursor(10,1) + lcd.rightToLeft() + lcd.message("Testing") + sleep(2) + + # Printing normally from the middle of the line + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Left to Right:") + lcd.setCursor(10,1) + lcd.message("Testing") + sleep(2) + + # Enabling the cursor and having it blink + lcd.clear() + lcd.setCursor(0,0) + lcd.cursor() + lcd.blink() + lcd.message("Cursor is blinking") + lcd.setCursor(0,1) + sleep(3) + lcd.noCursor() + lcd.noBlink() + + # Turning the backlight off and showing a simple count down + lcd.clear() + lcd.setCursor(0,0) + lcd.message("Backlight off in") + lcd.setCursor(0,3) + lcd.message("Back on in 3sec") + lcd.setCursor(17,0) #Reseting the cursor here keeps us from having to clear the screen, this over writes the previous character + lcd.message("3") + sleep(1) + + lcd.setCursor(17,0) + lcd.message("2") + sleep(1) + + lcd.setCursor(17,0) + lcd.message("1") + sleep(1) + + lcd.backlight(lcd.OFF) + lcd.clear() + lcd.setCursor(0,0) + sleep(3) + lcd.backlight(lcd.ON) + lcd.message("Backlight on")