1+ #!/usr/bin/pythonhttp://raspberrypi.local/editor
2+
3+ #
4+ # based on code from lrvick and LiquidCrystal
5+ # lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py
6+ # LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp
7+ #
8+
9+ from time import sleep
10+ from Adafruit_I2C import Adafruit_I2C
11+ from Adafruit_MCP230xx import Adafruit_MCP230XX
12+ import smbus
13+
14+ OUTPUT = 0
15+ INPUT = 1
16+ mcp = Adafruit_MCP230XX (busnum = 0 , address = 0x20 , num_gpios = 16 )
17+
18+
19+ class Adafruit_CharLCD :
20+
21+ # commands
22+ LCD_CLEARDISPLAY = 0x01
23+ LCD_RETURNHOME = 0x02
24+ LCD_ENTRYMODESET = 0x04
25+ LCD_DISPLAYCONTROL = 0x08
26+ LCD_CURSORSHIFT = 0x10
27+ LCD_FUNCTIONSET = 0x20
28+ LCD_SETCGRAMADDR = 0x40
29+ LCD_SETDDRAMADDR = 0x80
30+
31+ # flags for display entry mode
32+ LCD_ENTRYRIGHT = 0x00
33+ LCD_ENTRYLEFT = 0x02
34+ LCD_ENTRYSHIFTINCREMENT = 0x01
35+ LCD_ENTRYSHIFTDECREMENT = 0x00
36+
37+ # flags for display on/off control
38+ LCD_DISPLAYON = 0x04
39+ LCD_DISPLAYOFF = 0x00
40+ LCD_CURSORON = 0x02
41+ LCD_CURSOROFF = 0x00
42+ LCD_BLINKON = 0x01
43+ LCD_BLINKOFF = 0x00
44+
45+ # flags for display/cursor shift
46+ LCD_DISPLAYMOVE = 0x08
47+ LCD_CURSORMOVE = 0x00
48+
49+ # flags for display/cursor shift
50+ LCD_DISPLAYMOVE = 0x08
51+ LCD_CURSORMOVE = 0x00
52+ LCD_MOVERIGHT = 0x04
53+ LCD_MOVELEFT = 0x00
54+
55+ # flags for function set
56+ LCD_8BITMODE = 0x10
57+ LCD_4BITMODE = 0x00
58+ LCD_2LINE = 0x08
59+ LCD_1LINE = 0x00
60+ LCD_5x10DOTS = 0x04
61+ LCD_5x8DOTS = 0x00
62+
63+
64+
65+ def __init__ (self , pin_rs = 25 , pin_e = 24 , pins_db = [23 , 17 , 21 , 22 ], pin_rw = 0 ):
66+ self .pin_rs = pin_rs
67+ self .pin_e = pin_e
68+ self .pin_rw = pin_rw
69+ self .pins_db = pins_db
70+
71+ mcp .config (self .pin_e , OUTPUT )
72+ mcp .config (self .pin_rs , OUTPUT )
73+ mcp .config (self .pin_rw , OUTPUT )
74+ mcp .output (self .pin_rw , 0 )
75+ mcp .output (self .pin_e , 0 )
76+
77+ for pin in self .pins_db :
78+ mcp .config (pin , OUTPUT )
79+
80+ self .write4bits (0x33 ) # initialization
81+ self .write4bits (0x32 ) # initialization
82+ self .write4bits (0x28 ) # 2 line 5x7 matrix
83+ self .write4bits (0x0C ) # turn cursor off 0x0E to enable cursor
84+ self .write4bits (0x06 ) # shift cursor right
85+
86+ self .displaycontrol = self .LCD_DISPLAYON | self .LCD_CURSOROFF | self .LCD_BLINKOFF
87+
88+ self .displayfunction = self .LCD_4BITMODE | self .LCD_1LINE | self .LCD_5x8DOTS
89+ self .displayfunction |= self .LCD_2LINE
90+
91+ """ Initialize to default text direction (for romance languages) """
92+ self .displaymode = self .LCD_ENTRYLEFT | self .LCD_ENTRYSHIFTDECREMENT
93+ self .write4bits (self .LCD_ENTRYMODESET | self .displaymode ) # set the entry mode
94+
95+
96+ def begin (self , cols , lines ):
97+ if (lines > 1 ):
98+ self .numlines = lines
99+ self .displayfunction |= self .LCD_2LINE
100+ self .currline = 0
101+ self .clear ()
102+
103+ def home (self ):
104+ self .write4bits (self .LCD_RETURNHOME ) # set cursor position to zero
105+ self .delayMicroseconds (2000 ) # this command takes a long time!
106+
107+ def clear (self ):
108+ self .write4bits (self .LCD_CLEARDISPLAY ) # command to clear display
109+ self .delayMicroseconds (2000 ) # 2000 microsecond sleep, clearing the display takes a long time
110+
111+ def setCursor (self , col , row ):
112+ self .row_offsets = [ 0x00 , 0x40 , 0x14 , 0x54 ]
113+ if ( row > self .numlines ):
114+ row = self .numlines - 1 # we count rows starting w/0
115+ self .write4bits (self .LCD_SETDDRAMADDR | (col + self .row_offsets [row ]))
116+
117+ def noDisplay (self ):
118+ """ Turn the display off (quickly) """
119+ self .displaycontrol &= ~ self .LCD_DISPLAYON
120+ self .write4bits (self .LCD_DISPLAYCONTROL | self .displaycontrol )
121+
122+ def display (self ):
123+ """ Turn the display on (quickly) """
124+ self .displaycontrol |= self .LCD_DISPLAYON
125+ self .write4bits (self .LCD_DISPLAYCONTROL | self .displaycontrol )
126+
127+ def noCursor (self ):
128+ """ Turns the underline cursor on/off """
129+ self .displaycontrol &= ~ self .LCD_CURSORON
130+ self .write4bits (self .LCD_DISPLAYCONTROL | self .displaycontrol )
131+
132+
133+ def cursor (self ):
134+ """ Cursor On """
135+ self .displaycontrol |= self .LCD_CURSORON
136+ self .write4bits (self .LCD_DISPLAYCONTROL | self .displaycontrol )
137+
138+ def noBlink (self ):
139+ """ Turn on and off the blinking cursor """
140+ self .displaycontrol &= ~ self .LCD_BLINKON
141+ self .write4bits (self .LCD_DISPLAYCONTROL | self .displaycontrol )
142+
143+ def noBlink (self ):
144+ """ Turn on and off the blinking cursor """
145+ self .displaycontrol &= ~ self .LCD_BLINKON
146+ self .write4bits (self .LCD_DISPLAYCONTROL | self .displaycontrol )
147+
148+ def DisplayLeft (self ):
149+ """ These commands scroll the display without changing the RAM """
150+ self .write4bits (self .LCD_CURSORSHIFT | self .LCD_DISPLAYMOVE | self .LCD_MOVELEFT )
151+
152+ def scrollDisplayRight (self ):
153+ """ These commands scroll the display without changing the RAM """
154+ self .write4bits (self .LCD_CURSORSHIFT | self .LCD_DISPLAYMOVE | self .LCD_MOVERIGHT );
155+
156+ def leftToRight (self ):
157+ """ This is for text that flows Left to Right """
158+ self .displaymode |= self .LCD_ENTRYLEFT
159+ self .write4bits (self .LCD_ENTRYMODESET | self .displaymode );
160+
161+ def rightToLeft (self ):
162+ """ This is for text that flows Right to Left """
163+ self .displaymode &= ~ self .LCD_ENTRYLEFT
164+ self .write4bits (self .LCD_ENTRYMODESET | self .displaymode )
165+
166+ def autoscroll (self ):
167+ """ This will 'right justify' text from the cursor """
168+ self .displaymode |= self .LCD_ENTRYSHIFTINCREMENT
169+ self .write4bits (self .LCD_ENTRYMODESET | self .displaymode )
170+
171+ def noAutoscroll (self ):
172+ """ This will 'left justify' text from the cursor """
173+ self .displaymode &= ~ self .LCD_ENTRYSHIFTINCREMENT
174+ self .write4bits (self .LCD_ENTRYMODESET | self .displaymode )
175+
176+ def write4bits (self , bits , char_mode = False ):
177+ """ Send command to LCD """
178+ #self.delayMicroseconds(1000) # 1000 microsecond sleep
179+ bits = bin (bits )[2 :].zfill (8 )
180+ mcp .output (self .pin_rs , char_mode )
181+
182+ for i in range (4 ):
183+ if bits [i ] == "1" :
184+ mcp .output (self .pins_db [::- 1 ][i ], True )
185+ else :
186+ mcp .output (self .pins_db [::- 1 ][i ], False )
187+ self .pulseEnable ()
188+
189+ for i in range (4 ,8 ):
190+ if bits [i ] == "1" :
191+ mcp .output (self .pins_db [::- 1 ][i - 4 ], True )
192+ else :
193+ mcp .output (self .pins_db [::- 1 ][i - 4 ], False )
194+ self .pulseEnable ()
195+
196+ def delayMicroseconds (self , microseconds ):
197+ seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds
198+ sleep (seconds )
199+
200+ def pulseEnable (self ):
201+ mcp .output (self .pin_e , True )
202+ self .delayMicroseconds (1 ) # 1 microsecond pause - enable pulse must be > 450ns
203+ mcp .output (self .pin_e , False )
204+ #self.delayMicroseconds(1) # commands need > 37us to settle
205+
206+ def message (self , text ):
207+ """ Send string to LCD. Newline wraps to second line"""
208+ for char in text :
209+ if char == '\n ' :
210+ self .write4bits (0xC0 ) # next line
211+ else :
212+ self .write4bits (ord (char ),True )
213+
214+
215+
216+ if __name__ == '__main__' :
217+
218+
219+ # input test
220+ # for i in range(16):
221+ # mcp.pullup(i, 1)
222+ # while (True):
223+ # for i in range(16):
224+ # print "%d: %x" % (i, mcp.input(i) >> i)
225+ mcp .config (6 , OUTPUT )
226+ mcp .config (7 , OUTPUT )
227+ mcp .config (8 , OUTPUT )
228+ mcp .output (6 , 0 ) # red
229+ mcp .output (7 , 0 ) # green
230+ mcp .output (8 , 0 ) # blue
231+
232+ lcd = Adafruit_CharLCD (15 , 13 , [12 ,11 ,10 ,9 ], 14 )
233+ lcd .clear ()
234+ lcd .message ("Adafruit RGB LCD\n Plate w/Keypad!" )
235+ while 1 :
236+ mcp .output (6 , 0 ) # red
237+ mcp .output (7 , 1 ) # green
238+ mcp .output (8 , 1 ) # blue
239+ sleep (1 )
240+ mcp .output (7 , 0 ) # green
241+ sleep (1 )
242+ mcp .output (6 , 1 ) # red
243+ sleep (1 )
244+ mcp .output (8 , 0 ) # blue
245+ sleep (1 )
246+ mcp .output (7 , 1 ) # green
247+ sleep (1 )
248+ mcp .output (6 , 0 ) # red
249+ sleep (1 )
250+
0 commit comments