From 26795f4a7ee659cea4ac405faad892882829683f Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Wed, 13 Feb 2013 21:58:17 +1300 Subject: [PATCH 01/13] Indentation is a mixture of tabs and spaces which confused webide. So tidied this up. Unfortunately this is hard for diff to handle, so the changes appear as big blocks of code being removed and other blocks being added. CharLCDPlate.py Added more routines - ToggleCursor(), blink(), ToggleBlink(), read4bits(), readBF() In particular implemented Reading BF and Address and ReadingRAM Implemented waitBFlow() which can replace a time delay Tidied up comments for many of the routines, as they did not accurately reflect what they do. MCP230xx.py Fixed some bugs config(self, pin, mode) did not maintain a 16bit record of the I/O state of of the pins. input(self, pin, check=True) fixed to return either 0 or 1 rather then 0 or various non-zero values added parameter which defaults to previous rountine, but allows asserstion to be skipped - to enable experimenting reading 'output' pins Removed orphaned code after return in output(self, pin, value) All the low level rountines readU8, readS8 etc. where indented so they were sub function of input and no used there, and inaccessible in the class Moved indentation and modified may to use the i2c routines more efficiently. --- .../Adafruit_CharLCDPlate.py | 178 +++++++++++---- Adafruit_MCP230xx/Adafruit_MCP230xx.py | 206 +++++++++--------- 2 files changed, 236 insertions(+), 148 deletions(-) diff --git a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py index 12e4cdf8..6e7af7a1 100644 --- a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py +++ b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py @@ -4,7 +4,7 @@ # 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 time import sleep from Adafruit_I2C import Adafruit_I2C @@ -79,7 +79,7 @@ class Adafruit_CharLCDPlate: - def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): + def __init__(self, busnum=1, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): self.pin_rs = pin_rs self.pin_e = pin_e self.pin_rw = pin_rw @@ -87,7 +87,7 @@ def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_r self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) - self.mcp.config(self.pin_e, self.OUTPUT) + self.mcp.config(self.pin_e, self.OUTPUT) self.mcp.config(self.pin_rs, self.OUTPUT) self.mcp.config(self.pin_rw, self.OUTPUT) self.mcp.output(self.pin_rw, 0) @@ -98,9 +98,9 @@ def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_r self.write4bits(0x33) # initialization self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x7 matrix + self.write4bits(0x28) # 2 line 5x8 matrix self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # shift cursor right + self.write4bits(0x06) # set cursor incrementing and no shift of display self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF @@ -140,12 +140,13 @@ def begin(self, cols, lines): def home(self): self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero - self.delayMicroseconds(2000) # this command takes a long time! + self.waitBFlow() #wait for Busy flag low + def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time - + self.waitBFlow() #wait for Busy flag low + def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): @@ -163,26 +164,39 @@ def display(self): self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): - """ Turns the underline cursor on/off """ + """ underline cursor off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): - """ Cursor On """ + """ underline Cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def noBlink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON + def ToggleCursor(self): + """ Toggles the underline cursor On/Off bb""" + self.displaycontrol ^= self.LCD_CURSORON + self.delayMicroseconds(200000) self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): - """ Turn on and off the blinking cursor """ + """ Turn off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + def blink(self): + """ Turn on the blinking cursor""" + self.displaycontrol |= self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def ToggleBlink(self): + """ Toggles the blinking cursor""" + self.displaycontrol ^= self.LCD_BLINKON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def DisplayLeft(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) @@ -230,6 +244,64 @@ def write4bits(self, bits, char_mode=False): else: self.mcp.output(self.pins_db[::-1][i-4], False) self.pulseEnable() + + #See pg. 24 and 58 HD44780.pdf and http://www.avrbeginners.net/ Standard LCD bit mode + def read4bits(self, char_mode=False): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, char_mode) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 +# Configure pins for input + makeinput=True + if makeinput: + for pin in self.pins_db: + self.mcp.config(pin, self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + bits = range(8) + # get the pins values + for i in range(4): + bt = self.mcp.input(self.pins_db[::-1][i], makeinput) # if makeinput is False, pin direction checking is supressed in input + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.mcp.output(self.pin_e, True) # set Enable high and keep while read 2nd nibble + # get the pins values + for i in range(4,8): + bt = self.mcp.input(self.pins_db[::-1][i-4],makeinput) + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish 2nd nibble + # restore to pins to output and rw to 0 + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 +# print "Last :", bin(self.mcp.direction)[2:].zfill(16) + return bits; + + def readBF(self): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, 0) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 +# Configure pins for input + makeinput=True + self.mcp.config(self.pins_db[::-1][1], self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + # get the pins values + bt = self.mcp.input(self.pins_db[::-1][1], makeinput) # if makeinput is False, pin direction checking is supressed in input + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.pulseEnable() # one more pulse to get (but ingore the 2nd nibble) + # restore to pins to output and rw to 0 + self.mcp.config(self.pins_db[::-1][1], self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 + return bt==1 + + def waitBFlow(self): + for cnt in range(100000): + if not self.readBF(): + #print cnt + return + print "timed out of waitBFlow" def delayMicroseconds(self, microseconds): seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds @@ -245,7 +317,7 @@ def message(self, text): """ Send string to LCD. Newline wraps to second line""" for char in text: if char == '\n': - self.write4bits(0xC0) # next line + self.write4bits(0xC0) # set DDRAM address 0x40 start of second line else: self.write4bits(ord(char),True) @@ -263,41 +335,55 @@ def buttonPressed(self, buttonname): if __name__ == '__main__': - lcd = Adafruit_CharLCDPlate(busnum = 0) - lcd.clear() - lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") - sleep(1) - while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) + lcd = Adafruit_CharLCDPlate(busnum = 1) + lcd.clear() + lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") + sleep(1) - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) + print " Cycle thru backlight colors 3 times " - if (lcd.buttonPressed(lcd.DOWN)): + for i in range(3): + print "red" + lcd.backlight(lcd.RED) + sleep(1) + print "yellow" + lcd.backlight(lcd.YELLOW) + sleep(1) + print "green" lcd.backlight(lcd.GREEN) - - if (lcd.buttonPressed(lcd.RIGHT)): + sleep(1) + print "teal" + lcd.backlight(lcd.TEAL) + sleep(1) + print "blue" + lcd.backlight(lcd.BLUE) + sleep(1) + print "violet" lcd.backlight(lcd.VIOLET) - - if (lcd.buttonPressed(lcd.SELECT)): + sleep(1) + print "off" + lcd.backlight(lcd.OFF) + sleep(1) + print "on" lcd.backlight(lcd.ON) + sleep(1) + + print " Try buttons on plate" + + while 1: + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) - while 1: - lcd.backlight(lcd.RED) - sleep(1) - lcd.backlight(lcd.YELLOW) - sleep(1) - lcd.backlight(lcd.GREEN) - sleep(1) - lcd.backlight(lcd.TEAL) - sleep(1) - lcd.backlight(lcd.BLUE) - sleep(1) - lcd.backlight(lcd.VIOLET) - sleep(1) - lcd.backlight(lcd.ON) - sleep(1) - lcd.backlight(lcd.OFF) - sleep(1) diff --git a/Adafruit_MCP230xx/Adafruit_MCP230xx.py b/Adafruit_MCP230xx/Adafruit_MCP230xx.py index 42565d8d..4fc18695 100755 --- a/Adafruit_MCP230xx/Adafruit_MCP230xx.py +++ b/Adafruit_MCP230xx/Adafruit_MCP230xx.py @@ -37,123 +37,125 @@ MCP23008_OLATA = 0x0A class Adafruit_MCP230XX(object): - OUTPUT = 0 - INPUT = 1 + OUTPUT = 0 + INPUT = 1 - def __init__(self, address, num_gpios, busnum = 0): - assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16" - self.i2c = Adafruit_I2C(address=address, bus=smbus.SMBus(busnum)) - self.address = address - self.num_gpios = num_gpios + def __init__(self, address, num_gpios, busnum = 0): + assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16" + self.i2c = Adafruit_I2C(address=address, bus=smbus.SMBus(busnum)) + self.address = address + self.num_gpios = num_gpios # set defaults - if num_gpios <= 8: - self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A - self.direction = self.i2c.readU8(MCP23017_IODIRA) - self.i2c.write8(MCP23008_GPPUA, 0x00) - elif num_gpios > 8 and num_gpios <= 16: - self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A - self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B - self.direction = self.i2c.readU8(MCP23017_IODIRA) - self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 - self.i2c.write8(MCP23017_GPPUA, 0x00) - self.i2c.write8(MCP23017_GPPUB, 0x00) - - def _changebit(self, bitmap, bit, value): - assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value - if value == 0: - return bitmap & ~(1 << bit) - elif value == 1: - return bitmap | (1 << bit) - - def _readandchangepin(self, port, pin, value, currvalue = None): - assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin - if not currvalue: - currvalue = self.i2c.readU8(port) - newvalue = self._changebit(currvalue, pin, value) - self.i2c.write8(port, newvalue) - return newvalue - - - def pullup(self, pin, value): - if self.num_gpios <= 8: - return self._readandchangepin(MCP23008_GPPUA, pin, value) - if self.num_gpios <= 16: - if (pin < 8): - return self._readandchangepin(MCP23017_GPPUA, pin, value) - else: - return self._readandchangepin(MCP23017_GPPUB, pin-8, value) - - # Set pin to either input or output mode - def config(self, pin, mode): - if self.num_gpios <= 8: - self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) - if self.num_gpios <= 16: - if (pin < 8): - self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) - else: - self.direction = self._readandchangepin(MCP23017_IODIRB, pin-8, mode) - - return self.direction - - def output(self, pin, value): - # assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin - if self.num_gpios <= 8: - self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA)) - if self.num_gpios <= 16: - if (pin < 8): - self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) - else: - self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) - - return self.outputvalue + if num_gpios <= 8: + self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A + self.direction = self.i2c.readU8(MCP23017_IODIRA) + self.i2c.write8(MCP23008_GPPUA, 0x00) + elif num_gpios > 8 and num_gpios <= 16: + self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A + self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B + self.direction = self.i2c.readU8(MCP23017_IODIRA) + self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 + self.i2c.write8(MCP23017_GPPUA, 0x00) + self.i2c.write8(MCP23017_GPPUB, 0x00) - - self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue) - return self.outputvalue + + def _changebit(self, bitmap, bit, value): + assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value + if value == 0: + return bitmap & ~(1 << bit) + elif value == 1: + return bitmap | (1 << bit) + + def _readandchangepin(self, port, pin, value, currvalue = None): + assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) + #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin + if not currvalue: + currvalue = self.i2c.readU8(port) + newvalue = self._changebit(currvalue, pin, value) + self.i2c.write8(port, newvalue) + return newvalue + + + def pullup(self, pin, value): + if self.num_gpios <= 8: + return self._readandchangepin(MCP23008_GPPUA, pin, value) + if self.num_gpios <= 16: + if (pin < 8): + return self._readandchangepin(MCP23017_GPPUA, pin, value) + else: + return self._readandchangepin(MCP23017_GPPUB, pin-8, value) + + # Set pin to either input or output mode + def config(self, pin, mode): + if self.num_gpios <= 8: + self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) + if self.num_gpios <= 16: + if (pin < 8): + # replace low bits + self.direction = (self.direction >> 8)<<8 | self._readandchangepin(MCP23017_IODIRA, pin, mode) + else: + # replace hi bits + self.direction = (self.direction & 0xff) | self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8 + #print "config ", pin, mode, self.direction, bin(self.direction)[2:].zfill(16) + return self.direction + + def output(self, pin, value): + # assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin + if self.num_gpios <= 8: + self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA)) + if self.num_gpios <= 16: + if (pin < 8): + self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) + else: + self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) + return self.outputvalue + +# what is this code doing here inaccessible place! - def input(self, pin): - assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin - if self.num_gpios <= 8: - value = self.i2c.readU8(MCP23008_GPIOA) - elif self.num_gpios > 8 and self.num_gpios <= 16: - value = self.i2c.readU16(MCP23017_GPIOA) - temp = value >> 8 - value <<= 8 - value |= temp - return value & (1 << pin) - - def readU8(self): - result = self.i2c.readU8(MCP23008_OLATA) + def input(self, pin, check=True): + assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) + if check: + assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin + if self.num_gpios <= 8: + value = self.i2c.readU8(MCP23008_GPIOA) + elif self.num_gpios > 8 and self.num_gpios <= 16: + value = self.i2c.readU16(MCP23017_GPIOA) + temp = value >> 8 + value <<= 8 + value |= temp + return (value & (1 << pin))>>pin # to make 0 or 1 + + + +# these were indented so within scope of input but have now made them all part of the class +# have modified so can read any address but default to those given in original code +# also use available routines in imported Adafruit_I2C class + def readU8(self, add=MCP23008_OLATA): + result = self.i2c.readU8(add) return(result) - def readS8(self): - result = self.i2c.readU8(MCP23008_OLATA) - if (result > 127): result -= 256 + def readS8(self, add=MCP23008_OLATA): + result = self.i2c.readS8(add) return result - def readU16(self): + def readU16(self, add=MCP23017_OLATA): assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - return((hi << 8) | lo) + result = self.i2c.readU16(add) + return result - def readS16(self): + def readS16(self, add=MCP23017_OLATA): assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - if (hi > 127): hi -= 256 - return((hi << 8) | lo) + result = self.i2c.readS16(add) + return result - def write8(self, value): - self.i2c.write8(MCP23008_OLATA, value) + def write8(self, value, add=MCP23008_OLATA): + self.i2c.write8(add, value) - def write16(self, value): + def write16(self, value, add=MCP23017_OLATA): assert self.num_gpios >= 16, "16bits required" - self.i2c.write8(MCP23017_OLATA, value & 0xFF) - self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF) + self.i2c.write16(add, value) + # RPi.GPIO compatible interface for MCP23017 and MCP23008 From c48fe0dfab6792c65a933f53bf5f0b2dd901a9d5 Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 13:33:00 +1300 Subject: [PATCH 02/13] No Tabs only spaces --- Adafruit_CharLCDPlate/ACLP4spaceindent.py | 389 ++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 Adafruit_CharLCDPlate/ACLP4spaceindent.py diff --git a/Adafruit_CharLCDPlate/ACLP4spaceindent.py b/Adafruit_CharLCDPlate/ACLP4spaceindent.py new file mode 100644 index 00000000..6e7af7a1 --- /dev/null +++ b/Adafruit_CharLCDPlate/ACLP4spaceindent.py @@ -0,0 +1,389 @@ +#!/usr/bin/pythonhttp://raspberrypi.local/editor + +# +# 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 time import sleep +from Adafruit_I2C import Adafruit_I2C +from Adafruit_MCP230xx import Adafruit_MCP230XX +import smbus + + +class Adafruit_CharLCDPlate: + + OUTPUT = 0 + INPUT = 1 + + # LED colors + RED = 0x01 + GREEN = 0x02 + BLUE = 0x04 + YELLOW = 0x03 + TEAL = 0x06 + VIOLET = 0x05 + ON = 0x07 + OFF = 0x0 + + # buttons + SELECT = 0 + RIGHT = 1 + DOWN = 2 + UP = 3 + LEFT = 4 + + # 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 entry mode + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 + + # 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/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + + # flags for display/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 + + # flags for function set + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 + + + + + def __init__(self, busnum=1, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): + self.pin_rs = pin_rs + self.pin_e = pin_e + self.pin_rw = pin_rw + self.pins_db = pins_db + + self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + + self.mcp.config(self.pin_e, self.OUTPUT) + self.mcp.config(self.pin_rs, self.OUTPUT) + self.mcp.config(self.pin_rw, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) + self.mcp.output(self.pin_e, 0) + + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + + self.write4bits(0x33) # initialization + self.write4bits(0x32) # initialization + self.write4bits(0x28) # 2 line 5x8 matrix + self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor + self.write4bits(0x06) # set cursor incrementing and no shift of display + + self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + """ Initialize to default text direction (for romance languages) """ + self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode + + # turn on backlights! + self.mcp.config(6, self.mcp.OUTPUT) + self.mcp.config(7, self.mcp.OUTPUT) + self.mcp.config(8, self.mcp.OUTPUT) + self.mcp.output(6, 0) # red + self.mcp.output(7, 0) # green + self.mcp.output(8, 0) # blue + + # turn on pullups + self.mcp.pullup(self.SELECT, True) + self.mcp.pullup(self.LEFT, True) + self.mcp.pullup(self.RIGHT, True) + self.mcp.pullup(self.UP, True) + self.mcp.pullup(self.DOWN, True) + self.mcp.config(self.SELECT, self.mcp.INPUT) + self.mcp.config(self.LEFT, self.mcp.INPUT) + self.mcp.config(self.RIGHT, self.mcp.INPUT) + self.mcp.config(self.DOWN, self.mcp.INPUT) + self.mcp.config(self.UP, self.mcp.INPUT) + + def begin(self, cols, lines): + if (lines > 1): + self.numlines = lines + self.displayfunction |= self.LCD_2LINE + self.currline = 0 + self.clear() + + def home(self): + self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero + self.waitBFlow() #wait for Busy flag low + + + def clear(self): + self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display + self.waitBFlow() #wait for Busy flag low + + def setCursor(self, col, row): + self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] + if ( row > self.numlines ): + row = self.numlines - 1 # we count rows starting w/0 + self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) + + def noDisplay(self): + """ Turn the display off (quickly) """ + self.displaycontrol &= ~self.LCD_DISPLAYON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def display(self): + """ Turn the display on (quickly) """ + self.displaycontrol |= self.LCD_DISPLAYON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noCursor(self): + """ underline cursor off """ + self.displaycontrol &= ~self.LCD_CURSORON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + + def cursor(self): + """ underline Cursor On """ + self.displaycontrol |= self.LCD_CURSORON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def ToggleCursor(self): + """ Toggles the underline cursor On/Off bb""" + self.displaycontrol ^= self.LCD_CURSORON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noBlink(self): + """ Turn off the blinking cursor """ + self.displaycontrol &= ~self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def blink(self): + """ Turn on the blinking cursor""" + self.displaycontrol |= self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def ToggleBlink(self): + """ Toggles the blinking cursor""" + self.displaycontrol ^= self.LCD_BLINKON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + + def DisplayLeft(self): + """ These commands scroll the display without changing the RAM """ + self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) + + def scrollDisplayRight(self): + """ These commands scroll the display without changing the RAM """ + self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); + + def leftToRight(self): + """ This is for text that flows Left to Right """ + self.displaymode |= self.LCD_ENTRYLEFT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); + + def rightToLeft(self): + """ This is for text that flows Right to Left """ + self.displaymode &= ~self.LCD_ENTRYLEFT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def autoscroll(self): + """ This will 'right justify' text from the cursor """ + self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def noAutoscroll(self): + """ This will 'left justify' text from the cursor """ + self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def write4bits(self, bits, char_mode=False): + """ Send command to LCD """ + #self.delayMicroseconds(1000) # 1000 microsecond sleep + bits=bin(bits)[2:].zfill(8) + self.mcp.output(self.pin_rs, char_mode) + + for i in range(4): + if bits[i] == "1": + self.mcp.output(self.pins_db[::-1][i], True) + else: + self.mcp.output(self.pins_db[::-1][i], False) + self.pulseEnable() + + for i in range(4,8): + if bits[i] == "1": + self.mcp.output(self.pins_db[::-1][i-4], True) + else: + self.mcp.output(self.pins_db[::-1][i-4], False) + self.pulseEnable() + + #See pg. 24 and 58 HD44780.pdf and http://www.avrbeginners.net/ Standard LCD bit mode + def read4bits(self, char_mode=False): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, char_mode) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 +# Configure pins for input + makeinput=True + if makeinput: + for pin in self.pins_db: + self.mcp.config(pin, self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + bits = range(8) + # get the pins values + for i in range(4): + bt = self.mcp.input(self.pins_db[::-1][i], makeinput) # if makeinput is False, pin direction checking is supressed in input + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.mcp.output(self.pin_e, True) # set Enable high and keep while read 2nd nibble + # get the pins values + for i in range(4,8): + bt = self.mcp.input(self.pins_db[::-1][i-4],makeinput) + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish 2nd nibble + # restore to pins to output and rw to 0 + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 +# print "Last :", bin(self.mcp.direction)[2:].zfill(16) + return bits; + + def readBF(self): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, 0) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 +# Configure pins for input + makeinput=True + self.mcp.config(self.pins_db[::-1][1], self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + # get the pins values + bt = self.mcp.input(self.pins_db[::-1][1], makeinput) # if makeinput is False, pin direction checking is supressed in input + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.pulseEnable() # one more pulse to get (but ingore the 2nd nibble) + # restore to pins to output and rw to 0 + self.mcp.config(self.pins_db[::-1][1], self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 + return bt==1 + + def waitBFlow(self): + for cnt in range(100000): + if not self.readBF(): + #print cnt + return + print "timed out of waitBFlow" + + def delayMicroseconds(self, microseconds): + seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds + sleep(seconds) + + def pulseEnable(self): + self.mcp.output(self.pin_e, True) + self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns + self.mcp.output(self.pin_e, False) + #self.delayMicroseconds(1) # commands need > 37us to settle + + def message(self, text): + """ Send string to LCD. Newline wraps to second line""" + for char in text: + if char == '\n': + self.write4bits(0xC0) # set DDRAM address 0x40 start of second line + else: + self.write4bits(ord(char),True) + + def backlight(self, color): + self.mcp.output(6, not color & 0x01) + self.mcp.output(7, not color & 0x02) + self.mcp.output(8, not color & 0x04) + + def buttonPressed(self, buttonname): + if (buttonname > self.LEFT): + return false + + return not self.mcp.input(buttonname) + + +if __name__ == '__main__': + + lcd = Adafruit_CharLCDPlate(busnum = 1) + lcd.clear() + lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") + sleep(1) + + print " Cycle thru backlight colors 3 times " + + for i in range(3): + print "red" + lcd.backlight(lcd.RED) + sleep(1) + print "yellow" + lcd.backlight(lcd.YELLOW) + sleep(1) + print "green" + lcd.backlight(lcd.GREEN) + sleep(1) + print "teal" + lcd.backlight(lcd.TEAL) + sleep(1) + print "blue" + lcd.backlight(lcd.BLUE) + sleep(1) + print "violet" + lcd.backlight(lcd.VIOLET) + sleep(1) + print "off" + lcd.backlight(lcd.OFF) + sleep(1) + print "on" + lcd.backlight(lcd.ON) + sleep(1) + + print " Try buttons on plate" + + while 1: + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) + + From 466ef2f0e2d2d01297b7e325c64b53199c831d3e Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 13:36:04 +1300 Subject: [PATCH 03/13] Removed all tabs and used 4 space indenting style --- Adafruit_CharLCDPlate/ACLP4spaceindent.py | 336 ++++++++-------------- 1 file changed, 120 insertions(+), 216 deletions(-) diff --git a/Adafruit_CharLCDPlate/ACLP4spaceindent.py b/Adafruit_CharLCDPlate/ACLP4spaceindent.py index 6e7af7a1..4de5400a 100644 --- a/Adafruit_CharLCDPlate/ACLP4spaceindent.py +++ b/Adafruit_CharLCDPlate/ACLP4spaceindent.py @@ -4,7 +4,7 @@ # 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 time import sleep from Adafruit_I2C import Adafruit_I2C @@ -35,101 +35,97 @@ class Adafruit_CharLCDPlate: LEFT = 4 # 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 + 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 entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control - LCD_DISPLAYON = 0x04 - LCD_DISPLAYOFF = 0x00 - LCD_CURSORON = 0x02 - LCD_CURSOROFF = 0x00 - LCD_BLINKON = 0x01 - LCD_BLINKOFF = 0x00 + LCD_DISPLAYON = 0x04 + LCD_DISPLAYOFF = 0x00 + LCD_CURSORON = 0x02 + LCD_CURSOROFF = 0x00 + LCD_BLINKON = 0x01 + LCD_BLINKOFF = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 - def __init__(self, busnum=1, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): + def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): self.pin_rs = pin_rs self.pin_e = pin_e self.pin_rw = pin_rw self.pins_db = pins_db - self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) - - self.mcp.config(self.pin_e, self.OUTPUT) + self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + self.mcp.config(self.pin_e, self.OUTPUT) self.mcp.config(self.pin_rs, self.OUTPUT) self.mcp.config(self.pin_rw, self.OUTPUT) self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) - + self.mcp.output(self.pin_e, 0) for pin in self.pins_db: self.mcp.config(pin, self.OUTPUT) - - self.write4bits(0x33) # initialization - self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x8 matrix - self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # set cursor incrementing and no shift of display - - self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF - - self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS - self.displayfunction |= self.LCD_2LINE - - """ Initialize to default text direction (for romance languages) """ - self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode - - # turn on backlights! - self.mcp.config(6, self.mcp.OUTPUT) - self.mcp.config(7, self.mcp.OUTPUT) - self.mcp.config(8, self.mcp.OUTPUT) - self.mcp.output(6, 0) # red - self.mcp.output(7, 0) # green - self.mcp.output(8, 0) # blue - - # turn on pullups + self.write4bits(0x33) # initialization + self.write4bits(0x32) # initialization + self.write4bits(0x28) # 2 line 5x7 matrix + self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor + self.write4bits(0x06) # shift cursor right + + self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + """ Initialize to default text direction (for romance languages) """ + self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode + + # turn on backlights! + self.mcp.config(6, self.mcp.OUTPUT) + self.mcp.config(7, self.mcp.OUTPUT) + self.mcp.config(8, self.mcp.OUTPUT) + self.mcp.output(6, 0) # red + self.mcp.output(7, 0) # green + self.mcp.output(8, 0) # blue + + # turn on pullups self.mcp.pullup(self.SELECT, True) self.mcp.pullup(self.LEFT, True) self.mcp.pullup(self.RIGHT, True) self.mcp.pullup(self.UP, True) self.mcp.pullup(self.DOWN, True) - self.mcp.config(self.SELECT, self.mcp.INPUT) - self.mcp.config(self.LEFT, self.mcp.INPUT) - self.mcp.config(self.RIGHT, self.mcp.INPUT) - self.mcp.config(self.DOWN, self.mcp.INPUT) - self.mcp.config(self.UP, self.mcp.INPUT) + self.mcp.config(self.SELECT, self.mcp.INPUT) + self.mcp.config(self.LEFT, self.mcp.INPUT) + self.mcp.config(self.RIGHT, self.mcp.INPUT) + self.mcp.config(self.DOWN, self.mcp.INPUT) + self.mcp.config(self.UP, self.mcp.INPUT) def begin(self, cols, lines): if (lines > 1): @@ -140,17 +136,16 @@ def begin(self, cols, lines): def home(self): self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero - self.waitBFlow() #wait for Busy flag low - + self.delayMicroseconds(2000) # this command takes a long time! def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.waitBFlow() #wait for Busy flag low - + self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time + def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): - row = self.numlines - 1 # we count rows starting w/0 + row = self.numlines - 1 # we count rows starting w/0 self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) def noDisplay(self): @@ -164,64 +159,51 @@ def display(self): self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): - """ underline cursor off """ + """ Turns the underline cursor off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): - """ underline Cursor On """ + """ Turns the underline cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def ToggleCursor(self): - """ Toggles the underline cursor On/Off bb""" - self.displaycontrol ^= self.LCD_CURSORON - self.delayMicroseconds(200000) - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def noBlink(self): - """ Turn off the blinking cursor """ + """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def blink(self): - """ Turn on the blinking cursor""" + """ Turn on and off the blinking cursor """ self.displaycontrol |= self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def ToggleBlink(self): - """ Toggles the blinking cursor""" - self.displaycontrol ^= self.LCD_BLINKON - self.delayMicroseconds(200000) - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def DisplayLeft(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) def scrollDisplayRight(self): - """ These commands scroll the display without changing the RAM """ + """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); def leftToRight(self): - """ This is for text that flows Left to Right """ + """ This is for text that flows Left to Right """ self.displaymode |= self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); def rightToLeft(self): - """ This is for text that flows Right to Left """ + """ This is for text that flows Right to Left """ self.displaymode &= ~self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def autoscroll(self): - """ This will 'right justify' text from the cursor """ + """ This will 'right justify' text from the cursor """ self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def noAutoscroll(self): - """ This will 'left justify' text from the cursor """ + """ This will 'left justify' text from the cursor """ self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) @@ -230,160 +212,82 @@ def write4bits(self, bits, char_mode=False): #self.delayMicroseconds(1000) # 1000 microsecond sleep bits=bin(bits)[2:].zfill(8) self.mcp.output(self.pin_rs, char_mode) - for i in range(4): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i], True) else: self.mcp.output(self.pins_db[::-1][i], False) self.pulseEnable() - for i in range(4,8): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i-4], True) else: self.mcp.output(self.pins_db[::-1][i-4], False) self.pulseEnable() - - #See pg. 24 and 58 HD44780.pdf and http://www.avrbeginners.net/ Standard LCD bit mode - def read4bits(self, char_mode=False): - """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ -# print "First:", bin(self.mcp.direction)[2:].zfill(16) - self.mcp.output(self.pin_rs, char_mode) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data - self.mcp.output(self.pin_rw, 1) #set rw to 1 -# Configure pins for input - makeinput=True - if makeinput: - for pin in self.pins_db: - self.mcp.config(pin, self.INPUT) - self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble - bits = range(8) - # get the pins values - for i in range(4): - bt = self.mcp.input(self.pins_db[::-1][i], makeinput) # if makeinput is False, pin direction checking is supressed in input - bits[i]=bt - #print i,bt,bits[i] - self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble - self.mcp.output(self.pin_e, True) # set Enable high and keep while read 2nd nibble - # get the pins values - for i in range(4,8): - bt = self.mcp.input(self.pins_db[::-1][i-4],makeinput) - bits[i]=bt - #print i,bt,bits[i] - self.mcp.output(self.pin_e, False) # set Enable low to finish 2nd nibble - # restore to pins to output and rw to 0 - for pin in self.pins_db: - self.mcp.config(pin, self.OUTPUT) - self.mcp.output(self.pin_rw, 0) # return rw to 0 -# print "Last :", bin(self.mcp.direction)[2:].zfill(16) - return bits; - - def readBF(self): - """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ -# print "First:", bin(self.mcp.direction)[2:].zfill(16) - self.mcp.output(self.pin_rs, 0) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data - self.mcp.output(self.pin_rw, 1) #set rw to 1 -# Configure pins for input - makeinput=True - self.mcp.config(self.pins_db[::-1][1], self.INPUT) - self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble - # get the pins values - bt = self.mcp.input(self.pins_db[::-1][1], makeinput) # if makeinput is False, pin direction checking is supressed in input - self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble - self.pulseEnable() # one more pulse to get (but ingore the 2nd nibble) - # restore to pins to output and rw to 0 - self.mcp.config(self.pins_db[::-1][1], self.OUTPUT) - self.mcp.output(self.pin_rw, 0) # return rw to 0 - return bt==1 - - def waitBFlow(self): - for cnt in range(100000): - if not self.readBF(): - #print cnt - return - print "timed out of waitBFlow" def delayMicroseconds(self, microseconds): - seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds + seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds sleep(seconds) def pulseEnable(self): self.mcp.output(self.pin_e, True) - self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns + self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.mcp.output(self.pin_e, False) - #self.delayMicroseconds(1) # commands need > 37us to settle + #self.delayMicroseconds(1) # commands need > 37us to settle def message(self, text): """ Send string to LCD. Newline wraps to second line""" for char in text: if char == '\n': - self.write4bits(0xC0) # set DDRAM address 0x40 start of second line + self.write4bits(0xC0) # next line else: self.write4bits(ord(char),True) def backlight(self, color): - self.mcp.output(6, not color & 0x01) - self.mcp.output(7, not color & 0x02) - self.mcp.output(8, not color & 0x04) + self.mcp.output(6, not color & 0x01) + self.mcp.output(7, not color & 0x02) + self.mcp.output(8, not color & 0x04) def buttonPressed(self, buttonname): - if (buttonname > self.LEFT): - return false - - return not self.mcp.input(buttonname) + if (buttonname > self.LEFT): + return false + return not self.mcp.input(buttonname) if __name__ == '__main__': - lcd = Adafruit_CharLCDPlate(busnum = 1) - lcd.clear() - lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") - sleep(1) - - print " Cycle thru backlight colors 3 times " - - for i in range(3): - print "red" - lcd.backlight(lcd.RED) - sleep(1) - print "yellow" - lcd.backlight(lcd.YELLOW) - sleep(1) - print "green" - lcd.backlight(lcd.GREEN) - sleep(1) - print "teal" - lcd.backlight(lcd.TEAL) - sleep(1) - print "blue" - lcd.backlight(lcd.BLUE) - sleep(1) - print "violet" - lcd.backlight(lcd.VIOLET) - sleep(1) - print "off" - lcd.backlight(lcd.OFF) - sleep(1) - print "on" - lcd.backlight(lcd.ON) - sleep(1) - - print " Try buttons on plate" - - while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) - + lcd = Adafruit_CharLCDPlate(busnum = 0) + lcd.clear() + lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") + sleep(1) + while 1: + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) + + + while 1: + lcd.backlight(lcd.RED) + sleep(1) + lcd.backlight(lcd.YELLOW) + sleep(1) + lcd.backlight(lcd.GREEN) + sleep(1) + lcd.backlight(lcd.TEAL) + sleep(1) + lcd.backlight(lcd.BLUE) + sleep(1) + lcd.backlight(lcd.VIOLET) + sleep(1) + lcd.backlight(lcd.ON) + sleep(1) + lcd.backlight(lcd.OFF) + sleep(1) From 466f773849f1a34a4da863a2de815b12724f3761 Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 13:54:22 +1300 Subject: [PATCH 04/13] Original Code --- Adafruit_CharLCDPlate/ACLP4spaceindent.py | 227 ++++++++++++---------- 1 file changed, 119 insertions(+), 108 deletions(-) diff --git a/Adafruit_CharLCDPlate/ACLP4spaceindent.py b/Adafruit_CharLCDPlate/ACLP4spaceindent.py index 4de5400a..c0a97e6c 100644 --- a/Adafruit_CharLCDPlate/ACLP4spaceindent.py +++ b/Adafruit_CharLCDPlate/ACLP4spaceindent.py @@ -35,46 +35,46 @@ class Adafruit_CharLCDPlate: LEFT = 4 # 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 + 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 entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control - LCD_DISPLAYON = 0x04 - LCD_DISPLAYOFF = 0x00 - LCD_CURSORON = 0x02 - LCD_CURSOROFF = 0x00 - LCD_BLINKON = 0x01 - LCD_BLINKOFF = 0x00 + LCD_DISPLAYON = 0x04 + LCD_DISPLAYOFF = 0x00 + LCD_CURSORON = 0x02 + LCD_CURSOROFF = 0x00 + LCD_BLINKON = 0x01 + LCD_BLINKOFF = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 @@ -85,47 +85,51 @@ def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_r self.pin_rw = pin_rw self.pins_db = pins_db - self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + self.mcp.config(self.pin_e, self.OUTPUT) self.mcp.config(self.pin_rs, self.OUTPUT) self.mcp.config(self.pin_rw, self.OUTPUT) self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) + self.mcp.output(self.pin_e, 0) + for pin in self.pins_db: self.mcp.config(pin, self.OUTPUT) - self.write4bits(0x33) # initialization - self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x7 matrix - self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # shift cursor right - - self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF - self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS - self.displayfunction |= self.LCD_2LINE - - """ Initialize to default text direction (for romance languages) """ - self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode - - # turn on backlights! - self.mcp.config(6, self.mcp.OUTPUT) - self.mcp.config(7, self.mcp.OUTPUT) - self.mcp.config(8, self.mcp.OUTPUT) - self.mcp.output(6, 0) # red - self.mcp.output(7, 0) # green - self.mcp.output(8, 0) # blue - - # turn on pullups + + self.write4bits(0x33) # initialization + self.write4bits(0x32) # initialization + self.write4bits(0x28) # 2 line 5x7 matrix + self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor + self.write4bits(0x06) # shift cursor right + + self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + """ Initialize to default text direction (for romance languages) """ + self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode + + # turn on backlights! + self.mcp.config(6, self.mcp.OUTPUT) + self.mcp.config(7, self.mcp.OUTPUT) + self.mcp.config(8, self.mcp.OUTPUT) + self.mcp.output(6, 0) # red + self.mcp.output(7, 0) # green + self.mcp.output(8, 0) # blue + + # turn on pullups self.mcp.pullup(self.SELECT, True) self.mcp.pullup(self.LEFT, True) self.mcp.pullup(self.RIGHT, True) self.mcp.pullup(self.UP, True) self.mcp.pullup(self.DOWN, True) - self.mcp.config(self.SELECT, self.mcp.INPUT) - self.mcp.config(self.LEFT, self.mcp.INPUT) - self.mcp.config(self.RIGHT, self.mcp.INPUT) - self.mcp.config(self.DOWN, self.mcp.INPUT) - self.mcp.config(self.UP, self.mcp.INPUT) + self.mcp.config(self.SELECT, self.mcp.INPUT) + self.mcp.config(self.LEFT, self.mcp.INPUT) + self.mcp.config(self.RIGHT, self.mcp.INPUT) + self.mcp.config(self.DOWN, self.mcp.INPUT) + self.mcp.config(self.UP, self.mcp.INPUT) def begin(self, cols, lines): if (lines > 1): @@ -140,12 +144,12 @@ def home(self): def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time + self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): - row = self.numlines - 1 # we count rows starting w/0 + row = self.numlines - 1 # we count rows starting w/0 self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) def noDisplay(self): @@ -159,24 +163,24 @@ def display(self): self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): - """ Turns the underline cursor off """ + """ Turns the underline cursor on/off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): - """ Turns the underline cursor On """ + """ Cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): - """ Turn on and off the blinking cursor """ + """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def blink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol |= self.LCD_BLINKON + def noBlink(self): + """ Turn on and off the blinking cursor """ + self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def DisplayLeft(self): @@ -184,26 +188,26 @@ def DisplayLeft(self): self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) def scrollDisplayRight(self): - """ These commands scroll the display without changing the RAM """ + """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); def leftToRight(self): - """ This is for text that flows Left to Right """ + """ This is for text that flows Left to Right """ self.displaymode |= self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); def rightToLeft(self): - """ This is for text that flows Right to Left """ + """ This is for text that flows Right to Left """ self.displaymode &= ~self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def autoscroll(self): - """ This will 'right justify' text from the cursor """ + """ This will 'right justify' text from the cursor """ self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def noAutoscroll(self): - """ This will 'left justify' text from the cursor """ + """ This will 'left justify' text from the cursor """ self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) @@ -212,12 +216,14 @@ def write4bits(self, bits, char_mode=False): #self.delayMicroseconds(1000) # 1000 microsecond sleep bits=bin(bits)[2:].zfill(8) self.mcp.output(self.pin_rs, char_mode) + for i in range(4): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i], True) else: self.mcp.output(self.pins_db[::-1][i], False) self.pulseEnable() + for i in range(4,8): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i-4], True) @@ -226,14 +232,14 @@ def write4bits(self, bits, char_mode=False): self.pulseEnable() def delayMicroseconds(self, microseconds): - seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds + seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds sleep(seconds) def pulseEnable(self): self.mcp.output(self.pin_e, True) - self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns + self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.mcp.output(self.pin_e, False) - #self.delayMicroseconds(1) # commands need > 37us to settle + #self.delayMicroseconds(1) # commands need > 37us to settle def message(self, text): """ Send string to LCD. Newline wraps to second line""" @@ -244,14 +250,15 @@ def message(self, text): self.write4bits(ord(char),True) def backlight(self, color): - self.mcp.output(6, not color & 0x01) - self.mcp.output(7, not color & 0x02) - self.mcp.output(8, not color & 0x04) + self.mcp.output(6, not color & 0x01) + self.mcp.output(7, not color & 0x02) + self.mcp.output(8, not color & 0x04) def buttonPressed(self, buttonname): - if (buttonname > self.LEFT): - return false - return not self.mcp.input(buttonname) + if (buttonname > self.LEFT): + return false + + return not self.mcp.input(buttonname) if __name__ == '__main__': @@ -261,33 +268,37 @@ def buttonPressed(self, buttonname): lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") sleep(1) while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) while 1: - lcd.backlight(lcd.RED) - sleep(1) - lcd.backlight(lcd.YELLOW) - sleep(1) - lcd.backlight(lcd.GREEN) - sleep(1) - lcd.backlight(lcd.TEAL) - sleep(1) - lcd.backlight(lcd.BLUE) - sleep(1) - lcd.backlight(lcd.VIOLET) - sleep(1) - lcd.backlight(lcd.ON) - sleep(1) - lcd.backlight(lcd.OFF) - sleep(1) + lcd.backlight(lcd.RED) + sleep(1) + lcd.backlight(lcd.YELLOW) + sleep(1) + lcd.backlight(lcd.GREEN) + sleep(1) + lcd.backlight(lcd.TEAL) + sleep(1) + lcd.backlight(lcd.BLUE) + sleep(1) + lcd.backlight(lcd.VIOLET) + sleep(1) + lcd.backlight(lcd.ON) + sleep(1) + lcd.backlight(lcd.OFF) + sleep(1) From 30252340c0fd66bd63934973d2f15e63cee4811f Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 14:03:27 +1300 Subject: [PATCH 05/13] removed file --- Adafruit_CharLCDPlate/ACLP4spaceindent.py | 304 ---------------------- 1 file changed, 304 deletions(-) delete mode 100644 Adafruit_CharLCDPlate/ACLP4spaceindent.py diff --git a/Adafruit_CharLCDPlate/ACLP4spaceindent.py b/Adafruit_CharLCDPlate/ACLP4spaceindent.py deleted file mode 100644 index c0a97e6c..00000000 --- a/Adafruit_CharLCDPlate/ACLP4spaceindent.py +++ /dev/null @@ -1,304 +0,0 @@ -#!/usr/bin/pythonhttp://raspberrypi.local/editor - -# -# 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 time import sleep -from Adafruit_I2C import Adafruit_I2C -from Adafruit_MCP230xx import Adafruit_MCP230XX -import smbus - - -class Adafruit_CharLCDPlate: - - OUTPUT = 0 - INPUT = 1 - - # LED colors - RED = 0x01 - GREEN = 0x02 - BLUE = 0x04 - YELLOW = 0x03 - TEAL = 0x06 - VIOLET = 0x05 - ON = 0x07 - OFF = 0x0 - - # buttons - SELECT = 0 - RIGHT = 1 - DOWN = 2 - UP = 3 - LEFT = 4 - - # 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 entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 - - # 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/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - - # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 - - # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 - - - - - def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): - self.pin_rs = pin_rs - self.pin_e = pin_e - self.pin_rw = pin_rw - self.pins_db = pins_db - - self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) - - self.mcp.config(self.pin_e, self.OUTPUT) - self.mcp.config(self.pin_rs, self.OUTPUT) - self.mcp.config(self.pin_rw, self.OUTPUT) - self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) - - for pin in self.pins_db: - self.mcp.config(pin, self.OUTPUT) - - self.write4bits(0x33) # initialization - self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x7 matrix - self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # shift cursor right - - self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF - - self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS - self.displayfunction |= self.LCD_2LINE - - """ Initialize to default text direction (for romance languages) """ - self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode - - # turn on backlights! - self.mcp.config(6, self.mcp.OUTPUT) - self.mcp.config(7, self.mcp.OUTPUT) - self.mcp.config(8, self.mcp.OUTPUT) - self.mcp.output(6, 0) # red - self.mcp.output(7, 0) # green - self.mcp.output(8, 0) # blue - - # turn on pullups - self.mcp.pullup(self.SELECT, True) - self.mcp.pullup(self.LEFT, True) - self.mcp.pullup(self.RIGHT, True) - self.mcp.pullup(self.UP, True) - self.mcp.pullup(self.DOWN, True) - self.mcp.config(self.SELECT, self.mcp.INPUT) - self.mcp.config(self.LEFT, self.mcp.INPUT) - self.mcp.config(self.RIGHT, self.mcp.INPUT) - self.mcp.config(self.DOWN, self.mcp.INPUT) - self.mcp.config(self.UP, self.mcp.INPUT) - - def begin(self, cols, lines): - if (lines > 1): - self.numlines = lines - self.displayfunction |= self.LCD_2LINE - self.currline = 0 - self.clear() - - def home(self): - self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero - self.delayMicroseconds(2000) # this command takes a long time! - - def clear(self): - self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time - - def setCursor(self, col, row): - self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] - if ( row > self.numlines ): - row = self.numlines - 1 # we count rows starting w/0 - self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) - - def noDisplay(self): - """ Turn the display off (quickly) """ - self.displaycontrol &= ~self.LCD_DISPLAYON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def display(self): - """ Turn the display on (quickly) """ - self.displaycontrol |= self.LCD_DISPLAYON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noCursor(self): - """ Turns the underline cursor on/off """ - self.displaycontrol &= ~self.LCD_CURSORON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - - def cursor(self): - """ Cursor On """ - self.displaycontrol |= self.LCD_CURSORON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noBlink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noBlink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def DisplayLeft(self): - """ These commands scroll the display without changing the RAM """ - self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) - - def scrollDisplayRight(self): - """ These commands scroll the display without changing the RAM """ - self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); - - def leftToRight(self): - """ This is for text that flows Left to Right """ - self.displaymode |= self.LCD_ENTRYLEFT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); - - def rightToLeft(self): - """ This is for text that flows Right to Left """ - self.displaymode &= ~self.LCD_ENTRYLEFT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def autoscroll(self): - """ This will 'right justify' text from the cursor """ - self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def noAutoscroll(self): - """ This will 'left justify' text from the cursor """ - self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def write4bits(self, bits, char_mode=False): - """ Send command to LCD """ - #self.delayMicroseconds(1000) # 1000 microsecond sleep - bits=bin(bits)[2:].zfill(8) - self.mcp.output(self.pin_rs, char_mode) - - for i in range(4): - if bits[i] == "1": - self.mcp.output(self.pins_db[::-1][i], True) - else: - self.mcp.output(self.pins_db[::-1][i], False) - self.pulseEnable() - - for i in range(4,8): - if bits[i] == "1": - self.mcp.output(self.pins_db[::-1][i-4], True) - else: - self.mcp.output(self.pins_db[::-1][i-4], False) - self.pulseEnable() - - def delayMicroseconds(self, microseconds): - seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds - sleep(seconds) - - def pulseEnable(self): - self.mcp.output(self.pin_e, True) - self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns - self.mcp.output(self.pin_e, False) - #self.delayMicroseconds(1) # commands need > 37us to settle - - def message(self, text): - """ Send string to LCD. Newline wraps to second line""" - for char in text: - if char == '\n': - self.write4bits(0xC0) # next line - else: - self.write4bits(ord(char),True) - - def backlight(self, color): - self.mcp.output(6, not color & 0x01) - self.mcp.output(7, not color & 0x02) - self.mcp.output(8, not color & 0x04) - - def buttonPressed(self, buttonname): - if (buttonname > self.LEFT): - return false - - return not self.mcp.input(buttonname) - - -if __name__ == '__main__': - - lcd = Adafruit_CharLCDPlate(busnum = 0) - lcd.clear() - lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") - sleep(1) - while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) - - - while 1: - lcd.backlight(lcd.RED) - sleep(1) - lcd.backlight(lcd.YELLOW) - sleep(1) - lcd.backlight(lcd.GREEN) - sleep(1) - lcd.backlight(lcd.TEAL) - sleep(1) - lcd.backlight(lcd.BLUE) - sleep(1) - lcd.backlight(lcd.VIOLET) - sleep(1) - lcd.backlight(lcd.ON) - sleep(1) - lcd.backlight(lcd.OFF) - sleep(1) - From 6af2219777b370d6ee3c92ac64661bf10f75ca7a Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 14:52:00 +1300 Subject: [PATCH 06/13] Back to original code from Adafruit for Adafruit_CharLCDPlate.py --- .../Adafruit_CharLCDPlate.py | 692 ++++++++---------- 1 file changed, 303 insertions(+), 389 deletions(-) diff --git a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py index 6e7af7a1..f0e2a0b3 100644 --- a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py +++ b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py @@ -1,389 +1,303 @@ -#!/usr/bin/pythonhttp://raspberrypi.local/editor - -# -# 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 time import sleep -from Adafruit_I2C import Adafruit_I2C -from Adafruit_MCP230xx import Adafruit_MCP230XX -import smbus - - -class Adafruit_CharLCDPlate: - - OUTPUT = 0 - INPUT = 1 - - # LED colors - RED = 0x01 - GREEN = 0x02 - BLUE = 0x04 - YELLOW = 0x03 - TEAL = 0x06 - VIOLET = 0x05 - ON = 0x07 - OFF = 0x0 - - # buttons - SELECT = 0 - RIGHT = 1 - DOWN = 2 - UP = 3 - LEFT = 4 - - # 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 entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 - - # 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/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - - # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 - - # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 - - - - - def __init__(self, busnum=1, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): - self.pin_rs = pin_rs - self.pin_e = pin_e - self.pin_rw = pin_rw - self.pins_db = pins_db - - self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) - - self.mcp.config(self.pin_e, self.OUTPUT) - self.mcp.config(self.pin_rs, self.OUTPUT) - self.mcp.config(self.pin_rw, self.OUTPUT) - self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) - - for pin in self.pins_db: - self.mcp.config(pin, self.OUTPUT) - - self.write4bits(0x33) # initialization - self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x8 matrix - self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # set cursor incrementing and no shift of display - - self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF - - self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS - self.displayfunction |= self.LCD_2LINE - - """ Initialize to default text direction (for romance languages) """ - self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode - - # turn on backlights! - self.mcp.config(6, self.mcp.OUTPUT) - self.mcp.config(7, self.mcp.OUTPUT) - self.mcp.config(8, self.mcp.OUTPUT) - self.mcp.output(6, 0) # red - self.mcp.output(7, 0) # green - self.mcp.output(8, 0) # blue - - # turn on pullups - self.mcp.pullup(self.SELECT, True) - self.mcp.pullup(self.LEFT, True) - self.mcp.pullup(self.RIGHT, True) - self.mcp.pullup(self.UP, True) - self.mcp.pullup(self.DOWN, True) - self.mcp.config(self.SELECT, self.mcp.INPUT) - self.mcp.config(self.LEFT, self.mcp.INPUT) - self.mcp.config(self.RIGHT, self.mcp.INPUT) - self.mcp.config(self.DOWN, self.mcp.INPUT) - self.mcp.config(self.UP, self.mcp.INPUT) - - def begin(self, cols, lines): - if (lines > 1): - self.numlines = lines - self.displayfunction |= self.LCD_2LINE - self.currline = 0 - self.clear() - - def home(self): - self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero - self.waitBFlow() #wait for Busy flag low - - - def clear(self): - self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.waitBFlow() #wait for Busy flag low - - def setCursor(self, col, row): - self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] - if ( row > self.numlines ): - row = self.numlines - 1 # we count rows starting w/0 - self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) - - def noDisplay(self): - """ Turn the display off (quickly) """ - self.displaycontrol &= ~self.LCD_DISPLAYON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def display(self): - """ Turn the display on (quickly) """ - self.displaycontrol |= self.LCD_DISPLAYON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noCursor(self): - """ underline cursor off """ - self.displaycontrol &= ~self.LCD_CURSORON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - - def cursor(self): - """ underline Cursor On """ - self.displaycontrol |= self.LCD_CURSORON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def ToggleCursor(self): - """ Toggles the underline cursor On/Off bb""" - self.displaycontrol ^= self.LCD_CURSORON - self.delayMicroseconds(200000) - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noBlink(self): - """ Turn off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def blink(self): - """ Turn on the blinking cursor""" - self.displaycontrol |= self.LCD_BLINKON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def ToggleBlink(self): - """ Toggles the blinking cursor""" - self.displaycontrol ^= self.LCD_BLINKON - self.delayMicroseconds(200000) - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - - def DisplayLeft(self): - """ These commands scroll the display without changing the RAM """ - self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) - - def scrollDisplayRight(self): - """ These commands scroll the display without changing the RAM """ - self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); - - def leftToRight(self): - """ This is for text that flows Left to Right """ - self.displaymode |= self.LCD_ENTRYLEFT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); - - def rightToLeft(self): - """ This is for text that flows Right to Left """ - self.displaymode &= ~self.LCD_ENTRYLEFT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def autoscroll(self): - """ This will 'right justify' text from the cursor """ - self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def noAutoscroll(self): - """ This will 'left justify' text from the cursor """ - self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def write4bits(self, bits, char_mode=False): - """ Send command to LCD """ - #self.delayMicroseconds(1000) # 1000 microsecond sleep - bits=bin(bits)[2:].zfill(8) - self.mcp.output(self.pin_rs, char_mode) - - for i in range(4): - if bits[i] == "1": - self.mcp.output(self.pins_db[::-1][i], True) - else: - self.mcp.output(self.pins_db[::-1][i], False) - self.pulseEnable() - - for i in range(4,8): - if bits[i] == "1": - self.mcp.output(self.pins_db[::-1][i-4], True) - else: - self.mcp.output(self.pins_db[::-1][i-4], False) - self.pulseEnable() - - #See pg. 24 and 58 HD44780.pdf and http://www.avrbeginners.net/ Standard LCD bit mode - def read4bits(self, char_mode=False): - """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ -# print "First:", bin(self.mcp.direction)[2:].zfill(16) - self.mcp.output(self.pin_rs, char_mode) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data - self.mcp.output(self.pin_rw, 1) #set rw to 1 -# Configure pins for input - makeinput=True - if makeinput: - for pin in self.pins_db: - self.mcp.config(pin, self.INPUT) - self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble - bits = range(8) - # get the pins values - for i in range(4): - bt = self.mcp.input(self.pins_db[::-1][i], makeinput) # if makeinput is False, pin direction checking is supressed in input - bits[i]=bt - #print i,bt,bits[i] - self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble - self.mcp.output(self.pin_e, True) # set Enable high and keep while read 2nd nibble - # get the pins values - for i in range(4,8): - bt = self.mcp.input(self.pins_db[::-1][i-4],makeinput) - bits[i]=bt - #print i,bt,bits[i] - self.mcp.output(self.pin_e, False) # set Enable low to finish 2nd nibble - # restore to pins to output and rw to 0 - for pin in self.pins_db: - self.mcp.config(pin, self.OUTPUT) - self.mcp.output(self.pin_rw, 0) # return rw to 0 -# print "Last :", bin(self.mcp.direction)[2:].zfill(16) - return bits; - - def readBF(self): - """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ -# print "First:", bin(self.mcp.direction)[2:].zfill(16) - self.mcp.output(self.pin_rs, 0) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data - self.mcp.output(self.pin_rw, 1) #set rw to 1 -# Configure pins for input - makeinput=True - self.mcp.config(self.pins_db[::-1][1], self.INPUT) - self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble - # get the pins values - bt = self.mcp.input(self.pins_db[::-1][1], makeinput) # if makeinput is False, pin direction checking is supressed in input - self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble - self.pulseEnable() # one more pulse to get (but ingore the 2nd nibble) - # restore to pins to output and rw to 0 - self.mcp.config(self.pins_db[::-1][1], self.OUTPUT) - self.mcp.output(self.pin_rw, 0) # return rw to 0 - return bt==1 - - def waitBFlow(self): - for cnt in range(100000): - if not self.readBF(): - #print cnt - return - print "timed out of waitBFlow" - - def delayMicroseconds(self, microseconds): - seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds - sleep(seconds) - - def pulseEnable(self): - self.mcp.output(self.pin_e, True) - self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns - self.mcp.output(self.pin_e, False) - #self.delayMicroseconds(1) # commands need > 37us to settle - - def message(self, text): - """ Send string to LCD. Newline wraps to second line""" - for char in text: - if char == '\n': - self.write4bits(0xC0) # set DDRAM address 0x40 start of second line - else: - self.write4bits(ord(char),True) - - def backlight(self, color): - self.mcp.output(6, not color & 0x01) - self.mcp.output(7, not color & 0x02) - self.mcp.output(8, not color & 0x04) - - def buttonPressed(self, buttonname): - if (buttonname > self.LEFT): - return false - - return not self.mcp.input(buttonname) - - -if __name__ == '__main__': - - lcd = Adafruit_CharLCDPlate(busnum = 1) - lcd.clear() - lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") - sleep(1) - - print " Cycle thru backlight colors 3 times " - - for i in range(3): - print "red" - lcd.backlight(lcd.RED) - sleep(1) - print "yellow" - lcd.backlight(lcd.YELLOW) - sleep(1) - print "green" - lcd.backlight(lcd.GREEN) - sleep(1) - print "teal" - lcd.backlight(lcd.TEAL) - sleep(1) - print "blue" - lcd.backlight(lcd.BLUE) - sleep(1) - print "violet" - lcd.backlight(lcd.VIOLET) - sleep(1) - print "off" - lcd.backlight(lcd.OFF) - sleep(1) - print "on" - lcd.backlight(lcd.ON) - sleep(1) - - print " Try buttons on plate" - - while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) - - +#!/usr/bin/pythonhttp://raspberrypi.local/editor + +# +# 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 time import sleep +from Adafruit_I2C import Adafruit_I2C +from Adafruit_MCP230xx import Adafruit_MCP230XX +import smbus + + +class Adafruit_CharLCDPlate: + + OUTPUT = 0 + INPUT = 1 + + # LED colors + RED = 0x01 + GREEN = 0x02 + BLUE = 0x04 + YELLOW = 0x03 + TEAL = 0x06 + VIOLET = 0x05 + ON = 0x07 + OFF = 0x0 + + # buttons + SELECT = 0 + RIGHT = 1 + DOWN = 2 + UP = 3 + LEFT = 4 + + # 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 entry mode + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 + + # 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/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + + # flags for display/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 + + # flags for function set + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 + + + + + def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): + self.pin_rs = pin_rs + self.pin_e = pin_e + self.pin_rw = pin_rw + self.pins_db = pins_db + + self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + + self.mcp.config(self.pin_e, self.OUTPUT) + self.mcp.config(self.pin_rs, self.OUTPUT) + self.mcp.config(self.pin_rw, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) + self.mcp.output(self.pin_e, 0) + + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + + self.write4bits(0x33) # initialization + self.write4bits(0x32) # initialization + self.write4bits(0x28) # 2 line 5x7 matrix + self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor + self.write4bits(0x06) # shift cursor right + + self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + """ Initialize to default text direction (for romance languages) """ + self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode + + # turn on backlights! + self.mcp.config(6, self.mcp.OUTPUT) + self.mcp.config(7, self.mcp.OUTPUT) + self.mcp.config(8, self.mcp.OUTPUT) + self.mcp.output(6, 0) # red + self.mcp.output(7, 0) # green + self.mcp.output(8, 0) # blue + + # turn on pullups + self.mcp.pullup(self.SELECT, True) + self.mcp.pullup(self.LEFT, True) + self.mcp.pullup(self.RIGHT, True) + self.mcp.pullup(self.UP, True) + self.mcp.pullup(self.DOWN, True) + self.mcp.config(self.SELECT, self.mcp.INPUT) + self.mcp.config(self.LEFT, self.mcp.INPUT) + self.mcp.config(self.RIGHT, self.mcp.INPUT) + self.mcp.config(self.DOWN, self.mcp.INPUT) + self.mcp.config(self.UP, self.mcp.INPUT) + + def begin(self, cols, lines): + if (lines > 1): + self.numlines = lines + self.displayfunction |= self.LCD_2LINE + self.currline = 0 + self.clear() + + def home(self): + self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero + self.delayMicroseconds(2000) # this command takes a long time! + + def clear(self): + self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display + self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time + + def setCursor(self, col, row): + self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] + if ( row > self.numlines ): + row = self.numlines - 1 # we count rows starting w/0 + self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) + + def noDisplay(self): + """ Turn the display off (quickly) """ + self.displaycontrol &= ~self.LCD_DISPLAYON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def display(self): + """ Turn the display on (quickly) """ + self.displaycontrol |= self.LCD_DISPLAYON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noCursor(self): + """ Turns the underline cursor on/off """ + self.displaycontrol &= ~self.LCD_CURSORON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + + def cursor(self): + """ Cursor On """ + self.displaycontrol |= self.LCD_CURSORON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noBlink(self): + """ Turn on and off the blinking cursor """ + self.displaycontrol &= ~self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noBlink(self): + """ Turn on and off the blinking cursor """ + self.displaycontrol &= ~self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def DisplayLeft(self): + """ These commands scroll the display without changing the RAM """ + self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) + + def scrollDisplayRight(self): + """ These commands scroll the display without changing the RAM """ + self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); + + def leftToRight(self): + """ This is for text that flows Left to Right """ + self.displaymode |= self.LCD_ENTRYLEFT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); + + def rightToLeft(self): + """ This is for text that flows Right to Left """ + self.displaymode &= ~self.LCD_ENTRYLEFT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def autoscroll(self): + """ This will 'right justify' text from the cursor """ + self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def noAutoscroll(self): + """ This will 'left justify' text from the cursor """ + self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def write4bits(self, bits, char_mode=False): + """ Send command to LCD """ + #self.delayMicroseconds(1000) # 1000 microsecond sleep + bits=bin(bits)[2:].zfill(8) + self.mcp.output(self.pin_rs, char_mode) + + for i in range(4): + if bits[i] == "1": + self.mcp.output(self.pins_db[::-1][i], True) + else: + self.mcp.output(self.pins_db[::-1][i], False) + self.pulseEnable() + + for i in range(4,8): + if bits[i] == "1": + self.mcp.output(self.pins_db[::-1][i-4], True) + else: + self.mcp.output(self.pins_db[::-1][i-4], False) + self.pulseEnable() + + def delayMicroseconds(self, microseconds): + seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds + sleep(seconds) + + def pulseEnable(self): + self.mcp.output(self.pin_e, True) + self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns + self.mcp.output(self.pin_e, False) + #self.delayMicroseconds(1) # commands need > 37us to settle + + def message(self, text): + """ Send string to LCD. Newline wraps to second line""" + for char in text: + if char == '\n': + self.write4bits(0xC0) # next line + else: + self.write4bits(ord(char),True) + + def backlight(self, color): + self.mcp.output(6, not color & 0x01) + self.mcp.output(7, not color & 0x02) + self.mcp.output(8, not color & 0x04) + + def buttonPressed(self, buttonname): + if (buttonname > self.LEFT): + return false + + return not self.mcp.input(buttonname) + + +if __name__ == '__main__': + + lcd = Adafruit_CharLCDPlate(busnum = 0) + lcd.clear() + lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") + sleep(1) + while 1: + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) + + + while 1: + lcd.backlight(lcd.RED) + sleep(1) + lcd.backlight(lcd.YELLOW) + sleep(1) + lcd.backlight(lcd.GREEN) + sleep(1) + lcd.backlight(lcd.TEAL) + sleep(1) + lcd.backlight(lcd.BLUE) + sleep(1) + lcd.backlight(lcd.VIOLET) + sleep(1) + lcd.backlight(lcd.ON) + sleep(1) + lcd.backlight(lcd.OFF) + sleep(1) From d957bcb67a2a11b30d39a4a88930e88efffbdccc Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 15:01:05 +1300 Subject: [PATCH 07/13] Original Code from Adafruit made Pep8 with all tabs removed so indent = 4 spaces --- .../Adafruit_CharLCDPlate.py | 227 +++++++++--------- 1 file changed, 108 insertions(+), 119 deletions(-) diff --git a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py index f0e2a0b3..77f08099 100644 --- a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py +++ b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py @@ -35,46 +35,46 @@ class Adafruit_CharLCDPlate: LEFT = 4 # 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 + 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 entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control - LCD_DISPLAYON = 0x04 - LCD_DISPLAYOFF = 0x00 - LCD_CURSORON = 0x02 - LCD_CURSOROFF = 0x00 - LCD_BLINKON = 0x01 - LCD_BLINKOFF = 0x00 + LCD_DISPLAYON = 0x04 + LCD_DISPLAYOFF = 0x00 + LCD_CURSORON = 0x02 + LCD_CURSOROFF = 0x00 + LCD_BLINKON = 0x01 + LCD_BLINKOFF = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 @@ -85,51 +85,47 @@ def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_r self.pin_rw = pin_rw self.pins_db = pins_db - self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) - + self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) self.mcp.config(self.pin_e, self.OUTPUT) self.mcp.config(self.pin_rs, self.OUTPUT) self.mcp.config(self.pin_rw, self.OUTPUT) self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) - + self.mcp.output(self.pin_e, 0) for pin in self.pins_db: self.mcp.config(pin, self.OUTPUT) - - self.write4bits(0x33) # initialization - self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x7 matrix - self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # shift cursor right - - self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF - - self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS - self.displayfunction |= self.LCD_2LINE - - """ Initialize to default text direction (for romance languages) """ - self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode - - # turn on backlights! - self.mcp.config(6, self.mcp.OUTPUT) - self.mcp.config(7, self.mcp.OUTPUT) - self.mcp.config(8, self.mcp.OUTPUT) - self.mcp.output(6, 0) # red - self.mcp.output(7, 0) # green - self.mcp.output(8, 0) # blue - - # turn on pullups + self.write4bits(0x33) # initialization + self.write4bits(0x32) # initialization + self.write4bits(0x28) # 2 line 5x7 matrix + self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor + self.write4bits(0x06) # shift cursor right + + self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + """ Initialize to default text direction (for romance languages) """ + self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode + + # turn on backlights! + self.mcp.config(6, self.mcp.OUTPUT) + self.mcp.config(7, self.mcp.OUTPUT) + self.mcp.config(8, self.mcp.OUTPUT) + self.mcp.output(6, 0) # red + self.mcp.output(7, 0) # green + self.mcp.output(8, 0) # blue + + # turn on pullups self.mcp.pullup(self.SELECT, True) self.mcp.pullup(self.LEFT, True) self.mcp.pullup(self.RIGHT, True) self.mcp.pullup(self.UP, True) self.mcp.pullup(self.DOWN, True) - self.mcp.config(self.SELECT, self.mcp.INPUT) - self.mcp.config(self.LEFT, self.mcp.INPUT) - self.mcp.config(self.RIGHT, self.mcp.INPUT) - self.mcp.config(self.DOWN, self.mcp.INPUT) - self.mcp.config(self.UP, self.mcp.INPUT) + self.mcp.config(self.SELECT, self.mcp.INPUT) + self.mcp.config(self.LEFT, self.mcp.INPUT) + self.mcp.config(self.RIGHT, self.mcp.INPUT) + self.mcp.config(self.DOWN, self.mcp.INPUT) + self.mcp.config(self.UP, self.mcp.INPUT) def begin(self, cols, lines): if (lines > 1): @@ -144,12 +140,12 @@ def home(self): def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time + self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): - row = self.numlines - 1 # we count rows starting w/0 + row = self.numlines - 1 # we count rows starting w/0 self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) def noDisplay(self): @@ -163,24 +159,24 @@ def display(self): self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): - """ Turns the underline cursor on/off """ + """ Turns the underline cursor off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): - """ Cursor On """ + """ Turns the underline cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): - """ Turn on and off the blinking cursor """ + """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - def noBlink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON + def blink(self): + """ Turn on and off the blinking cursor """ + self.displaycontrol |= self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def DisplayLeft(self): @@ -188,26 +184,26 @@ def DisplayLeft(self): self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) def scrollDisplayRight(self): - """ These commands scroll the display without changing the RAM """ + """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); def leftToRight(self): - """ This is for text that flows Left to Right """ + """ This is for text that flows Left to Right """ self.displaymode |= self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); def rightToLeft(self): - """ This is for text that flows Right to Left """ + """ This is for text that flows Right to Left """ self.displaymode &= ~self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def autoscroll(self): - """ This will 'right justify' text from the cursor """ + """ This will 'right justify' text from the cursor """ self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def noAutoscroll(self): - """ This will 'left justify' text from the cursor """ + """ This will 'left justify' text from the cursor """ self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) @@ -216,14 +212,12 @@ def write4bits(self, bits, char_mode=False): #self.delayMicroseconds(1000) # 1000 microsecond sleep bits=bin(bits)[2:].zfill(8) self.mcp.output(self.pin_rs, char_mode) - for i in range(4): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i], True) else: self.mcp.output(self.pins_db[::-1][i], False) self.pulseEnable() - for i in range(4,8): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i-4], True) @@ -232,14 +226,14 @@ def write4bits(self, bits, char_mode=False): self.pulseEnable() def delayMicroseconds(self, microseconds): - seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds + seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds sleep(seconds) def pulseEnable(self): self.mcp.output(self.pin_e, True) - self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns + self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.mcp.output(self.pin_e, False) - #self.delayMicroseconds(1) # commands need > 37us to settle + #self.delayMicroseconds(1) # commands need > 37us to settle def message(self, text): """ Send string to LCD. Newline wraps to second line""" @@ -250,15 +244,14 @@ def message(self, text): self.write4bits(ord(char),True) def backlight(self, color): - self.mcp.output(6, not color & 0x01) - self.mcp.output(7, not color & 0x02) - self.mcp.output(8, not color & 0x04) + self.mcp.output(6, not color & 0x01) + self.mcp.output(7, not color & 0x02) + self.mcp.output(8, not color & 0x04) def buttonPressed(self, buttonname): - if (buttonname > self.LEFT): - return false - - return not self.mcp.input(buttonname) + if (buttonname > self.LEFT): + return false + return not self.mcp.input(buttonname) if __name__ == '__main__': @@ -268,36 +261,32 @@ def buttonPressed(self, buttonname): lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") sleep(1) while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) while 1: - lcd.backlight(lcd.RED) - sleep(1) - lcd.backlight(lcd.YELLOW) - sleep(1) - lcd.backlight(lcd.GREEN) - sleep(1) - lcd.backlight(lcd.TEAL) - sleep(1) - lcd.backlight(lcd.BLUE) - sleep(1) - lcd.backlight(lcd.VIOLET) - sleep(1) - lcd.backlight(lcd.ON) - sleep(1) - lcd.backlight(lcd.OFF) - sleep(1) + lcd.backlight(lcd.RED) + sleep(1) + lcd.backlight(lcd.YELLOW) + sleep(1) + lcd.backlight(lcd.GREEN) + sleep(1) + lcd.backlight(lcd.TEAL) + sleep(1) + lcd.backlight(lcd.BLUE) + sleep(1) + lcd.backlight(lcd.VIOLET) + sleep(1) + lcd.backlight(lcd.ON) + sleep(1) + lcd.backlight(lcd.OFF) + sleep(1) From 9d037355cf2da4d4e7f34f268a510f5d87569142 Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 15:03:54 +1300 Subject: [PATCH 08/13] Addition Routines and corrections added conforming to pep8 standard --- .../Adafruit_CharLCDPlate.py | 214 +++++++++++++----- 1 file changed, 155 insertions(+), 59 deletions(-) diff --git a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py index 77f08099..b5da2bc1 100644 --- a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py +++ b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py @@ -1,10 +1,10 @@ -#!/usr/bin/pythonhttp://raspberrypi.local/editor +#!/usr/bin/pythonhttp://raspberrypi.local/editor # # 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 time import sleep from Adafruit_I2C import Adafruit_I2C @@ -35,71 +35,75 @@ class Adafruit_CharLCDPlate: LEFT = 4 # 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 + 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 entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control - LCD_DISPLAYON = 0x04 - LCD_DISPLAYOFF = 0x00 - LCD_CURSORON = 0x02 - LCD_CURSOROFF = 0x00 - LCD_BLINKON = 0x01 - LCD_BLINKOFF = 0x00 + LCD_DISPLAYON = 0x04 + LCD_DISPLAYOFF = 0x00 + LCD_CURSORON = 0x02 + LCD_CURSOROFF = 0x00 + LCD_BLINKON = 0x01 + LCD_BLINKOFF = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 - def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): + def __init__(self, busnum=1, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): self.pin_rs = pin_rs self.pin_e = pin_e self.pin_rw = pin_rw self.pins_db = pins_db self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + self.mcp.config(self.pin_e, self.OUTPUT) self.mcp.config(self.pin_rs, self.OUTPUT) self.mcp.config(self.pin_rw, self.OUTPUT) self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) + self.mcp.output(self.pin_e, 0) + for pin in self.pins_db: self.mcp.config(pin, self.OUTPUT) + self.write4bits(0x33) # initialization self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x7 matrix + self.write4bits(0x28) # 2 line 5x8 matrix self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # shift cursor right + self.write4bits(0x06) # set cursor incrementing and no shift of display self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS self.displayfunction |= self.LCD_2LINE @@ -136,12 +140,13 @@ def begin(self, cols, lines): def home(self): self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero - self.delayMicroseconds(2000) # this command takes a long time! + self.waitBFlow() #wait for Busy flag low + def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time - + self.waitBFlow() #wait for Busy flag low + def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): @@ -159,26 +164,39 @@ def display(self): self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): - """ Turns the underline cursor off """ + """ underline cursor off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): - """ Turns the underline cursor On """ + """ underline Cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + def ToggleCursor(self): + """ Toggles the underline cursor On/Off bb""" + self.displaycontrol ^= self.LCD_CURSORON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + def noBlink(self): - """ Turn on and off the blinking cursor """ + """ Turn off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def blink(self): - """ Turn on and off the blinking cursor """ + """ Turn on the blinking cursor""" self.displaycontrol |= self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + def ToggleBlink(self): + """ Toggles the blinking cursor""" + self.displaycontrol ^= self.LCD_BLINKON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def DisplayLeft(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) @@ -212,18 +230,78 @@ def write4bits(self, bits, char_mode=False): #self.delayMicroseconds(1000) # 1000 microsecond sleep bits=bin(bits)[2:].zfill(8) self.mcp.output(self.pin_rs, char_mode) + for i in range(4): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i], True) else: self.mcp.output(self.pins_db[::-1][i], False) self.pulseEnable() + for i in range(4,8): if bits[i] == "1": self.mcp.output(self.pins_db[::-1][i-4], True) else: self.mcp.output(self.pins_db[::-1][i-4], False) self.pulseEnable() + + #See pg. 24 and 58 HD44780.pdf and http://www.avrbeginners.net/ Standard LCD bit mode + def read4bits(self, char_mode=False): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, char_mode) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 + # Configure pins for input + makeinput=True + if makeinput: + for pin in self.pins_db: + self.mcp.config(pin, self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + bits = range(8) + # get the pins values + for i in range(4): + bt = self.mcp.input(self.pins_db[::-1][i], makeinput) # if makeinput is False, pin direction checking is supressed in input + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.mcp.output(self.pin_e, True) # set Enable high and keep while read 2nd nibble + # get the pins values + for i in range(4,8): + bt = self.mcp.input(self.pins_db[::-1][i-4],makeinput) + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish 2nd nibble + # restore the pins to output and rw to 0 + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 +# print "Last :", bin(self.mcp.direction)[2:].zfill(16) + return bits; + + def readBF(self): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, 0) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 + # Configure pins for input + makeinput=True + self.mcp.config(self.pins_db[::-1][1], self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + # get the pins values + bt = self.mcp.input(self.pins_db[::-1][1], makeinput) # if makeinput is False, pin direction checking is supressed in input + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.pulseEnable() # one more pulse to get (but ingore the 2nd nibble) + # restore the pins to output and rw to 0 + self.mcp.config(self.pins_db[::-1][1], self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 + return bt==1 + + def waitBFlow(self): + for cnt in range(100000): + if not self.readBF(): + #print cnt + return + print "timed out of waitBFlow" def delayMicroseconds(self, microseconds): seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds @@ -239,7 +317,7 @@ def message(self, text): """ Send string to LCD. Newline wraps to second line""" for char in text: if char == '\n': - self.write4bits(0xC0) # next line + self.write4bits(0xC0) # set DDRAM address 0x40 start of second line else: self.write4bits(ord(char),True) @@ -251,42 +329,60 @@ def backlight(self, color): def buttonPressed(self, buttonname): if (buttonname > self.LEFT): return false + return not self.mcp.input(buttonname) if __name__ == '__main__': - lcd = Adafruit_CharLCDPlate(busnum = 0) + lcd = Adafruit_CharLCDPlate(busnum = 1) lcd.clear() lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") sleep(1) - while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) + print " Cycle thru backlight colors 3 times " - while 1: + for i in range(3): + print "red" lcd.backlight(lcd.RED) sleep(1) + print "yellow" lcd.backlight(lcd.YELLOW) sleep(1) + print "green" lcd.backlight(lcd.GREEN) sleep(1) + print "teal" lcd.backlight(lcd.TEAL) sleep(1) + print "blue" lcd.backlight(lcd.BLUE) sleep(1) + print "violet" lcd.backlight(lcd.VIOLET) sleep(1) - lcd.backlight(lcd.ON) - sleep(1) + print "off" lcd.backlight(lcd.OFF) sleep(1) + print "on" + lcd.backlight(lcd.ON) + sleep(1) + + print " Try buttons on plate" + + while 1: + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) + From c5a4f34a3a9b4ca3be81d4c1e64196e5fe51af99 Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 16:01:55 +1300 Subject: [PATCH 09/13] Original Adafruit_MCP230xx.py --- Adafruit_MCP230xx/Adafruit_MCP230xx.py | 406 ++++++++++++------------- 1 file changed, 202 insertions(+), 204 deletions(-) diff --git a/Adafruit_MCP230xx/Adafruit_MCP230xx.py b/Adafruit_MCP230xx/Adafruit_MCP230xx.py index 4fc18695..83c0fed4 100755 --- a/Adafruit_MCP230xx/Adafruit_MCP230xx.py +++ b/Adafruit_MCP230xx/Adafruit_MCP230xx.py @@ -1,204 +1,202 @@ -#!/usr/bin/python - -# Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy of -# this software and associated documentation files (the "Software"), to deal MCP230XX_GPIO(1, 0xin -# the Software without restriction, including without limitation the rights to -# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is furnished to do -# so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from Adafruit_I2C import Adafruit_I2C -import smbus -import time - -MCP23017_IODIRA = 0x00 -MCP23017_IODIRB = 0x01 -MCP23017_GPIOA = 0x12 -MCP23017_GPIOB = 0x13 -MCP23017_GPPUA = 0x0C -MCP23017_GPPUB = 0x0D -MCP23017_OLATA = 0x14 -MCP23017_OLATB = 0x15 -MCP23008_GPIOA = 0x09 -MCP23008_GPPUA = 0x06 -MCP23008_OLATA = 0x0A - -class Adafruit_MCP230XX(object): - OUTPUT = 0 - INPUT = 1 - - def __init__(self, address, num_gpios, busnum = 0): - assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16" - self.i2c = Adafruit_I2C(address=address, bus=smbus.SMBus(busnum)) - self.address = address - self.num_gpios = num_gpios - - # set defaults - if num_gpios <= 8: - self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A - self.direction = self.i2c.readU8(MCP23017_IODIRA) - self.i2c.write8(MCP23008_GPPUA, 0x00) - elif num_gpios > 8 and num_gpios <= 16: - self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A - self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B - self.direction = self.i2c.readU8(MCP23017_IODIRA) - self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 - self.i2c.write8(MCP23017_GPPUA, 0x00) - self.i2c.write8(MCP23017_GPPUB, 0x00) - - - def _changebit(self, bitmap, bit, value): - assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value - if value == 0: - return bitmap & ~(1 << bit) - elif value == 1: - return bitmap | (1 << bit) - - def _readandchangepin(self, port, pin, value, currvalue = None): - assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin - if not currvalue: - currvalue = self.i2c.readU8(port) - newvalue = self._changebit(currvalue, pin, value) - self.i2c.write8(port, newvalue) - return newvalue - - - def pullup(self, pin, value): - if self.num_gpios <= 8: - return self._readandchangepin(MCP23008_GPPUA, pin, value) - if self.num_gpios <= 16: - if (pin < 8): - return self._readandchangepin(MCP23017_GPPUA, pin, value) - else: - return self._readandchangepin(MCP23017_GPPUB, pin-8, value) - - # Set pin to either input or output mode - def config(self, pin, mode): - if self.num_gpios <= 8: - self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) - if self.num_gpios <= 16: - if (pin < 8): - # replace low bits - self.direction = (self.direction >> 8)<<8 | self._readandchangepin(MCP23017_IODIRA, pin, mode) - else: - # replace hi bits - self.direction = (self.direction & 0xff) | self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8 - #print "config ", pin, mode, self.direction, bin(self.direction)[2:].zfill(16) - return self.direction - - def output(self, pin, value): - # assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin - if self.num_gpios <= 8: - self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA)) - if self.num_gpios <= 16: - if (pin < 8): - self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) - else: - self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) - return self.outputvalue - -# what is this code doing here inaccessible place! - - def input(self, pin, check=True): - assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - if check: - assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin - if self.num_gpios <= 8: - value = self.i2c.readU8(MCP23008_GPIOA) - elif self.num_gpios > 8 and self.num_gpios <= 16: - value = self.i2c.readU16(MCP23017_GPIOA) - temp = value >> 8 - value <<= 8 - value |= temp - return (value & (1 << pin))>>pin # to make 0 or 1 - - - -# these were indented so within scope of input but have now made them all part of the class -# have modified so can read any address but default to those given in original code -# also use available routines in imported Adafruit_I2C class - def readU8(self, add=MCP23008_OLATA): - result = self.i2c.readU8(add) - return(result) - - def readS8(self, add=MCP23008_OLATA): - result = self.i2c.readS8(add) - return result - - def readU16(self, add=MCP23017_OLATA): - assert self.num_gpios >= 16, "16bits required" - result = self.i2c.readU16(add) - return result - - def readS16(self, add=MCP23017_OLATA): - assert self.num_gpios >= 16, "16bits required" - result = self.i2c.readS16(add) - return result - - def write8(self, value, add=MCP23008_OLATA): - self.i2c.write8(add, value) - - def write16(self, value, add=MCP23017_OLATA): - assert self.num_gpios >= 16, "16bits required" - self.i2c.write16(add, value) - - -# RPi.GPIO compatible interface for MCP23017 and MCP23008 - -class MCP230XX_GPIO(object): - OUT = 0 - IN = 1 - BCM = 0 - BOARD = 0 - def __init__(self, busnum, address, num_gpios): - self.chip = Adafruit_MCP230XX(busnum, address, num_gpios) - def setmode(self, mode): - # do nothing - pass - def setup(self, pin, mode): - self.chip.config(pin, mode) - def input(self, pin): - return self.chip.input(pin) - def output(self, pin, value): - self.chip.output(pin, value) - def pullup(self, pin, value): - self.chip.pullup(pin, value) - - -if __name__ == '__main__': - mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) - - # *************************************************** - # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! - # If you have a new Pi you may also need to add: - # busnum = 1 - # *************************************************** - - # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) - mcp.config(0, mcp.OUTPUT) - mcp.config(1, mcp.OUTPUT) - mcp.config(2, mcp.OUTPUT) - - # Set pin 3 to input with the pullup resistor enabled - mcp.pullup(3, 1) - # Read pin 3 and display the results - print "%d: %x" % (3, mcp.input(3) >> 3) - - # Python speed test on output 0 toggling at max speed - while (True): - mcp.output(0, 1) # Pin 0 High - mcp.output(0, 0) # Pin 0 Low +#!/usr/bin/python + +# Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal MCP230XX_GPIO(1, 0xin +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from Adafruit_I2C import Adafruit_I2C +import smbus +import time + +MCP23017_IODIRA = 0x00 +MCP23017_IODIRB = 0x01 +MCP23017_GPIOA = 0x12 +MCP23017_GPIOB = 0x13 +MCP23017_GPPUA = 0x0C +MCP23017_GPPUB = 0x0D +MCP23017_OLATA = 0x14 +MCP23017_OLATB = 0x15 +MCP23008_GPIOA = 0x09 +MCP23008_GPPUA = 0x06 +MCP23008_OLATA = 0x0A + +class Adafruit_MCP230XX(object): + OUTPUT = 0 + INPUT = 1 + + def __init__(self, address, num_gpios, busnum = 0): + assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16" + self.i2c = Adafruit_I2C(address=address, bus=smbus.SMBus(busnum)) + self.address = address + self.num_gpios = num_gpios + + # set defaults + if num_gpios <= 8: + self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A + self.direction = self.i2c.readU8(MCP23017_IODIRA) + self.i2c.write8(MCP23008_GPPUA, 0x00) + elif num_gpios > 8 and num_gpios <= 16: + self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A + self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B + self.direction = self.i2c.readU8(MCP23017_IODIRA) + self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 + self.i2c.write8(MCP23017_GPPUA, 0x00) + self.i2c.write8(MCP23017_GPPUB, 0x00) + + def _changebit(self, bitmap, bit, value): + assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value + if value == 0: + return bitmap & ~(1 << bit) + elif value == 1: + return bitmap | (1 << bit) + + def _readandchangepin(self, port, pin, value, currvalue = None): + assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) + #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin + if not currvalue: + currvalue = self.i2c.readU8(port) + newvalue = self._changebit(currvalue, pin, value) + self.i2c.write8(port, newvalue) + return newvalue + + + def pullup(self, pin, value): + if self.num_gpios <= 8: + return self._readandchangepin(MCP23008_GPPUA, pin, value) + if self.num_gpios <= 16: + if (pin < 8): + return self._readandchangepin(MCP23017_GPPUA, pin, value) + else: + return self._readandchangepin(MCP23017_GPPUB, pin-8, value) + + # Set pin to either input or output mode + def config(self, pin, mode): + if self.num_gpios <= 8: + self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) + if self.num_gpios <= 16: + if (pin < 8): + self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) + else: + self.direction = self._readandchangepin(MCP23017_IODIRB, pin-8, mode) + + return self.direction + + def output(self, pin, value): + # assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin + if self.num_gpios <= 8: + self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA)) + if self.num_gpios <= 16: + if (pin < 8): + self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) + else: + self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) + + return self.outputvalue + + + self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue) + return self.outputvalue + + def input(self, pin): + assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) + assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin + if self.num_gpios <= 8: + value = self.i2c.readU8(MCP23008_GPIOA) + elif self.num_gpios > 8 and self.num_gpios <= 16: + value = self.i2c.readU16(MCP23017_GPIOA) + temp = value >> 8 + value <<= 8 + value |= temp + return value & (1 << pin) + + def readU8(self): + result = self.i2c.readU8(MCP23008_OLATA) + return(result) + + def readS8(self): + result = self.i2c.readU8(MCP23008_OLATA) + if (result > 127): result -= 256 + return result + + def readU16(self): + assert self.num_gpios >= 16, "16bits required" + lo = self.i2c.readU8(MCP23017_OLATA) + hi = self.i2c.readU8(MCP23017_OLATB) + return((hi << 8) | lo) + + def readS16(self): + assert self.num_gpios >= 16, "16bits required" + lo = self.i2c.readU8(MCP23017_OLATA) + hi = self.i2c.readU8(MCP23017_OLATB) + if (hi > 127): hi -= 256 + return((hi << 8) | lo) + + def write8(self, value): + self.i2c.write8(MCP23008_OLATA, value) + + def write16(self, value): + assert self.num_gpios >= 16, "16bits required" + self.i2c.write8(MCP23017_OLATA, value & 0xFF) + self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF) + +# RPi.GPIO compatible interface for MCP23017 and MCP23008 + +class MCP230XX_GPIO(object): + OUT = 0 + IN = 1 + BCM = 0 + BOARD = 0 + def __init__(self, busnum, address, num_gpios): + self.chip = Adafruit_MCP230XX(busnum, address, num_gpios) + def setmode(self, mode): + # do nothing + pass + def setup(self, pin, mode): + self.chip.config(pin, mode) + def input(self, pin): + return self.chip.input(pin) + def output(self, pin, value): + self.chip.output(pin, value) + def pullup(self, pin, value): + self.chip.pullup(pin, value) + + +if __name__ == '__main__': + mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) + + # *************************************************** + # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! + # If you have a new Pi you may also need to add: + # busnum = 1 + # *************************************************** + + # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) + mcp.config(0, mcp.OUTPUT) + mcp.config(1, mcp.OUTPUT) + mcp.config(2, mcp.OUTPUT) + + # Set pin 3 to input with the pullup resistor enabled + mcp.pullup(3, 1) + # Read pin 3 and display the results + print "%d: %x" % (3, mcp.input(3) >> 3) + + # Python speed test on output 0 toggling at max speed + while (True): + mcp.output(0, 1) # Pin 0 High + mcp.output(0, 0) # Pin 0 Low From 897860368ef35d2de4abd12d9bbb1e56b7dcb17d Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 16:03:41 +1300 Subject: [PATCH 10/13] Tabs Removed from Adafruit_MCP230xx.py --- Adafruit_MCP230xx/Adafruit_MCP230xx.py | 68 +++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/Adafruit_MCP230xx/Adafruit_MCP230xx.py b/Adafruit_MCP230xx/Adafruit_MCP230xx.py index 83c0fed4..23691430 100755 --- a/Adafruit_MCP230xx/Adafruit_MCP230xx.py +++ b/Adafruit_MCP230xx/Adafruit_MCP230xx.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python # Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried) # @@ -125,35 +125,35 @@ def input(self, pin): value |= temp return value & (1 << pin) - def readU8(self): - result = self.i2c.readU8(MCP23008_OLATA) - return(result) + def readU8(self): + result = self.i2c.readU8(MCP23008_OLATA) + return(result) - def readS8(self): - result = self.i2c.readU8(MCP23008_OLATA) - if (result > 127): result -= 256 - return result + def readS8(self): + result = self.i2c.readU8(MCP23008_OLATA) + if (result > 127): result -= 256 + return result - def readU16(self): - assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - return((hi << 8) | lo) + def readU16(self): + assert self.num_gpios >= 16, "16bits required" + lo = self.i2c.readU8(MCP23017_OLATA) + hi = self.i2c.readU8(MCP23017_OLATB) + return((hi << 8) | lo) - def readS16(self): - assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - if (hi > 127): hi -= 256 - return((hi << 8) | lo) + def readS16(self): + assert self.num_gpios >= 16, "16bits required" + lo = self.i2c.readU8(MCP23017_OLATA) + hi = self.i2c.readU8(MCP23017_OLATB) + if (hi > 127): hi -= 256 + return((hi << 8) | lo) - def write8(self, value): - self.i2c.write8(MCP23008_OLATA, value) + def write8(self, value): + self.i2c.write8(MCP23008_OLATA, value) - def write16(self, value): - assert self.num_gpios >= 16, "16bits required" - self.i2c.write8(MCP23017_OLATA, value & 0xFF) - self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF) + def write16(self, value): + assert self.num_gpios >= 16, "16bits required" + self.i2c.write8(MCP23017_OLATA, value & 0xFF) + self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF) # RPi.GPIO compatible interface for MCP23017 and MCP23008 @@ -181,21 +181,21 @@ def pullup(self, pin, value): mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) # *************************************************** - # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! - # If you have a new Pi you may also need to add: - # busnum = 1 - # *************************************************** - - # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) + # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! + # If you have a new Pi you may also need to add: + # busnum = 1 + # *************************************************** + + # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) mcp.config(0, mcp.OUTPUT) mcp.config(1, mcp.OUTPUT) mcp.config(2, mcp.OUTPUT) - - # Set pin 3 to input with the pullup resistor enabled + + # Set pin 3 to input with the pullup resistor enabled mcp.pullup(3, 1) # Read pin 3 and display the results print "%d: %x" % (3, mcp.input(3) >> 3) - + # Python speed test on output 0 toggling at max speed while (True): mcp.output(0, 1) # Pin 0 High From e0ab25d3a55fefdf5490c36d19003947ba61e1aa Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Thu, 14 Feb 2013 16:06:35 +1300 Subject: [PATCH 11/13] Correction and additions on Adafruit_MCP230xx.py keeping to pep8 --- Adafruit_MCP230xx/Adafruit_MCP230xx.py | 102 +++++++++++++------------ 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/Adafruit_MCP230xx/Adafruit_MCP230xx.py b/Adafruit_MCP230xx/Adafruit_MCP230xx.py index 23691430..c596ea19 100755 --- a/Adafruit_MCP230xx/Adafruit_MCP230xx.py +++ b/Adafruit_MCP230xx/Adafruit_MCP230xx.py @@ -58,6 +58,7 @@ def __init__(self, address, num_gpios, busnum = 0): self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 self.i2c.write8(MCP23017_GPPUA, 0x00) self.i2c.write8(MCP23017_GPPUB, 0x00) + def _changebit(self, bitmap, bit, value): assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value @@ -70,7 +71,7 @@ def _readandchangepin(self, port, pin, value, currvalue = None): assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin if not currvalue: - currvalue = self.i2c.readU8(port) + currvalue = self.i2c.readU8(port) newvalue = self._changebit(currvalue, pin, value) self.i2c.write8(port, newvalue) return newvalue @@ -91,10 +92,12 @@ def config(self, pin, mode): self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) if self.num_gpios <= 16: if (pin < 8): - self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) + # replace low bits + self.direction = (self.direction >> 8)<<8 | self._readandchangepin(MCP23017_IODIRA, pin, mode) else: - self.direction = self._readandchangepin(MCP23017_IODIRB, pin-8, mode) - + # replace hi bits + self.direction = (self.direction & 0xff) | self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8 + #print "config ", pin, mode, self.direction, bin(self.direction)[2:].zfill(16) return self.direction def output(self, pin, value): @@ -106,16 +109,14 @@ def output(self, pin, value): self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) else: self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) - return self.outputvalue - - self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue) - return self.outputvalue +# inaccessible code removed from here - def input(self, pin): + def input(self, pin, check=True): assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin + if check: + assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin if self.num_gpios <= 8: value = self.i2c.readU8(MCP23008_GPIOA) elif self.num_gpios > 8 and self.num_gpios <= 16: @@ -123,37 +124,38 @@ def input(self, pin): temp = value >> 8 value <<= 8 value |= temp - return value & (1 << pin) - - def readU8(self): - result = self.i2c.readU8(MCP23008_OLATA) - return(result) - - def readS8(self): - result = self.i2c.readU8(MCP23008_OLATA) - if (result > 127): result -= 256 - return result - - def readU16(self): - assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - return((hi << 8) | lo) - - def readS16(self): - assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - if (hi > 127): hi -= 256 - return((hi << 8) | lo) - - def write8(self, value): - self.i2c.write8(MCP23008_OLATA, value) - - def write16(self, value): - assert self.num_gpios >= 16, "16bits required" - self.i2c.write8(MCP23017_OLATA, value & 0xFF) - self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF) + return (value & (1 << pin))>>pin # to make 0 or 1 + + + +# these were indented so within scope of input but have now made them all part of the class +# have modified so can read any address but default to those given in original code +# also use available routines in imported Adafruit_I2C class + def readU8(self, add=MCP23008_OLATA): + result = self.i2c.readU8(add) + return(result) + + def readS8(self, add=MCP23008_OLATA): + result = self.i2c.readS8(add) + return result + + def readU16(self, add=MCP23017_OLATA): + assert self.num_gpios >= 16, "16bits required" + result = self.i2c.readU16(add) + return result + + def readS16(self, add=MCP23017_OLATA): + assert self.num_gpios >= 16, "16bits required" + result = self.i2c.readS16(add) + return result + + def write8(self, value, add=MCP23008_OLATA): + self.i2c.write8(add, value) + + def write16(self, value, add=MCP23017_OLATA): + assert self.num_gpios >= 16, "16bits required" + self.i2c.write16(add, value) + # RPi.GPIO compatible interface for MCP23017 and MCP23008 @@ -181,21 +183,21 @@ def pullup(self, pin, value): mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) # *************************************************** - # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! - # If you have a new Pi you may also need to add: - # busnum = 1 - # *************************************************** - - # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) + # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! + # If you have a new Pi you may also need to add: + # busnum = 1 + # *************************************************** + + # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) mcp.config(0, mcp.OUTPUT) mcp.config(1, mcp.OUTPUT) mcp.config(2, mcp.OUTPUT) - - # Set pin 3 to input with the pullup resistor enabled + + # Set pin 3 to input with the pullup resistor enabled mcp.pullup(3, 1) # Read pin 3 and display the results print "%d: %x" % (3, mcp.input(3) >> 3) - + # Python speed test on output 0 toggling at max speed while (True): mcp.output(0, 1) # Pin 0 High From 1d408f904cb214c449c60149f49765398fd947c2 Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Mon, 18 Feb 2013 06:47:33 +1300 Subject: [PATCH 12/13] Test routine and extra routines to contol LCD --- Adafruit_CharLCDPlate/NewLCDTest.py | 566 ++++++++++++++++++++++++++++ 1 file changed, 566 insertions(+) create mode 100644 Adafruit_CharLCDPlate/NewLCDTest.py diff --git a/Adafruit_CharLCDPlate/NewLCDTest.py b/Adafruit_CharLCDPlate/NewLCDTest.py new file mode 100644 index 00000000..7210de6b --- /dev/null +++ b/Adafruit_CharLCDPlate/NewLCDTest.py @@ -0,0 +1,566 @@ +#!/usr/bin/python +# mod by bb 29 Jan 2013 + +from time import sleep +from random import randint +from Adafruit_I2C import Adafruit_I2C +from Adafruit_MCP230xx import Adafruit_MCP230XX +from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate +#from Adafruit_MCP230xx import MCP23017_GPIOB, MCP23017_IODIRB +MCP23017_IODIRA = 0x00 +MCP23017_IODIRB = 0x01 +MCP23017_GPIOA = 0x12 +MCP23017_GPIOB = 0x13 +MCP23017_GPPUA = 0x0C +MCP23017_GPPUB = 0x0D +MCP23017_OLATA = 0x14 +MCP23017_OLATB = 0x15 +import smbus + + +def binfill(num,len=8): + return bin(num)[2:].zfill(len) + +ReverseNib = [0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15] + +def cur_right(num=1): # note num = 40 in 2 lines mode moves up/down to other line + for cnt in range(num): + lcd.mcp.write8(0x30, MCP23017_GPIOB) #RS=0, R/W=0, E=1, high nibble of lcd command reversed, 0. Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(0x04, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x24, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x04, MCP23017_GPIOB) #same as line two to send E low to finish + +def cur_left(num=1): + for cnt in range(num): + lcd.mcp.write8(0x30, MCP23017_GPIOB) #RS=0, R/W=0, E=1, high nibble of lcd command reversed, 0. Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(0x00, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x20, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x00, MCP23017_GPIOB) #same as line two to send E low to finish + +def display_right(num=1): # note num = 40 in 2 lines mode moves up/down to other line + for cnt in range(num): + lcd.mcp.write8(0x30, MCP23017_GPIOB) #RS=0, R/W=0, E=1, high nibble of lcd command reversed, 0. Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(0x06, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x26, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x06, MCP23017_GPIOB) #same as line two to send E low to finish + +def cur_pos(num=0): +# i.e. Set DDRAM address - the cursor will move to this address +# Note +# in two line mode DDRAM 0 to 39 is first line +# DDRAM 64 to 39+64 is second line +# using num from 40 till 63 will set DDRAM to 64 +# using num from above 39+64 will set DDRAM to 0 +# in one line mode DDRAM goes from 0 to 79 and setting above will go to 0 + # make num become the instruction code for Set DDRAM address + num &= 0x7f # truncate num to 7 bits + num |= 0x80 # make highest bit 1 + # make first byte to send which contains the reverse high nibble of num + hinum = (num & 0xf0) >> 4 + byte1 = 0x20 | (ReverseNib[hinum] << 1) # RS=0, R/W = 0, E = 1, high nibble of lcd command reversed, 0. + lonum = (num & 0xf) + byte2 = (ReverseNib[lonum] << 1) # RS=0, R/W = 0, E = 0, low nibble of lcd command reversed, 0. + #print "num = ", bin8(num), "hinum = ", bin8(hinum), "lonum = ", bin8(lonum) + #print "byte1 = ", bin8(byte1), "byte2 = ", bin8(byte2) + lcd.mcp.write8(byte1, MCP23017_GPIOB) #Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(0x20 | byte2, MCP23017_GPIOB) # going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # send E low to finish + +def setCGRAMadd(num=0): +# i.e. Set CGRAM address - Write/Read Data from RAM after this will use Character Graphic RAM + # make num become the instruction code for Set CGRAM address + num &= 0x3f # truncate num to 6 bits + num |= 0x40 # make 2nd to highest bit 1 + # make first byte to send which contains the reverse high nibble of num + hinum = (num & 0xf0) >> 4 + byte1 = 0x20 | (ReverseNib[hinum] << 1) # RS=0, R/W = 0, E = 1, high nibble of lcd command reversed, 0. + lonum = (num & 0xf) + byte2 = (ReverseNib[lonum] << 1) # RS=0, R/W = 0, E = 0, low nibble of lcd command reversed, 0. + print "num = ", binfill(num), "hinum = ", binfill(hinum), "lonum = ", binfill(lonum) + print "byte1 = ", binfill(byte1), "byte2 = ", binfill(byte2) + lcd.mcp.write8(byte1, MCP23017_GPIOB) #Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(0x20 | byte2, MCP23017_GPIOB) # going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # send E low to finish + +def general_cmd(cmd,RS=0,RW=0,debug=0): +# execute a general command for the LCD TC1602A-01T +# cmd are the 8 bits of instuction code from table pg. 11 +# if cmd is a read command (RW = 1) the value read is returned + # make first byte to send which contains the reverse high nibble of cmd + RSbit=0x80 if RS else 0x00 + RWbit=0x40 if RW else 0x00 + Ebit = 0x20 + hicmd = (cmd & 0xf0) >> 4 + byte1 = RSbit | RWbit | Ebit | (ReverseNib[hicmd] << 1) # RS,RW, E = 1, high nibble of lcd command reversed, 0. + locmd = (cmd & 0xf) + byte2 = RSbit | RWbit | (ReverseNib[locmd] << 1) # RS,RW, E = 0, low nibble of lcd command reversed, 0. + if debug: + print "cmd = ", binfill(cmd), "hinum = ", binfill(hicmd), "locmd = ", binfill(locmd) + print "byte1 = ", binfill(byte1), "byte2 = ", binfill(byte2) + lcd.mcp.write8(byte1, MCP23017_GPIOB) #Going high sends this to LCD as hi bits of instruction code + if RW: + currentiodir = lcd.mcp.readU8(MCP23017_IODIRB) # save entering state of input/output for pins from 8-15 + lcd.mcp.write8(0b00011110 | currentiodir, MCP23017_IODIRB) # configure input for pins 9-12 which are 4-7 in GPB + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed high nibble from LCD + hinum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse + lcd.mcp.write8(byte2, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(Ebit | byte2, MCP23017_GPIOB) # going high sends this nibble to LCD as low bits of instruction code + if RW: + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed low nibble from LCD + lonum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse + if RW: + lcd.mcp.write8(currentiodir, MCP23017_IODIRB) # restore pins input/output to state upon entering this routine + lcd.mcp.write8(0x00, MCP23017_GPIOB) # send all low to finish and be compatible with other CarLCDPlate routines + if RW: + return (hinum << 4) | lonum + +def readfast(ram=False): +# read BF and AC or RAM Data + if ram: + cmdhi = 0xe0 + cmdlo = 0xc0 + else: + cmdhi = 0x60 + cmdlo = 0x40 + lcd.mcp.write8(0b00011111, MCP23017_IODIRB) # configure so input on pins 9-12 which are 4-7 in GPB + lcd.mcp.write8(cmdhi, MCP23017_GPIOB) #Going high prepares to record first nibble info + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed high nibble from LCD + hinum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse# extract the 4 bits and reverse + lcd.mcp.write8(cmdlo, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(cmdhi, MCP23017_GPIOB) # going high prepares to recond second nibble info + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed low nibble from LCD + lonum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse + lcd.mcp.write8(0x0, MCP23017_GPIOB) # send E low to finish and set RS, RW and all to zero + lcd.mcp.write8(0b00000001, MCP23017_IODIRB) # configure so all approrpriate pins are output again + return (hinum << 4) | lonum + +def DumpMCP23017Regs(regs_to_use=[0x0,18,20]): +# Dump MCP23017 registers see MCP2301721952b.pdf specifications but show first B then A +# Default is to dump only IODIR, GPIO and OLATA +# will show B bank followed by A bank i.e. IODIRB, IODIRA so +# the output corresponds to 'pins' 15,14,...,0 +# to dump all use regs_to_use = range(0x0,0x15,0x2) + RegName = ["IODIR","IPOL","GPINTEN","DEFVAL","INTCON","IOCON","GPPU","INTF","INTCAP","GPIO","OLATA"] + print "B bank then A bank so Pins 15, 14, ..., 0" + print binfill(lcd.mcp.direction,16), " lcd.mcp.direction" #ideally should be same as IODIR + for reg in regs_to_use: + str = binfill(lcd.mcp.readU16(reg),16) + # interchange bytes B reg then A reg so 'pins' are from left to right are 15,14,13,...,0 + print str[8:]+str[:8]," ", RegName[reg/2] + +def home_fast(): +# fast return home + lcd.mcp.write8(0x20, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as hi bits of instruction code + lcd.mcp.write8(0x08, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x28, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x08, MCP23017_GPIOB) #same as line three to send E low to finish + +def clear_fast(): +# fast clear + lcd.mcp.write8(0x20, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as hi bits of instruction code + lcd.mcp.write8(0x10, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of clear display reversed, 0 + lcd.mcp.write8(0x30, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x10, MCP23017_GPIOB) #same as line three to send E low to finish + +def dim_light(on=.5,time=1,nforsec=50): +# dimming routine doesnt work very well +# flashes display on and off over interval time +# on is fraction of time on during the interval + assert 0 <= on and on <= 1, "bad value for on" + ontime = float(on)/nforsec + offtime = (1.0-on)/nforsec + maxct = int(nforsec*time) + print ontime, offtime, maxct + for ct in range(maxct): + lcd.write4bits(0x8) # display off + sleep(offtime) + lcd.write4bits(0xc) # display on + sleep(ontime) + +def dispall(delay=.1): + for i in range(256): + general_cmd(i,1) + sleep(delay) + +def cycle(seq, n): +# cyclic premutation of seq shifting left n + n = n % len(seq) + return seq[n:] + seq[:n] + +def cyclerange(DDRAMrange=range(40), amount=1): +# cyclically shift characters in a range of DDRAM addresses by amount +# DDRAMrange default is line 1 in 2 line mode i.e. 0...39 + # get DDRAM address to be restored + add = general_cmd(0,0,1) + lenrange = len(DDRAMrange) + startadd = DDRAMrange[0] + # get data in DDRAMrange + # set DDRAM address to startadd + general_cmd(0b10000000 + startadd) + win = [0]*lenrange + for i in range(lenrange): #read DDRAM beginning at startadd + win[i] = general_cmd(0,1,1) + win = cycle(win,amount) + general_cmd(0b10000000 + startadd) + for i in range(lenrange): #write shifted values back in DDRAM starting at startadd + general_cmd(win[i],1,0) + # restore DDRAM address + general_cmd(add | 0x80) + +def scrollrange(DDRAMrange=range(40), num=1, delay=.01): + num = num*len(DDRAMrange) + for i in range(num): + cyclerange(DDRAMrange,1) + #sleep(delay) + +def shiftwithinrange(textstart,textlen,DDRAMrange=range(40)): +# cyclically shift characters in a range of DDRAM addresses by one position +# this code maybe faster than cyclerange code +# DDRAMrange default is line 1 in 2 line mode i.e. 0...39 + # if have string of text can shift it to the right one place within a range (say top line) + # assuming this string is surrounded by blanks in the rest of the range + # assuming LCD set in increment mode (rather than decrement mode) + # get DDRAM address to be restored + add = general_cmd(0,0,1) + startrange = DDRAMrange[0] + endrange = DDRAMrange[-1] + lenrange = len(DDRAMrange) + #print startrange, endrange, lenrange + for i in range(textstart+textlen-1,textstart-1,-1): # go thru in reverse + add = i + if i > endrange: + add = i - lenrange + startrange + #print "moving from ", add + # set DDRAM address to + general_cmd(0b10000000 + add) + byte = general_cmd(0,1,1) # this will get byte in DDRAM and increment address counter by 1 + if i+1 > endrange: + add = i + 1 - lenrange + startrange + general_cmd(0b10000000 + add ) + else: + add = add + 1 + general_cmd(byte,1,0) # this will put byte in DDRAM at the new address thus shifting it + #print "moving to ", add, "this char ", chr(byte) + general_cmd(0b10000000 + textstart) + general_cmd(0b00100000,1,0) # this will put blank + # restore DDRAM address + general_cmd(add | 0x80) + + +class Histogram: + def __init__(self): + # make bars in CGRAM of height 8 to 1 in for custom char 0 to 7 (and 8 to 15) + histdata = [31,31,31,31,31,31,31,31, 0,31,31,31,31,31,31,31, 0,0,31,31,31,31,31,31, 0,0,0,31,31,31,31,31, 0,0,0,0,31,31,31,31, 0,0,0,0,0,31,31,31, 0,0,0,0,0,0,31,31, 0,0,0,0,0,0,0,31 ] + general_cmd(0b01000000) # set CGRAM address 0 + for i in range(64): + general_cmd(histdata[i],1) # write data to ram + + def histogram(self,bar,DDRAMstart=64,UseTwoLines=True): + # draws bars of height bar[0],bar[1],... starting at + # DDRAMstart. Heights must >=0 and <= max 16 for TwoLines and 8 for OneLine). + # In the case UseTwoLines==True, the bars use two rows, so it is advised + # to make DDRAMstart on the 2nd line. + # note no checking done on values. If they are bigger than 16 other characters + # will be displayed instead of the custom bars. + # get DDRAM address to be restored + add = general_cmd(0,0,1) + # draw bottom row + # set DDRAM address to start + general_cmd(0b10000000 + DDRAMstart) + for y in bar: + char = max(16-y,8) + general_cmd(char,1,0) # put char which has appropriate height + if UseTwoLines: + # draw top row + # set DDRAM address to start + general_cmd(0b10000000 + DDRAMstart - 64) + for y in bar: + char = min(16-y,8) + 8 + general_cmd(char,1,0) # put char which has appropriate height + # restore DDRAM address + general_cmd(add | 0x80) + + +class DotGrid: + def __init__(self): + # make dot patterns in CGRAM + self.dotdata = [0,0,0,0,14,31,14,0, 14,31,14,0,0,0,0,0, 14,31,14,0,14,31,14,0, 0,0,0,0,0,14,31,14, 0,14,31,14,0,0,0,0, 0,14,31,14,0,14,31,14] + self.dedata = [[[64,2,1,0],[64,2,0,1],[0,5,4,3],[0,5,3,4]], [[64,1,2,32],[64,0,2,32],[0,4,5,32],[0,3,5,32]]] + self.isdotdata = [[64,0,2],[64,1,2],[0,3,5],[0,4,5]] + self.initialize_CGRAM() + + def initialize_CGRAM(self): + general_cmd(0b01000000) # set CGRAM address 0 + for i in range(len(self.dotdata)): + general_cmd(self.dotdata[i],1) # write data to ram + + def draw_erase_or_test(self,x,y,deort): # deort == 0 for draw, ==1 for erase, else test only + # draws, erases or tests a dot at (x,y) + # 0<=x<=39 but only x<=15 visable in default display but can shift to see + # 0<=y<=3 + # get DDRAM address to be restored + add = general_cmd(0,0,1) + addforx = x + self.dedata[0][y][0] + general_cmd(0b10000000 + addforx) # set DDRAM address + byte = general_cmd(0,1,1) # this will get byte in DDRAM + isdot = byte==self.isdotdata[y][1] or byte==self.isdotdata[y][2] + # if asked to draw a dot thats not there or erase a dot that is there do it! + if deort==0 and not isdot or deort==1 and isdot: + char = self.dedata[deort][y][1] if byte==self.dedata[deort][y][2] else self.dedata[deort][y][3] + general_cmd(0b10000000 + addforx) # set DDRAM address + general_cmd(char,1,0) # put char which is one or two dots + # restore DDRAM address + general_cmd(add | 0x80) + # return True if there was a dot at x,y when entered function + return isdot + + def draw(self,x,y): + return self.draw_erase_or_test(x,y,0) + + def erase(self,x,y): + return self.draw_erase_or_test(x,y,1) + + def isdot(self,x,y): + return self.draw_erase_or_test(x,y,2) + + +# OLD +# def draw(self,x,y): +# # draws a dot at (x,y) +# # 0<=x<=39 but only x<=15 in default display can shift to see +# # 0<=y<=3 +# # get DDRAM address to be restored +# add = general_cmd(0,0,1) +# if y==0: +# addforx = x + 64 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# char = 2 if byte==1 else 0 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# elif y==1: +# addforx = 64 + x +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# char = 2 if byte==0 else 1 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# elif y==2: +# addforx = x +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# char = 5 if byte==4 else 3 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# elif y==3: +# addforx = x +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# else: +# print "y not 0,1,2 or 3" +# # restore DDRAM address +# general_cmd(add | 0x80) +# + + +back = 0 +def ToggleBacklight(back): + back ^= 1 + lcd.backlight(back) + sleep(.2) + return back + + + +# initialize the LCD plate +# use busnum = 0 for raspi version 1 (256MB) and busnum = 1 for version 2 +lcd = Adafruit_CharLCDPlate(busnum = 1) + +Hist = Histogram() +bar = [0]*16 + +DotG = DotGrid() + +general_cmd(0b1) # clear +lcd.waitBFlow() # must wait for clear to complete + +# Testing using keyboard +while 1: + cmd = raw_input() + if cmd == 'help': + print "10, 9, bf, cgram, config, cyclerange, dim, dispall, dot, dotinit, dump, edot, histogram, histograminit, longchar, mess, oneline, ramdata, sdr, scrollrange, shiftwithinrange, test, twoline, quit" + + if cmd == 'test': + print "Routine for testing" + + if cmd == '10': + str = raw_input("10 bits of instruction code:") + RS = str[0]=="1" # 1 is true + RW = str[1]=="1" # 1 is true + str = str[2:].zfill(8) + num = int('0b'+str,2) + numrpt = raw_input("repeat #:") + numrpt = 1 if numrpt=="" else int(numrpt) + for count in range(0,numrpt): + print(general_cmd(num,RS,RW)) + + if cmd == 'dim': + time = 2 + on = input("Fraction on? ") + nforsec = input("nforsec? ") + dim_light(on,time,nforsec) + + if cmd == 'bf': + #print "BF", lcd.readBF() + print "fast BF + AD = ", binfill(readfast()) # read Busy Flag and Adress + #print "BF + AD = ", lcd.read4bits() # read Busy Flag and Adress + + if cmd == 'sdr': + numrpt = raw_input("Shift Display Right by ") + numrpt = 1 if numrpt=="" else int(numrpt) + display_right(numrpt) + + if cmd == 'cyclerange': + line = input("Window Range? ") + line = range(40) if line=="" else line + amt = raw_input("How much? ") + amt = 1 if amt=="" else int(amt) + cyclerange(line,amt) + + if cmd == 'dotinit': + DotG.initialize_CGRAM() + + if cmd == 'dot': + x = input("x? ") + y = input("y? ") + #print(DotG.draw_erase_or_test(x,y,0)) + print(DotG.draw(x,y)) + + if cmd == 'edot': + x = input("x? ") + y = input("y? ") + #print(DotG.draw_erase_or_test(x,y,1)) + print(DotG.erase(x,y)) + + if cmd == 'histograminit': + Hist.__init__() + + if cmd == 'histogram': + #bar = input("Bar list? ") + barcurrent = [0]*16 + barnew = barcurrent[:] + barshow = barcurrent[:] + for cnt in range(30): + for ind in range(len(barcurrent)): + barnew[ind] = randint(0,16) + tmax = 4 + for time in range(tmax+1): + for ind in range(len(barcurrent)): + barshow[ind] = int(((tmax-time)*barcurrent[ind] + time*barnew[ind])/float(tmax)) + Hist.histogram(barshow) + barcurrent = barnew[:] + + if cmd == 'scrollrange': + line = input("Window Range? ") + line = range(40) if line=="" else line + scrollrange(line) + + if cmd == 'shiftwithinrange': + #textstart = input('Start? ') + #textlen = input('Length? ') + #shiftwithinrange(textstart,textlen, range(10)) + #general_cmd(0b00011000) # display shift left + for i in range(40): + shiftwithinrange(i,16) + general_cmd(0b00011000) # display shift left + sleep(.05) + + if cmd == 'cgram': + num = raw_input("CGRAM address? ") + setCGRAMadd(int(num)) + + if cmd == 'ramdata': + print "fast RAM Data = ", binfill(readfast(True)) # read data from RAM + #print "RAM Data = ", lcd.read4bits(True) # read data from RAM + + if cmd == 'mess': + str = raw_input("message:") + lcd.message(str); + + if cmd == '9': + str = raw_input("9 bits of instruction code:") + char_mode = str[0]=="1" # 1 is true + str = str[1:].zfill(8) + bits = int('0b'+str,2) + print char_mode, str, bits + numrpt = raw_input("repeat #:") + numrpt = 1 if numrpt=="" else int(numrpt) + for count in range(0,numrpt): + lcd.write4bits(bits, char_mode) + + if cmd == 'dump': + DumpMCP23017Regs() + + if cmd == 'config': + pin = int(raw_input("pin number ")) + state = int(raw_input("1 or 0 "))==1 + lcd.mcp.config(pin,state) + + if cmd == 'oneline': + general_cmd(0b100000) + + if cmd == 'twoline': + general_cmd(0b101000) + + if cmd == 'longchar': + general_cmd(0b100100) + + if cmd == 'dispall': + dispall() + + if cmd == 'quit': + exit() + +# Testing using buttons on LCDPlate +while 1: + if (lcd.buttonPressed(lcd.LEFT)): + #print "BF", lcd.readBF() + print "fast BF + AD = ", binfill(readfast()) # read Busy Flag and Adress + #print "BF + AD = ", lcd.read4bits() # read Busy Flag and Adress + #back = ToggleBacklight(back) + sleep(.2) + + if (lcd.buttonPressed(lcd.UP)): + num = raw_input("Shift Display Right by ") + display_right(int(num)) + #num = raw_input("CGRAM address? ") + #setCGRAMadd(int(num)) + sleep(.2) #prevent multiple execution while button is down + + if (lcd.buttonPressed(lcd.DOWN)): + print "fast RAM Data = ", binfill(readfast(True)) # read data from RAM + #print "RAM Data = ", lcd.read4bits(True) # read data from RAM + sleep(.2) + + if (lcd.buttonPressed(lcd.RIGHT)): + str = raw_input("message:") + lcd.message(str); + + if (lcd.buttonPressed(lcd.SELECT)): + str = raw_input("9 bits of instruction code:") + char_mode = str[0]=="1" # 1 is true + str = str[1:].zfill(8) + bits = int('0b'+str,2) + print char_mode, str, bits + numrpt = raw_input("repeat #:") + #print "input",numrpt + if (numrpt == ""): # return means 1 + numrpt = 1 + else: + numrpt = int(numrpt) + for count in range(0,numrpt): + lcd.write4bits(bits, char_mode) From 0b3361316ea342c2df8d97ad9094c9e89584ba6c Mon Sep 17 00:00:00 2001 From: bbkiwi Date: Sun, 3 Mar 2013 18:08:39 +1300 Subject: [PATCH 13/13] Improved MCP230xx.py --- Adafruit_MCP230xx/Adafruit_MCP230xx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Adafruit_MCP230xx/Adafruit_MCP230xx.py b/Adafruit_MCP230xx/Adafruit_MCP230xx.py index c596ea19..ab1f4f25 100755 --- a/Adafruit_MCP230xx/Adafruit_MCP230xx.py +++ b/Adafruit_MCP230xx/Adafruit_MCP230xx.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python # Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried) # @@ -93,7 +93,7 @@ def config(self, pin, mode): if self.num_gpios <= 16: if (pin < 8): # replace low bits - self.direction = (self.direction >> 8)<<8 | self._readandchangepin(MCP23017_IODIRA, pin, mode) + self.direction = (self.direction & 0xff00) | self._readandchangepin(MCP23017_IODIRA, pin, mode) else: # replace hi bits self.direction = (self.direction & 0xff) | self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8