Tuesday, February 12, 2013
LCD testing notes
http://www.blogger.com/blogger.g?blogID=1840459474737789074#editor/target=post;postID=806095522320085075
Now I have also tested the LCD2004 just mounted behind the keypad. So now one 16 bit IO expander, MCP23017 controls 4 devices, buzzer, keypad, stepping motor, and LCD. I guess I cannot control all things at the same time. For example, after displaying something on the LCD, if I then move the motor, using the same MCP23017 GPA pins, then the LCD display would be corrupted.
So I should see now if I have used a demultiplexor, HC137, to select separate devices.
.END
# *****************************************************************************
# !/usr/bin/python2.7
#
# Program
# FPL4.py - 2013feb
# Author
# tlfong01 <http://tlfong01.blogspot.hk/>
# Configuration
# Raspberry Pi Bv2 512MB, Raspbian Wheezy, Python 2.7.3, RPI.GPIO 0.4.1a
# License
# GNU GPLv3
# Warranty
# For hobbist only. Use at your own risk. There is not any warranty,
# not even implied warranty of merchantability or fitness for any
# particular purpose
# System development methodologies / Programming paradims
# Software prototyping, Test-driven (TDD), Iterative and incremental (IID),
# Agile / Functional Programming (FP), Object Oriented Programming (OOP)
# Specifications summary
# 5V0max 50mA, 3V3max 300mA, PerPinMax 17mA source 12mA sink
# References
# IO Expander
# 1. Mcirochip Application Notes AN1043 (GPIO Expander)
# Matrix keypad
# 2. Microchip Application Notes AN1081 (Matrix Keypad)
# LCD1602
# 3. ShenZhen YaJingDa Electronics YJD1602A-1 datasheet (2007-09-08)
# 4. PowerTip PC-1602F datasheet (11/10/2004)
# 5. Sitronix ST7066U Dot Matrix LCD Controller/Driver datasheet (01/03/01)
# Raspberry Pi communities
# eLinux - http://elinux.org/RPi_Community
# element14 - http://www.element14.com/community/groups/raspberry-pi
# *****************************************************************************
# 0. Contents ******************************************************************
#
# 1. Program title
# 2. Python imports
# 3. RPi GPIO pin assignment, MCP230xx register base assignment
# 4. Global constants
# 5. GPIO Functions
# 6. Debugging and documentation functions (beep, print bit/byte, message)
# 7. IO Expander MCP23008, MCP23017
# 8. Decimal keypad
# 9. LCD - LCD1602. LCD2004
# 10. Stepping motor - unlpolar steppers 28BYJ48/NPM-PF35/PX245
# 11. Demultiplexor
# 12. Old test functions
# 13. Main program
# 1. Program Title ************************************************************
ProgramTitle = "FPL v4.05 TL Fong 2013feb11"
# 2 Python imports ***********************************************************
import sys
import time
import select
import RPi.GPIO as GPIO
import smbus
smBus1 = smbus.SMBus(1)
# 3. GPIO and IO Expander pin/address assignments *****************************
# * MCP230xx Register base addresses *
# * System B *
MCP23017BaseAddressSystemB1 = 0x20 # decimal/hexdecimal keypad
# * System A *
MCP23017BaseAddress1 = 0x22 # LED, button
MCP23008BaseAddress1 = 0x24 # stepping motors
MCP23008BaseAddress2 = 0x25 # keypad
MCP23008BaseAddress3 = 0x26 # LCD1602
# * GPIO pin numbering *
GPIO.setmode(GPIO.BOARD) # Use RPi GPIO numbering, Not BCM numbering
GPIO.setwarnings(False) # Disable linux's "pin already in use warning"
# * RPi GPIO pin numbering *
# P1-02 5V, P1-04 5V, P1-06 Gnd
# P1-01 3V3, P1-03 I2C SDA1, P1-05 I2C SCL1
# P1-08 UART TxD (MCP23017 Reset)
# P1-10 UART RxD (MCP23017 INTB)
# P1-12 RPi GPIO_GEN1 (BCM18) LED (P1-12 > LED > 330R > Gnd)
# P1-14 Gnd
# P1-16 GPIO_GEN4 - Buzzer, 3V3 5mA (P1-16 > Buzzer > Gnd)
# P1-18 GPIO_GEN5 Button (3V3 > 10K > Contact 1/2 > 330R > Gnd)
# P1-20 Gnd
# P1-22 GPIO_GEN6 - MCP23008 INT / MCP23017 INTA
RPiGPIOgen1 = 12 # Brown (P1-12, BCM GPIO 18) LED
RPiGPIOgen4 = 16 # Yellow (P1-16, BCM GPIO 23) Buzzer
RPiGPIOgen5 = 18 # Green (P1-18, BCM GPIO 24) Button
RPiGPIOgen6 = 22 # Blue (P1-22, BCM GPIO 25) IOx/keypad interrupt
RPiTxD = 8 # Orange (P1-08) UART TxD
RPiRxD = 10 # Yellow (P1-10) UART RxD
# * peripherals pins assignment *
LEDpin = RPiGPIOgen1
BuzzerPin = RPiGPIOgen4
ButtonPin = RPiGPIOgen5
TxDpin = RPiTxD
RxDpin = RPiRxD
# * GPIO input/output pins list *
OutputPinList = [LEDpin, BuzzerPin, TxDpin]
InputPinWithNoPullUpList = []
InputPinWithPullUpList = [ButtonPin, RxDpin, RPiGPIOgen6]
# 4. Global constants *********************************************************
# * Loop counters *
TwoTimes = 2
FourTimes = 4
EightTimes = 8
TenTimes = 10
TwentyTimes = 20
FiftyTimes = 50
OneHundredTimes = 100
TwoHundredTimess = 200
FourHundredTimes = 400
# * Elapse times *
TwentyMilliSeconds = 0.02
FiftyMilliSeconds = 0.05
OneHundredMilliSeconds = 0.1
TwoHundredMilliSeconds = 0.2
TenthSecond = 0.1
QuarterSecond = 0.25
HalfSecond = 0.5
OneSecond = 1
OneAndHalfSeconds = 1.5
TwoSeconds = 2
# * On/Off times *
OnTime = TenthSecond
OffTime = QuarterSecond
ButtonDebouncingTime = QuarterSecond
TestTime = FiftyMilliSeconds
OnTime = 0.1
OffTime = 0.25
# 5. GPIO Functions ***********************************************************
# * Local constants *
# * Nibble naming *
LowNibble = 0
HighNibble = 1
BothNibble = 2 # full byte of 8 bits
# * Nibble constants *
HighNibble1LowNibble0 = 0xf0
HighNibble0LowNibble1 = 0x0f
# * LED and buzzer states *
Off = False
On = True
# * Button states *
ButtonPressed = False
ButonReleased = True
# * Interrupt states *
Low = False
High = True
# * Setup, read/write GPIO pins *
setupOutputPin = lambda oPin: GPIO.setup(oPin, GPIO.OUT) # set GPIO pin as output
setupInputPinWithNoPullUp = lambda iPin: GPIO.setup(iPin, GPIO.IN, pull_up_down=GPIO.PUD_OFF) # set GPIO pin as input, no pull up
setupInputPinWithPullUp = lambda iPin: GPIO.setup(iPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # set GPIO pin as input, with pull up
writeOutputPin = lambda oPin, oValue: GPIO.output(oPin, oValue) # write value to output pin
setupWriteOutputPin = lambda oPin, oValue: (setupOutputPin(oPin), writeOutputPin(oPin, oValue)) # set and write
readInputPin = lambda iPin: GPIO.input(ButtonPin) # read value from input pin
def SetupGPIOpins(outputPinList, inputPinWithNoPullUpList, inputPinWithPullUpList): # set up GPIO pins in InputPinList and OutputPinList
for oPin in outputPinList:
setupWriteOutputPin(oPin, Off)
for iPin in inputPinWithNoPullUpList:
setupInputPinWithNoPullUp(iPin)
for iPin in inputPinWithPullUpList:
setupInputPinWithPullUp(iPin)
def SetupGPIO(): # set up GPIO pins
SetupGPIOpins(OutputPinList, InputPinWithNoPullUpList, InputPinWithPullUpList )
# * pulse/echo/toggle functions *
def pulsePin(oPin, onTime, offTime): # blink LED or beep buzzer
writeOutputPin(oPin, On)
time.sleep(onTime)
writeOutputPin(oPin, Off)
time.sleep(offTime)
def echoPin(iPin, oPin): # echo input pin to output pin, e.g. button to LED or buzzer
while True:
if readInputPin(iPin) == ButonReleased:
pass
else:
pulsePin(oPin, OnTime, OffTime)
break
continue
def togglePin(oPin, toggleTime): # toggle pin
writeOutputPin(oPin, On)
time.sleep(toggleTime)
writeOutputPin(oPin, Off)
time.sleep(toggleTime)
# * Test Buzzer, LED, Button *
def TestBuzzer(): # beep 4 times
SetupGPIO()
for i in range (FourTimes):
pulsePin(BuzzerPin, OnTime, OffTime)
def TestLED(): # blink 4 times
SetupGPIO()
for i in range (FourTimes):
pulsePin(LEDpin, OnTime, OffTime)
def TestButtonEchoBuzzer(): #
SetupGPIO()
print "\n", "Press button 4 times.", "\n"
for i in range (FourTimes):
echoPin(ButtonPin, BuzzerPin)
def TestButtonEchoTxD(): #
SetupGPIO()
print "\n", "Press button 4 times.", "\n"
for i in range (FourTimes):
echoPin(ButtonPin, TxDpin)
def TestButtonEchoRxD(): #
SetupGPIO()
print "\n", "Press button 4 times.", "\n"
for i in range (FourTimes):
echoPin(ButtonPin, RxDpin)
def TestRxdEchoTxD(): #
SetupGPIO()
print "\n", "RxD Echo TxD - Press button 4 times.", "\n"
for i in range (FourTimes):
echoPin(RxDpin, TxDpin)
def TestButtonEchoLED(): #
SetupGPIO()
print "\n", "Press button 4 times.", "\n"
for i in range (FourTimes):
echoPin(ButtonPin, LEDpin)
def TestTxDpin(): # blink 4 times
SetupGPIO()
for i in range (FourTimes):
pulsePin(TxDpin, OnTime, OffTime)
def TestRxDpin(): # blink 4 times
SetupGPIO()
for i in range (FourTimes):
pulsePin(RxDpin, OnTime, OffTime)
def TestTxDpinRxDpin1(): # blink, read 4 times
SetupGPIO()
for i in range (FourTimes):
writeOutputPin(TxDpin, On)
if readInputPin(RxDpin) == High:
print "RxD input = High"
else:
print "RxD input = Low"
time.sleep(1)
writeOutputPin(TxDpin, Off)
if readInputPin(RxDpin) == High:
print "RxD input = High"
else:
print "RxD input = Low"
time.sleep(1)
def TestTxDpinRxDpin2(): #
SetupGPIO()
print "\n", "Short to Ground RxDpin 4 times.", "\n"
for i in range (FourTimes):
echoPin(RxDpin, TxDpin)
# GPIO Interrupt function !!! not yet tested !!!
def TestInterruptPinFallingEdgeDetection(): # !!! Not tested !!!
GPIO.cleanup() # set all input pins no pull up, disable all interutp detection setting
SetupGPIO()
GPIO.set_low_event(InterruptPin) # set up low level detection
for i in range(30):
if GPIO.event_detected(InterruptPin):
break
else:
print "No interrupt detected.", i
time.sleep(1)
continue
GPIO.set_low_event(InterruptPin, enable = False) # disable detection
print "End of test, or interrupt detected"
# 5. Debugging and documentation functions ************************************
# * Data bit processing and printing *
def SetDataBit(dataByte, bitIndex):
setDataByte = 0x01 << bitIndex
dataByte = dataByte | setDataByte
return dataByte
def ResetDataBit(dataByte, bitIndex):
resetDataByte = ~(0x01 << bitIndex)
dataByte = dataByte & resetDataByte
return dataByte
def ConvertIntegerToFourBitPattern(integer):
FourBitPattern = [""]
for k in range(4):
FourBitPattern = [i+j for i in ['0','1'] for j in FourBitPattern]
return FourBitPattern[integer]
def ConvertIntegerToEightPattern(integer):
EightBitPattern = [""]
for k in range(8):
EightBitPattern = [i+j for i in ['0','1'] for j in EightBitPattern]
return EightBitPattern[integer]
def PrintEightBitPattern(message, dataByte):
eightBitPattern = ConvertIntegerToEightPattern(dataByte)
print message, eightBitPattern
def PrintFourBitPattern(message, dataByte):
fourBitPattern = ConvertIntegerToFourBitPattern(dataByte)
print message, fourBitPattern
def Beep(count):
for i in range(count):
pulsePin(BuzzerPin, OnTime, OffTime)
def StartBeep():
Beep(2)
time.sleep(1)
def StopBeep():
Beep(2)
def OneBeep():
Beep(1)
def FourBeeps():
Beep(4)
def StartProgram():
message = "\n" + "*** Start Program - " + ProgramTitle + " *******************************" + "\n"
SetupGPIO()
StartBeep()
print message
def StopProgram():
message = "\n" + "*** Stop Program **************************************************************" + "\n"
StopBeep()
print message
# 7. IO Expander MCP23008, MCP23017 *******************************************
# * Local constants *
# * Port type *
PortA = 0
PortB = 1
# * MCP23008/MCP23017 register address offsets index Bank 0 *
InputOutputDirection = 0
InputPolarity = 1
InterruptEnable = 2
DefaultValue = 3
CompareMode = 4
BankInterruptPinMode = 5
PullUp = 6
InterruptFlag = 7
InterruptCapture = 8
PortStatus = 9
OutputLatch = 10
# * Data constant bytes *
AllOutputByte = 0x00
AllInputByte = 0xff
AllHighByte = 0xff
AllLowByte = 0x00
AllPullUpByte = 0xff
# * Direction setting bytes *
HalfHighHalfLow = 0xf0
HalfLowHalfHigh = 0x0f
Nibble1HighNibble2Low = 0xf0
Nibble1LowNibble2High = 0x0f
HighNibbleInputLowNibbleOutput = 0xf0
# * MCP23008/MCP23017 Bank0/Bank1 register address offset arrays *
RegisterAddressOffsetArrayBank0 = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x1d, 0x0f, 0x11, 0x13, 0x15]
# * Setup input/output ports *
def SetupMCP23008PortAllOutput(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
def SetupMCP23017BothPortAllOutput(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortB, AllOutputByte)
def SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortB, AllInputByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PullUp, PortB, AllPullUpByte)
# * Read/write registers *
def WriteDataByte(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType, dataByte):
if (portType == PortA) | (portType == PortA):
addressOffset = registerAddressArray[dataRegisterIndex]
if (portType == PortB):
addressOffset = registerAddressArray[dataRegisterIndex + 11]
smBus1.write_byte_data(registerBaseAddress, addressOffset, dataByte)
def WriteDataBit(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType, bitNumber, dataBit):
if (portType == PortA) | (portType == PortA):
addressOffset = registerAddressArray[dataRegisterIndex]
if (portType == PortB):
addressOffset = registerAddressArray[dataRegisterIndex + 11]
dataByte = smBus1.read_byte_data(registerBaseAddress, addressOffset)
bitMask = 0x01 << bitNumber
if (dataBit == 1):
dataByte = dataByte | bitMask
else:
dataByte = dataByte & (~bitMask)
smBus1.write_byte_data(registerBaseAddress, addressOffset, dataByte)
def ReadDataByte(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType):
if (portType == PortA):
addressOffset = registerAddressArray[dataRegisterIndex]
if (portType == PortB):
addressOffset = registerAddressArray[dataRegisterIndex + 11]
dataByte = smBus1.read_byte_data(registerBaseAddress, addressOffset)
return dataByte
def ReadDataBit(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType, bitNumber):
if (portType == PortA):
addressOffset = registerAddressArray[dataRegisterIndex]
if (portType == PortB):
addressOffset = registerAddressArray[dataRegisterIndex + 11]
dataByte = smBus1.read_byte_data(registerBaseAddress, addressOffset)
bitMask = 0x01 << bitNumber
dataByte = dataByte & bitMask
if (dataByte == 0):
dataBit = 0
else:
dataBit = 1
return dataBit
def ReadUpperNibble(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType):
dataByte = ReadDataByte(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType)
upperNibble = dataByte >> 4
return upperNibble
def ReadLowerNibble(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType):
dataByte = ReadDataByte(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType)
lowerNibble = dataByte & 0x0f
return lowerNibble
# * Config interrupts *
def EnableInterruptOnChangeHighNibble(registerBaseAddress):
EnableInterruptHighNibble = 0xf0
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortA, EnableInterruptHighNibble)
def DisableInterruptOnChangeHighNibble(registerBaseAddress):
DisableInterruptHighNibble = 0x00
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortA, DisableInterruptHighNibble)
def SetInterruptOnChangeDefaultHighNibble(registerBaseAddress):
DefaultValueByte = 0xf0
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptOnChangeDefaultValue, PortA, DefaultValueByte)
def SetInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress):
InterruptOnChangeDefaultValueHighNibble = 0xf0 # GP4~7 change from default value will cause interrupt
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, CompareMode, PortA, InterruptOnChangeDefaultValueHighNibble)
def SetInterruptOutputPushPull(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
PushPull = 0b00111010 # 0x32, seq/slew disabled, interrupt output drive drive (push pull) active High
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PushPullOpenDrain, PortA, PushPull)
def SetInterruptOutputOpenDrain(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
OpenDrain = 0b00111000 # 0x34, seq/slew disabled, interrupt output open drain (don't care active High or Low)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PushPullOpenDrain, PortA, OpenDrain)
# * Poll interrupts *
def ReadInterruptFlagHighNibble(registerBaseAddress):
interruptFlagByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptFlag, PortA)
interruptFlagNbble = interruptFlagByte >> 4
return interruptFlagNibble
def ReadInterruptCaptureHighNibble(registerBaseAddress):
interruptCaptureByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptCapture, PortA)
interruptCaptureNibble = interruptCaptureByte >> 4
return interruptCaptureNibble
def ReadInterruptCaptureLowNibble(registerBaseAddress):
interruptCaptureByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptCapture, PortB)
interruptCaptureNibble = interruptCaptureByte & 0x0f
return interruptCaptureNibble
def DetectOneInterrupt(registerBaseAddress): # !!! NOT tested !!!
interruptFlagNibble = ReadInterruptFlagHighNibble(registerBaseAddress)
interruptCaptureNibble = ReadInterruptCaptureHighNibble(registerBaseAddress)
print "Interrupt capture high nibble = ", ConvertIntegerToFourBitPattern(interruptCaptureNibble)
print "Interrupt capture high nibble = ", ConvertIntegerToFourBitPattern(interruptCaptureNibble)
ClearInterruptOnChangeHighNibble(registerBaseAddress) # !!! clear interrupt !!!
time.sleep(2)
# * Test port toggling, poll interrupts *
def ToggleMCP23008GP(registerBaseAddress, toggleTime, toggleCount):
SetupMCP23008PortAllOutput(registerBaseAddress)
for i in range(toggleCount):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllHighByte)
time.sleep(toggleTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllLowByte)
time.sleep(toggleTime)
def ToggleMCP23017GP(registerBaseAddress, toggleTime, toggleCount):
SetupMCP23017BothPortAllOutput(registerBaseAddress)
for i in range(toggleCount):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllHighByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortB, AllHighByte)
time.sleep(toggleTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllLowByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortB, AllLowByte)
time.sleep(toggleTime)
def ToggleMCP23017B1(registerBaseAddress, toggleTime, toggleCount):
SetupMCP23017BothPortAllOutput(registerBaseAddress)
for i in range(toggleCount):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllHighByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortB, AllHighByte)
time.sleep(toggleTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllLowByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortB, AllLowByte)
time.sleep(toggleTime)
def TestToggleMCP23008GP():
ToggleMCP23008GP(MCP23008BaseAddress1, ToggleTime, ToggleCount)
def TestToggleMCP23017GP():
ToggleMCP23008GP(MCP23017BaseAddress1, ToggleTime, ToggleCount)
def TestDetectInterrupt(count): # !!! NOT Tested !!!
RegisterBaseAddress = MCP23008BaseAddress2
SetupKeypadInterruptHighNibbleCompareDefaultValueOpenDrainOutput(RegisterBaseAddress)
for i in range(count):
DetectOneInterrupt(RegisterBaseAddress)
# * System B test functions *
def TestToggleMCP23017SystemB1(count):
ToggleTime = 0.5
ToggleCount = 4
registerBaseAddress = MCP23017BaseAddressSystemB1
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
for i in range(count):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllHighByte)
time.sleep(ToggleTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, AllLowByte)
time.sleep(ToggleTime)
def TestReadMCP23017SystemB1(count):
registerBaseAddress = MCP23017BaseAddressSystemB1
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
for i in range(count):
dataByte = ReadDataByte(MCP23017BaseAddressSystemB1, RegisterAddressOffsetArrayBank0, PortStatus, PortB)
PrintEightBitPattern("Data byte read = ", dataByte)
time.sleep(1)
def TestBlinkMCP23017SystemB1GPIObit(bitNumber, onTime, offTime, count) :
registerBaseAddress = MCP23017BaseAddressSystemB1
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
for i in range(count):
WriteDataBit(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, bitNumber, High)
time.sleep(onTime)
WriteDataBit(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, bitNumber, Low)
time.sleep(offTime)
def TestReadMCP23017SystemB1GPIObit(bitNumber, count):
registerBaseAddress = MCP23017BaseAddressSystemB1
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
for i in range(count):
dataBit = ReadDataBit(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortB, bitNumber)
if (dataBit == High):
print "Data bit is High"
else:
print "Data bit is Low"
time.sleep(1)
# 8. Decimal keypad ***********************************************************
# *****************************************************************************
# * Decimal keypad using MCP23017 v2.18 TL Fong last update 2013feb03 *
# *****************************************************************************
# * Configuration *
# MCP23017 GPIO direction - Port A = output, Port B = input
# Keypad pin assignment - GPA0~A2 = Col0~2, GPB0~B3 = Row0~3
Keypad017InterruptPin = RPiGPIOgen6
# * Local constants *
# * MCP23017 stateTuple indexes and default values *
RegisterBaseAddressIndex = 0
OutputLatchRegisterIndex = 1
PortStatusRegisterIndex = 2
InterruptCaptureRegisterIndex = 3
InterruptFlagRegisterIndex = 4
RegisterBaseAddress = MCP23017BaseAddressSystemB1
OutputLatchRegisterResetValue = 0x00
PortStatusRegisterResetValue = 0x00
InterruptCaptureRegisterResetValue = 0x00
InterruptFlagRegisterResetValue = 0x00
MCP23017StateTuple = RegisterBaseAddress, OutputLatchRegisterResetValue, \
InterruptCaptureRegisterResetValue, InterruptFlagRegisterResetValue
# * Polling modes *
NoPollJustGetKeyEverySecond = 0
PollRowStatusNibble = 1
PollMCP23017Interrupt = 2
# * Setup keypad *
def SetupKeypad017(stateTuple):
registerBaseAddress = stateTuple[RegisterBaseAddressIndex]
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
SetupKeypad017Interrupt(registerBaseAddress) # buggy !!!!!!!!!!
ClearKeypad017Interrupt(registerBaseAddress)
WriteKeypad017ColumnsAllLow(registerBaseAddress)
return stateTuple
# * Setup/Clear/Check keypad interrupt *
def SetupKeypad017Interrupt(registerBaseAddress):
SetKeypad017InterruptEnable(registerBaseAddress)
SetKeypad017DefaultValue(registerBaseAddress)
SetKeypad017EnableCompareDefaultValue(registerBaseAddress)
SetKeypad017BankInterruptDriverMode(registerBaseAddress)
def SetKeypad017InterruptEnable(registerBaseAddress):
EnableInterruptLowNibble = 0x0f
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortB, EnableInterruptLowNibble)
def SetKeypad017InterruptDisable(registerBaseAddress):
DisableInterruptByte = 0x00
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortB, DisableInterruptByte)
def SetKeypad017DefaultValue(registerBaseAddress):
DefaultValueByte = 0x0f # row status nibble is all bits high if no key pressed
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, DefaultValue, PortB, DefaultValueByte)
def SetKeypad017EnableCompareDefaultValue(registerBaseAddress):
InterruptOnChangeDefaultValueLowNibble = 0x0f # GPB0~3 change from default value will cause interrupt
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, CompareMode, PortB, InterruptOnChangeDefaultValueLowNibble)
def SetKeypad017BankInterruptDriverMode(registerBaseAddress):
# bit 7 = 0 (Bank = 0, reg with each port are in the same bank (addresses are sequential))
# bit 6 = 0 (No mirror, INTA and INTB independent)
# bit 5 = 1 (Sequential operation disabled)
# bit 4 = 1 (Slew rate disabled)
# bit 3 = 0 (Disable MCP23S17 address pins, Don't care for MCP23017)
# bit 2 = 0 (Interrupt driver push pull, no open drain)
# bit 1 = 1 (Interrrupt active high)
# bit 0 = 0 (Unimplemented, read as 0)
# 0b00110010 = 0x32
Bank0DriverPushPullHighActive = 0x32
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, BankInterruptPinMode, PortB, Bank0DriverPushPullHighActive)
def ClearKeypad017Interrupt(registerBaseAddress):
WriteAllColumnsLow(registerBaseAddress)
time.sleep(0.5)
dummyRead = ReadInterruptCaptureLowNibble(registerBaseAddress)
#def ReadKeypad017InterruptPin(interruptPin):
# interruptStatus = readInputPin(interruptPin)
# return interruptStatus
# * Write columns *
def WriteKeypad017Columns(registerBaseAddress, columnDataByte):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, columnDataByte)
def WriteKeypad017ColumnsAllLow(registerBaseAddress):
WriteKeypad017Columns(registerBaseAddress, AllLowByte)
# * Read rows *
#def GetKeypad017RowDataByte(registerBaseAddress):
# rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortB)
# return rowDataByte
#def GetKeypad017RowDataNibble(registerBaseAddress):
# rowDataByte = GetKeypad017RowDataByte(registerBaseAddress)
# PrintEightBitPattern("Row pattern = ", rowDataByte)
# rowDataNibble = rowDataByte & 0x0f
# # PrintFourBitPattern("Row pattern = ", rowDataNibble)
# return rowDataNibble
def GetKeypad017RowDataNibble(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortB)
rowDataNibble = rowDataByte & 0x0f
return rowDataNibble
# * Get Row Number, Column Number, and Key Number *
def GetKeypad017RowNumber(registerBaseAddress):
RowDataNibbleTuple = 0b1110, 0b1101, 0b1011, 0b0111, 0b1111, 0b0000
rowDataNibble = GetKeypad017RowDataNibble(registerBaseAddress)
# *** Begin debugging *****************************************************
# rowDataNibble = 0b1011
# *** End debugging *******************************************************
# *** Begin debugging *****************************************************
PrintFourBitPattern("Row pattern = ", rowDataNibble)
rowNumber = RowDataNibbleTuple.index(rowDataNibble)
print ("Row number = ", rowNumber)
# *** End debugging *******************************************************
rowNumber = RowDataNibbleTuple.index(rowDataNibble)
return rowNumber
def GetKeypad017ColumnNumber(registerBaseAddress):
ColumnNibbleTuple = 0b1110, 0b1101, 0b1011
NoKeyPressNibble = 0b1111
for columnNibble in (ColumnNibbleTuple):
WriteKeypad017Columns(registerBaseAddress, columnNibble)
rowDataNibble = GetKeypad017RowDataNibble(registerBaseAddress)
if rowDataNibble != NoKeyPressNibble:
break
# *** Begin debugging *****************************************************
# columnNibble = 0b1101
# columnNumber = ColumnNibbleTuple.index(columnNibble)
# PrintFourBitPattern("Column pattern = ", columnNibble)
# print ("Column number = ", columnNumber)
# *** End debugging *******************************************************
columnNumber = ColumnNibbleTuple.index(columnNibble)
return columnNumber
def GetKeypad017KeyNumber(registerBaseAddress):
rowNumber = GetKeypad017RowNumber(registerBaseAddress)
columnNumber = GetKeypad017ColumnNumber(registerBaseAddress)
keyNumber = (rowNumber * 3) + (columnNumber + 1)
return keyNumber
# * Get keys *
def GetKeypad017Key(registerBaseAddress, checkPressingKeyMode):
if (checkPressingKeyMode == NoPollJustGetKeyEverySecond):
print "Read key every second"
time.sleep(1)
LoopUntilOneSecondEnded()
elif (checkPressingKeyMode == PollRowStatusNibble):
print "Polling Gpio"
LoopUntilKeypad017RowDataNibbleChange(registerBaseAddress)
elif (checkPressingKeyMode == PollMCP23017Interrupt):
print "Polling MCP23017 interrupt INTB"
LoopUntilKeypad017InterruptPinActive(registerBaseAddress)
keyNumber = GetKeypad017KeyNumber(registerBaseAddress)
return keyNumber
def GetKeypad017KeySequence(stateTuple, checkPressingKeyMode, count):
registerBaseAddress = stateTuple[RegisterBaseAddressIndex]
for i in range (count):
OneBeep()
keyNumber = GetKeypad017Key(registerBaseAddress, checkPressingKeyMode)
print "Key", i + 1, " = ", keyNumber
time.sleep(0.25)
return stateTuple
# * No polling, just read key at the end of each second *
def LoopUntilOneSecondEnded():
time.sleep(1)
# * Poll row status *
def LoopUntilKeypad017RowDataNibbleChange(registerBaseAddress):
WriteKeypad017Columns(registerBaseAddress, AllLowByte)
NoKeyPressedNibble = 0xf
rowDataNibble = NoKeyPressedNibble
while (rowDataNibble == NoKeyPressedNibble):
rowDataNibble = GetKeypad017RowDataNibble(registerBaseAddress)
time.sleep(0.05) # debouncing time 50mS
# * Poll MCP23017 interrupt pin *
def LoopUntilKeypad017InterruptPinActive(registerBaseAddress):
#MCP23017 INTB connected to RPiuGen6
#interruptPinState = readInputPin(RPiGPIOgen6)
#print "1 interruptPinState = ", interruptPinState
#ClearKeypadInterrupt(registerBaseAddress)
# interruptPinState = readInputPin(RPiGPIOgen6)
#print "2 interruptPinState = ", interruptPinState
# *** Begin debugging *****************************************************
#while True:
# interruptPinState = readInputPin( RPiGPIOgen6)
# print "3 interruptPinState = ", interruptPinState
# time.sleep(1)
# *** End debugging *******************************************************
#while (interruptPinState == ~InterruptActive):
# interruptPinState = readInputPin(interruptPin)
# print "interruptPinState = ", interruptPinState
# time.sleep(1)
# MCP23017 INTB shifted up to 5V) logical level, then connected to MCP23017 GPB5
KeypadInterruptPinNumber = 5
ClearKeypadInterrupt(registerBaseAddress)
interruptDataBit = High # !!! ULN2803 inverts MCP23017 INTB, so interrupt is now Low active !!!
while (interruptDataBit == High):
interruptDataBit = ReadDataBit(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortB, KeypadInterruptPinNumber)
time.sleep(0.1) # debouncing time
# * Test MCP23017 Decimal keypad *
def TestKeypad017(checkPressingKeyMode, keyCount):
stateTuple = MCP23017StateTuple
stateTuple = SetupKeypad017(stateTuple)
stateTuple = GetKeypad017KeySequence(stateTuple, checkPressingKeyMode, keyCount)
stateTuple = SetupKeypad017(stateTuple)
# *****************************************************************************
# * Decimal keypad using MCP23008 * TL Fong 2013feb01
# *****************************************************************************
# * Function descriptions *
# SetupKeypad(registerBaseAddress)
# Assign GP0~3 as output (Col0~2, Col3 n.c), GP4~7 input (Row0~3)
# WriteAllColumnsLow(registerBaseAddress)
# Set all column outputs (GP0~2 actually, GP3 dummy)
# LoopUntilGpioPortHighNibbleChange(registerBaseAddress)
# Loop until GPIO register's GP4~7 not all High (some key pressed)
# LoopUntilInterruptCaptureHighNibbleChange(registerBaseAddress)
# Loop until INTCAP register's ICP4~7 not all High (some key pressed)
# Keypad scanning procedure version 1.0
# 1. Set 3 column ports GP0, GP1, GP2 as output (GP3 don't care)
# 2. Set 4 row ports GP4, GP5, GP6, GP7 as input
# 3. Write Low to all column ports
# 4. Wait until any key pressed (pooling or interrupt)
# 5. Find rowNumber and column number
# 6. Calculate key number
# * keypad base address and smBus setting *
KeypadRegisterBaseAddress = MCP23008BaseAddress2
KeypadSmBus = smBus1
PollGpioRegister = 0
PollKeypadInterruptPin = 1
# * Set up keypad matrix GPIO and interrupts *
def SetupKeypad(registerBaseAddress):
SetupKeypadGPIO(registerBaseAddress)
SetupKeypadInterrupt(registerBaseAddress)
ClearKeypadInterrupt(registerBaseAddress)
def SetupKeypadGPIO(registerBaseAddress):
UpperNibbleInputLowerNibbleOutput = 0xf0 # (GP4~7, Row0~3) = input, lower nibble (GP0~3, Column0~2, 3 = no coonect) = output
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, UpperNibbleInputLowerNibbleOutput)
WriteAllColumnsLow(registerBaseAddress)
def SetupKeypadInterrupt(registerBaseAddress):
EnableInterruptOnChangeHighNibble(registerBaseAddress) # Enable interrupt on upper nibble (GP4~7)
SetInterruptOnChangeDefaultHighNibble(registerBaseAddress) # Interrupt default values = all high (GP4~7 0b1111)
SetInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress) # select compare default value interrutpt
SetInterruptOutputOpenDrain(registerBaseAddress) # set interrupt output (INT) open drain
def EnableInterruptOnChangeHighNibble(registerBaseAddress):
EnableInterruptHighNibble = 0xf0
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortA, EnableInterruptHighNibble)
def SetInterruptOnChangeDefaultHighNibble(registerBaseAddress):
DefaultValueByte = 0xf0
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptOnChangeDefaultValue, PortA, DefaultValueByte)
def SetInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress):
InterruptOnChangeDefaultValueHighNibble = 0xf0 # GP4~7 change from default value will cause interrupt
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, CompareMode, PortA, InterruptOnChangeDefaultValueHighNibble)
def SetInterruptOutputPushPull(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
PushPull = 0b00111010 # 0x32, seq/slew disabled, interrupt output drive drive (push pull) active High
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PushPullOpenDrain, PortA, PushPull)
def SetInterruptOutputOpenDrain(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
OpenDrain = 0b00111000 # 0x34, seq/slew disabled, interrupt output open drain (don't care active High or Low)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PushPullOpenDrain, PortA, OpenDrain)
# * Clear and poll interrupts *
def ClearKeypadInterrupt(registerBaseAddress):
WriteAllColumnsLow(registerBaseAddress)
time.sleep(0.5)
dummyRead = ReadInterruptCaptureHighNibble(registerBaseAddress)
def ReadKeypadInterruptPin(interruptPin):
interruptStatus = readInputPin(interruptPin)
return interruptStatus
# * Write columns *
def WriteColumns(registerBaseAddress, columnDataNibble):
columnDataByte = columnDataNibble | 0x00
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, columnDataByte)
def WriteAllColumnsLow(registerBaseAddress):
AllColumnsLowNibble = 0x0
WriteColumns(registerBaseAddress, AllColumnsLowNibble)
def WriteColumn0Low(registerBaseAddress):
Column0LowNibble = 0xe
WriteColumns(registerBaseAddress, Column0LowNibble)
def WriteColumn1Low(registerBaseAddress):
Column1LowNibble = 0xd
WriteColumns(registerBaseAddress, Column1LowNibble)
def WriteColumn2Low(registerBaseAddress):
Column2LowNibble = 0xb
WriteColumns(registerBaseAddress, Column2LowNibble)
# * Read rows *
def GetRowDataByte(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortA)
return rowDataByte
def GetRowDataNibble(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortA)
rowDataNibble = rowDataByte >> 4
return rowDataNibble
# * Get row number, column number, and key number *
def GetRowNumber(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortA)
rowDataNibble = rowDataByte >> 4
if rowDataNibble == 0b1110:
rowNumber = 0
return rowNumber
elif rowDataNibble == 0b1101:
rowNumber = 1
return rowNumber
elif rowDataNibble == 0b1011:
rowNumber = 2
return rowNumber
elif rowDataNibble == 0b0111:
rowNumber = 3
return rowNumber
else:
rowNumber = 99
return rowNumber
def GetColumnNumber(registerBaseAddress):
RowsAllHigh = 0xf
WriteColumn0Low(registerBaseAddress)
rowDataNibble = ReadUpperNibble(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortA)
if rowDataNibble != RowsAllHigh:
columnNumber = 0
return columnNumber
WriteColumn1Low(registerBaseAddress)
rowDataNibble = ReadUpperNibble(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortA)
if rowDataNibble != RowsAllHigh:
columnNumber = 1
return columnNumber
WriteColumn2Low(registerBaseAddress)
rowDataNibble = ReadUpperNibble(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortA)
if rowDataNibble != RowsAllHigh:
columnNumber = 2
return columnNumber
def GetKeyNumber(rowNumber, columnNumber):
# print "Row Number = ", rowNumber
# print "Column Number = ", columnNumber
keyNumber = (rowNumber * 3) + (columnNumber + 1)
return keyNumber
# * Get one key and a sequence of keys *
def GetKey(registerBaseAddress, pollType):
PollGpioRegister = 0
PollKeypadInterruptPin = 1
if (pollType == PollGpioRegister):
# print "Polling GpioRegister"
LoopUntilGpioPortHighNibbleChange(registerBaseAddress)
elif (pollType == PollKeypadInterruptPin):
# print "Polling Interrupt Pin"
LoopUntilKeypadInterruptPinLow(registerBaseAddress, KeypadInterruptPin)
rowNumber = GetRowNumber(registerBaseAddress)
columnNumber = GetColumnNumber(registerBaseAddress)
keyNumber = GetKeyNumber(rowNumber, columnNumber)
return keyNumber
def GetKeyString(registerBaseAddress, pollType, count):
for i in range (count):
OneBeep()
keyNumber = GetKey(registerBaseAddress, pollType)
print "Key", i + 1, " = ", keyNumber
# * Loop until row data changes *
def LoopUntilGpioPortHighNibbleChange(registerBaseAddress):
WriteAllColumnsLow(registerBaseAddress)
NoKeyPressedNibble = 0xf
rowDataNibble = NoKeyPressedNibble
while (rowDataNibble == NoKeyPressedNibble):
rowDataNibble = GetRowDataNibble(registerBaseAddress)
time.sleep(0.05) # debouncing time 50mS
# * Loop until interrupt key low *
def LoopUntilKeypadInterruptPinLow(registerBaseAddress, interruptPin):
ClearKeypadInterrupt(registerBaseAddress)
interruptPinState = readInputPin(interruptPin)
#print "interruptPinState = ", interruptPinState
while (interruptPinState == True):
interruptPinState = readInputPin(interruptPin)
#print "interruptPinState = ", interruptPinState
#time.sleep(1)
#print "interruptPinState = ", interruptPinState
time.sleep(0.05) # debouncing time 50mS
# * Test keypad *
def TestKeypad(registerBaseAddress, pollType, count):
SetupKeypad(registerBaseAddress)
if (pollType == PollKeypadInterruptPin):
SetupKeypadInterrupt(registerBaseAddress)
ClearKeypadInterrupt(registerBaseAddress)
print "*** Start testing keypad. ***"
print "Press keypad ", count, "times."
GetKeyString(registerBaseAddress, pollType, count)
ClearKeypadInterrupt(registerBaseAddress)
print "*** Stop testing keypad. ***\n"
def TestPollingKeypad():
TestKeypad(KeypadRegisterBaseAddress, PollGpioRegister, count = 4)
def TestInterruptKeypad():
TestKeypad(KeypadRegisterBaseAddress, PollKeypadInterruptPin, count = 4)
# * LCD1602 *******************************************************************
LcdRegisterBaseAddress = MCP23008BaseAddress3 # 0x26
# * LCD1602A-1 16-pin connector (MCP23008 GPIO 6-pin connector) Pin numbering *
# Pin 04 (Pin 1) RegisterSelect
# Pin 06 (Pin 2) WriteEnable
# Pin 11 (Pin 3) DataBit4 = 2
# Pin 12 (Pin 4) DataBit5 = 3
# Pin 13 (Pin 5) DataBit6 = 4
# Pin 14 (Pin 6) DataBit7 = 5
# LCD1602 software initialization procedure
# Part 1 - Pseudo 8 bit instructions to config 4 bit instruction mode (0x30, 0x30, 0x30, 0x20)
# 1. Power on, wait 20mS (> 15mS)
# 2. Write 0x3, wait 5mS (> 4.1mS) # set 8 bit interface
# 3. Write 0x3, wait 1mS (> 100uS) # set 8 bit interface
# 4. Write 0x3, wait 1mS (> 37uS) # set 8 bit interface
# 5. Write 0x2, wait 1mS (> 37uS) # set 4 bit interface
# Part 2- 4 bit instructions to config display characteristics (0x28, 0x08, 0x01, 0x06, 0x02)
# 6. Write 0x2, wait 1mS (> 37uS) 0x8 wait 1mS (> 37uS) (2 lines, 5x8 dot)
# 7. Write 0x0, wait 1mS (> 37uS) 0x8 wait 1mS (> 37uS) (cursor on, no blinking, blank screen)
# 8. Write 0x0, wait 1mS (> 37uS) 0x1 wait 2mS (> 1.52mS)(clear display)
# 9. Write 0x0, wait 1mS (> 37uS) 0xe (DisplayOnCursorOnCursorBlinkOff)
# a. Write 0x0, wait 1mS (> 37uS) 0x2 wait 2mS (cursor home)
# * LCD1602A-1 16-pin connector pin numbering *
RegisterSelect = 0 # 0 = instruction register, 1 = data register
WriteEnable = 1 # 1 = enable, 0 = disable
DataBit4 = 2
DataBit5 = 3
DataBit6 = 4
DataBit7 = 5
# * Constant data bytes *
AllZeroDataByte = 0x00
AllOneDataByte = 0xff
# * Write Enable/Disable, Select Data/Instruction masks *
EnableWriteMask = 0x02 # 0b 0000 0010
DisableWriteMask = 0xfd # 0b 1111 1101
SelectDataRegisterMask = 0x01 # 0b 0000 0001
SelectInstructionRegisterMask = 0xfe # 0b 1111 1110
# Register selection constant *
InstructionRegister = 0
DataRegister = 1
# * LCD1602A-1 control instructions *
# * Instruction codes *
EightBitInstructionMode = 0x3
FourBitInstructionMode = 0x2
TwoLineFiveTimesEightDot1 = 0x2
TwoLineFiveTimesEightDot2 = 0x8
DisplayOnCursorOnCursorBlinkOff1 = 0x0
DisplayOnCursorOnCursorBlinkOff2 = 0xe
ClearDisplay1 = 0x0
ClearDisplay2 = 0x1
CursorIncrementDisplayNoShift1 = 0x0
CursorIncrementDisplayNoShift2 = 0x6
CursorHome1 = 0x0
CursorHome2 = 0x2
# * Instruction timing *
PowerOnResetDelay = 0.05 # 50mS
VeryLongOperationDelay = 0.005 # 5mS
LongOperationDelay = 0.002 # 2mS
ShortOperationDelay = 0.00005 # 50uS
WritePulseLength = 0.00005 # 50uS
# * RPi/MCP23008 Python functions *
def LcdGpioSetup(registerBaseAddress):
SetupMCP23008PortAllOutput(registerBaseAddress)
def LcdConfiguration(registerBaseAddress):
dataControlByte = AllZeroDataByte
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
LcdDisableWrite(registerBaseAddress, dataControlByte)
time.sleep(PowerOnResetDelay)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, VeryLongOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte03 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte04 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, FourBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte05 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte06 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte07 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte08 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte09 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, ClearDisplay1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte10 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, ClearDisplay2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte11 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte12 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte13 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorHome1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte14 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorHome2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte15 = ", dataControlByte)
return dataControlByte
def LcdSelectDataRegister(registerBaseAddress, dataByte):
dataByte = dataByte | SelectDataRegisterMask
LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def LcdSelectInstructionRegister(registerBaseAddress, dataByte):
dataByte = dataByte & SelectInstructionRegisterMask
LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def LcdEnableWrite(registerBaseAddress, dataByte):
dataByte = dataByte | EnableWriteMask
LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def LcdDisableWrite(registerBaseAddress, dataByte):
dataByte = dataByte & DisableWriteMask
LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def LcdWritePulse(registerBaseAddress, dataByte):
LcdEnableWrite(registerBaseAddress, dataByte)
time.sleep(WritePulseLength)
LcdDisableWrite(registerBaseAddress, dataByte)
return dataByte
def LcdWriteDataByte(registerBaseAddress, dataByte):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, dataByte)
return dataByte
def LcdWriteDataNibble(registerBaseAddress, dataByte, dataNibble, registerType, operationDelay):
dataNibble = dataNibble << 2
dataByte = dataByte & 0b11000011
dataByte = dataByte | dataNibble
if (registerType == InstructionRegister):
dataByte = LcdSelectInstructionRegister(registerBaseAddress, dataByte)
elif (registerType == DataRegister):
dataByte = LcdSelectDataRegister(registerBaseAddress, dataByte)
LcdDisableWrite(registerBaseAddress, dataByte)
dataByte = LcdWriteDataByte(registerBaseAddress, dataByte)
LcdWritePulse(registerBaseAddress, dataByte)
time.sleep(operationDelay)
return dataByte
def LcdWriteCharFourBitMode(registerBaseAddress, dataControlByte, asciiChar, registerType):
charUpperNibble = ord(asciiChar) >> 4
charLowerNibble = ord(asciiChar) & 0x0f
LcdWriteCharTwoNibbles(registerBaseAddress, dataControlByte, charUpperNibble, charLowerNibble, registerType)
return dataControlByte
def LcdWriteDataByteFourBitMode(registerBaseAddress, dataControlByte, dataByte, registerType):
upperNibble = dataByte >> 4
lowerNibble = dataByte & 0x0f
LcdWriteCharTwoNibbles(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType)
return dataControlByte
def LcdWriteCharTwoNibbles(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType):
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, upperNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, lowerNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
return dataControlByte
def LcdWriteCharString(registerBaseAddress, dataControlByte, string):
for asciiChar in (string):
LcdWriteCharFourBitMode(registerBaseAddress, dataControlByte, asciiChar, DataRegister)
return dataControlByte
def LcdMoveCursor(registerBaseAddress, dataControlByte, rowNumber, columnNumber):
if (rowNumber == 1):
cursorByte = 0x80 | (0x00 + (columnNumber - 1)) # command = 0x80, row 1 DDRAM start address = 0x10
elif (rowNumber == 2):
cursorByte = 0x80 | (0x40 + (columnNumber - 1)) # row 2 DDRAM start address = 0x40
LcdWriteDataByteFourBitMode(registerBaseAddress, dataControlByte, cursorByte, InstructionRegister)
# charUpperNibble = cursorByte >> 4
# charLowerNibble = cursorByte & 0x0f
# dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, charUpperNibble, InstructionRegister, ShortOperationDelay)
# dataControlByte = LcdWriteDataNibble(registerBaseAddress, dataControlByte, charLowerNibble, InstructionRegister, ShortOperationDelay)
return dataControlByte
# * Test LCD1602 functions *
def TestLcd(registerBaseAddress):
LcdGpioSetup(registerBaseAddress)
dataControlByte = LcdConfiguration(registerBaseAddress)
dataControlByte = LcdMoveCursor(registerBaseAddress, dataControlByte, 1, 2)
dataControlByte = LcdWriteCharString(registerBaseAddress, dataControlByte, "Raspberry Pi")
dataControlByte = LcdMoveCursor(registerBaseAddress, dataControlByte, 2, 1)
dataControlByte = LcdWriteCharString(registerBaseAddress, dataControlByte, "2013-01-25 v1141")
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * MCP23017 LCD functions *
def Iox16LcdGpioSetup(registerBaseAddress):
# SetupMCP23008PortAllOutput(registerBaseAddress)
# registerBaseAddress = stateTuple[RegisterBaseAddressIndex]
registerBaseAddress = MCP23017BaseAddressSystemB1
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
def Iox16LcdConfiguration(registerBaseAddress):
dataControlByte = AllZeroDataByte
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
Iox16LcdDisableWrite(registerBaseAddress, dataControlByte)
time.sleep(PowerOnResetDelay)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, VeryLongOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte03 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte04 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, FourBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte05 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte06 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte07 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte08 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte09 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, ClearDisplay1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte10 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, ClearDisplay2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte11 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte12 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte13 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorHome1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte14 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, CursorHome2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte15 = ", dataControlByte)
return dataControlByte
def Iox16LcdSelectDataRegister(registerBaseAddress, dataByte):
dataByte = dataByte | SelectDataRegisterMask
Iox16LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def Iox16LcdSelectInstructionRegister(registerBaseAddress, dataByte):
dataByte = dataByte & SelectInstructionRegisterMask
Iox16LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def Iox16LcdEnableWrite(registerBaseAddress, dataByte):
dataByte = dataByte | EnableWriteMask
Iox16LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def Iox16LcdDisableWrite(registerBaseAddress, dataByte):
dataByte = dataByte & DisableWriteMask
Iox16LcdWriteDataByte(registerBaseAddress, dataByte)
return dataByte
def Iox16LcdWritePulse(registerBaseAddress, dataByte):
Iox16LcdEnableWrite(registerBaseAddress, dataByte)
time.sleep(WritePulseLength)
Iox16LcdDisableWrite(registerBaseAddress, dataByte)
return dataByte
def Iox16LcdWriteDataByte(registerBaseAddress, dataByte):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, dataByte)
return dataByte
def Iox16LcdWriteDataNibble(registerBaseAddress, dataByte, dataNibble, registerType, operationDelay):
dataNibble = dataNibble << 2
dataByte = dataByte & 0b11000011
dataByte = dataByte | dataNibble
if (registerType == InstructionRegister):
dataByte = Iox16LcdSelectInstructionRegister(registerBaseAddress, dataByte)
elif (registerType == DataRegister):
dataByte = Iox16LcdSelectDataRegister(registerBaseAddress, dataByte)
Iox16LcdDisableWrite(registerBaseAddress, dataByte)
dataByte = Iox16LcdWriteDataByte(registerBaseAddress, dataByte)
Iox16LcdWritePulse(registerBaseAddress, dataByte)
time.sleep(operationDelay)
return dataByte
def Iox16LcdWriteCharFourBitMode(registerBaseAddress, dataControlByte, asciiChar, registerType):
charUpperNibble = ord(asciiChar) >> 4
charLowerNibble = ord(asciiChar) & 0x0f
Iox16LcdWriteCharTwoNibbles(registerBaseAddress, dataControlByte, charUpperNibble, charLowerNibble, registerType)
return dataControlByte
def Iox16LcdWriteDataByteFourBitMode(registerBaseAddress, dataControlByte, dataByte, registerType):
upperNibble = dataByte >> 4
lowerNibble = dataByte & 0x0f
Iox16LcdWriteCharTwoNibbles(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType)
return dataControlByte
def Iox16LcdWriteCharTwoNibbles(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType):
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, upperNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, lowerNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
return dataControlByte
def Iox16LcdWriteCharString(registerBaseAddress, dataControlByte, string):
for asciiChar in (string):
Iox16LcdWriteCharFourBitMode(registerBaseAddress, dataControlByte, asciiChar, DataRegister)
return dataControlByte
def Iox16LcdMoveCursor(registerBaseAddress, dataControlByte, rowNumber, columnNumber):
if (rowNumber == 1):
cursorByte = 0x80 | (0x00 + (columnNumber - 1)) # command = 0x80, row 1 DDRAM start address = 0x10
elif (rowNumber == 2):
cursorByte = 0x80 | (0x40 + (columnNumber - 1)) # row 2 DDRAM start address = 0x40
Iox16LcdWriteDataByteFourBitMode(registerBaseAddress, dataControlByte, cursorByte, InstructionRegister)
# charUpperNibble = cursorByte >> 4
# charLowerNibble = cursorByte & 0x0f
# dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, charUpperNibble, InstructionRegister, ShortOperationDelay)
# dataControlByte = Iox16LcdWriteDataNibble(registerBaseAddress, dataControlByte, charLowerNibble, InstructionRegister, ShortOperationDelay)
return dataControlByte
# * Test LCD1602 functions *
def TestIox16Lcd(registerBaseAddress):
Iox16LcdGpioSetup(registerBaseAddress)
dataControlByte = Iox16LcdConfiguration(registerBaseAddress)
dataControlByte = Iox16LcdMoveCursor(registerBaseAddress, dataControlByte, 1, 1)
dataControlByte = Iox16LcdWriteCharString(registerBaseAddress, dataControlByte, "Raspberry Pi")
dataControlByte = Iox16LcdMoveCursor(registerBaseAddress, dataControlByte, 2, 1)
dataControlByte = Iox16LcdWriteCharString(registerBaseAddress, dataControlByte, "2013-02-11 v4.05")
# 8. Unipolar Stepping Motor 28BYJ48/NPM-PF35/PX245 ***************************
# Unipolar Stepping Motor Switching Sequence
# 1. Wave sequence = 1 - 3 - 2 - 4 (A-, B-, A+, B+)
# 2. Full step sequence = 13 - 14 - 24 - 23 (A-B-, A-B+, A+B+, A+B-)
# 3. Half step sequence = 13 - 1 - 14 - 4 - 24 - 2 - 23 - 3
# 4. One step swing = 1 - 3 - 1 - 3 (A-, B-, A-, B-)
# Winding A-(1) A+(2) B-(3) B+(4) COM
# NPM PF35 Black Yellow Brown Orange Red
# 28BYJ48 Pink Orange Blue Yellow Red
# PX245 Black Green Blue Red Yelow/White
# * Convert decimal pin number to hex *
def convert1PinToHex(p): # convert 1 of 8 high pin to hex
hexString = 0x01
for count in range(p-1):
hexString = hexString << 1
return hexString
def convert2PinToHex(p1, p2): # convert 2 of 8 high pins to hex
return (convert1PinToHex(p1) | convert1PinToHex(p2))
def convert2PinToHighNibble(p1, p2): # convert 2 of 8 high pins to high nibble
lowNibble = convert1PinToHex(p1) | convert1PinToHex(p2)
highNibble = lowNibble << 4
return highNibble
# * Move unipolar stepping motor *
def WriteMotorWindingWaveSequence1324(RegisterBaseAddress, NibbleType, StepCount, StepTime): # move motor using 13-24 sequence
# Set port all output
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
if NibbleType == LowNibble:
hexString1 = convert2PinToHex(1, 3)
hexString2 = convert2PinToHex(2, 4)
else:
hexString1 = convert2PinToHighNibble(1, 3)
hexString2 = convert2PinToHighNibble(2, 4)
for i in range(StepCount):
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, hexString1)
time.sleep(StepTime)
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, hexString2)
time.sleep(StepTime)
def WriteMotorWindingFullStepSequence13232414(RegisterBaseAddress, NibbleType, StepCount, StepTime): #move motor using 13-23-24-14 sequence
# Set port all output
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
if NibbleType == LowNibble:
motorWindingActivationPatternArray = (0x05, 0x06, 0x0a, 0x09)
else:
motorWindingActivationPatternArray = (0x50, 0x60, 0xa0, 0x90)
for i in range(StepCount):
for pattern in motorWindingActivationPatternArray:
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, pattern)
time.sleep(StepTime)
def TestConvert1PinToHex(): # test convert 1 high pin to hex
print "*** Testing 1 pin number decimal 0 ~ 7 converted to hexdecimal 0x01 ~ 0x80"
for d in range(8):
print hex(convert1PinToHex(d))
def TestConvert2PinToHex(p1, p2): # test convert 2 high pins to hex
print "*** Testing 2 pin numbers decimal 0 ~ 7 converted to hexdecimal"
print "Pin 1 = ", p1, "Pin 2 = ", p2
print "Hex = ", hex(convert2PinToHex(p1, p2))
def TestConvert2PinToHighNibble(p1, p2): # test convert 2 of 8 high pins to high nibble
print "*** Testing 2 pin numbers decimal 0 ~ 7 converted to high nibble"
print "Pin 1 = ", p1, "Pin 2 = ", p2
print "HighNibble = ", hex(convert2PinToHighNibble(p1, p2))
def MoveTwoMotors(RegisterBaseAddress):
OneBeep()
WriteMotorWindingWaveSequence1324(MCP23008BaseAddress1, LowNibble, TwentyTimes, FiftyMilliSeconds)
OneBeep()
WriteMotorWindingWaveSequence1324(MCP23008BaseAddress1, HighNibble, TwentyTimes, FiftyMilliSeconds)
OneBeep()
WriteMotorWindingFullStepSequence13232414(MCP23008BaseAddress1, LowNibble, TwentyTimes, OneHundredMilliSeconds)
OneBeep()
WriteMotorWindingFullStepSequence13232414(MCP23008BaseAddress1, HighNibble, TwentyTimes, OneHundredMilliSeconds)
def TestMotor():
MotorRegisterBaseAddress = MCP23008BaseAddress1
MoveTwoMotors(MotorRegisterBaseAddress)
def MoveUnipolarSteppingMotor(registerBaseAddress, NibbleType, StepCount, StepTime):
SetupMCP23017PortAoutputPortBinputPullUp(registerBaseAddress)
if NibbleType == LowNibble:
hexString1 = convert2PinToHex(1, 3)
hexString2 = convert2PinToHex(2, 4)
else:
hexString1 = convert2PinToHighNibble(1, 3)
hexString2 = convert2PinToHighNibble(2, 4)
for i in range(StepCount):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, hexString1)
time.sleep(StepTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, hexString2)
time.sleep(StepTime)
def TestMoveMotor():
registerBaseAddress = MCP23017BaseAddressSystemB1
nibbleType = LowNibble
stepCount = OneHundredTimes
stepTime = OneHundredMilliSeconds
MoveUnipolarSteppingMotor(registerBaseAddress, nibbleType, 500, 0.05)
# * Demultiplexer *************************************************************
DemuxRegisterBaseAddress = KeypadRegisterBaseAddress
def DemuxGpioSetup(registerBaseAddress):
UpperNibbleInputLowerNibbleOutput = 0xf0 # Input (GP4~7, Row0~3), Output (GP0~3, Column0~2, 3 reserved)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, UpperNibbleInputLowerNibbleOutput)
InitialControlDateByte = 0x00
return InitialControlDateByte
def DemuxAddressLatch(controlDataByte, latchAction):
DemuxAddressLatchMask = 0b00001000
Enable = 1
Disable = 0
if (latchAction == Enable):
controlDataByte = controlDataByte | DemuxAddressLatchMask
elif (latchAction == Disable):
controlDataByte = controlDataByte & ~(DemuxAddressLatchMask)
return controlDataByte
def SetDemuxChannel(registerBaseAddress, controlDataByte, addressNibble):
Enable = 1
Disable = 0
controlDataByte = controlDataByte & 0b11110000
addressNibble = addressNibble & 0b00000111
controlDataByte = controlDataByte | addressNibble
controlDataByte = DemuxAddressLatch(controlDataByte, Disable)
PrintEightBitPattern("demuxDataByte = ", controlDataByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, controlDataByte)
controlDataByte = DemuxAddressLatch(controlDataByte, Enable)
PrintEightBitPattern("demuxDataByte = ", controlDataByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, controlDataByte)
return controlDataByte
def TestDemux(demuxRegisterBaseAddress, channelNumber):
controlDataByte = DemuxGpioSetup(demuxRegisterBaseAddress)
controlDataByte = SetDemuxChannel(demuxRegisterBaseAddress, controlDataByte, channelNumber)
def TestDemuxLcd(demuxRegisterBaseAddress, lcdRegisterBaseAddress, channelNumber1, channelNumber2):
Row1 = 1
Row2 = 2
Row3 = 3
Row4 = 4
Column1 = 1
# Setup one MCP23008 for Demultiplexor, another MCP23008 for LCD1602/LCD2004
controlDataByte = DemuxGpioSetup(demuxRegisterBaseAddress)
LcdGpioSetup(lcdRegisterBaseAddress)
# Select demux channelNumber1
controlDataByte = SetDemuxChannel(demuxRegisterBaseAddress, controlDataByte, channelNumber1)
# Display two lines in the LCD at this channel
dataControlByte = LcdConfiguration(lcdRegisterBaseAddress)
dataControlByte = LcdMoveCursor(lcdRegisterBaseAddress, dataControlByte, Row1, Column1)
dataControlByte = LcdWriteCharString(lcdRegisterBaseAddress, dataControlByte, "Channel 1 01")
dataControlByte = LcdMoveCursor(lcdRegisterBaseAddress, dataControlByte, Row2, Column1)
dataControlByte = LcdWriteCharString(lcdRegisterBaseAddress, dataControlByte, "2013-01-28 v201")
time.sleep(2)
# Select demux channelNumber2
controlDataByte = SetDemuxChannel(demuxRegisterBaseAddress, controlDataByte, channelNumber2)
# Display two lines in the LCD at this channel
dataControlByte = LcdConfiguration(lcdRegisterBaseAddress)
dataControlByte = LcdMoveCursor(lcdRegisterBaseAddress, dataControlByte, Row1, Column1)
dataControlByte = LcdWriteCharString(lcdRegisterBaseAddress, dataControlByte, "Channel 2 01")
dataControlByte = LcdMoveCursor(lcdRegisterBaseAddress, dataControlByte, Row2, Column1)
dataControlByte = LcdWriteCharString(lcdRegisterBaseAddress, dataControlByte, "2013-01-30 v204")
time.sleep(2)
# 12. Old test functions *****************************************************
# * Old tests *
# RPi System A Tests *
# TestBuzzer() # beep buzzer 4 times
# TestLED() # blink LED 4 tmes
# TestButtonEchoBuzzer() # echo buton with buzzer 4 times
# TestButtonEchoLED() # echo button with LED 4 times
# TestToggleMCP23017GP() # toggle MCP23017 #1 output ports (connected to only 1 LED)
# TestToggleMCP23008GP() # toggle MCP23008 #1 output port (connected to stepping motors)
# TestMotor() # move two stepping motors
# TestPollingKeypad() # read 4 keys by polling IO Expander GPIO port of rows (MCP23008 #2)
# TestInterruptKeypad() # read 4 keys by polling IO Expander INT pin # !!! not tested !!!
# TestLcd(LcdRegisterBaseAddress)
# TestDemux(DemuxRegisterBaseAddress, 4)
# TestDemuxLcd(DemuxRegisterBaseAddress, LcdRegisterBaseAddress, channelNumber1 = 0, channelNumber2 = 1)
# RPi System B Tests *
# TestBuzzer() # beep buzzer 4 times
# TestLED() # blink LED 4 tmes
# TestButtonEchoBuzzer() # echo buton with buzzer 4 times
# TestButtonEchoLED() # echo button with LED 4 times
# TestToggleMCP23017SystemB1() # toggle MCP23017 System B1
# TestReadMCP23017SystemB1()
# * Rpi MCP23017 tests *
#TestButtonEchoBuzzer()
#TestTxDpin()
#TestRxDpin() # if set as output
#TestTxDpin()
#TestTxDpinRxDpin1()
#TestTxDpinRxDpin2()
#TestButtonEchoTxD()
#TestButtonEchoRxD()
# TestRxdEchoTxD() !!! not working !!!
# TestToggleMCP23017SystemB1(count = 4)
# TestReadMCP23017SystemB1(count = 4)
# TestKeypad017(checkPressingKeyMode = NoPollJustGetKeyEverySecond, keyCount = 4)
#TestKeypad017(checkPressingKeyMode = PollMCP23017Interrupt, keyCount = 4)
# TestKeypad017(checkPressingKeyMode = PollRowStatusNibble, keyCount = 4)
# 13. Main program ************************************************************
StartProgram()
#TestLED() # blink LED 4 tmes
#TestBuzzer() # beep buzzer 4 times
#TestButtonEchoBuzzer() # echo buton with buzzer 4 times
#TestButtonEchoLED() # echo button with LED 4 times
#TestToggleMCP23017SystemB1(count = 4)
#TestBlinkMCP23017SystemB1GPIObit(bitNumber = 3, onTime = 0.1, offTime = 0.3, count = 4)
#TestReadMCP23017SystemB1GPIObit(bitNumber = 4, count = 10)
#TestKeypad017(checkPressingKeyMode = PollRowStatusNibble, keyCount = 20)
#TestKeypad017(checkPressingKeyMode = PollMCP23017Interrupt, keyCount = 20)
#TestKeypad017(checkPressingKeyMode = PollRowStatusNibble, keyCount = 4)
#TestToggleMCP23017SystemB1(count = 4)
#TestBlinkMCP23017SystemB1GPIObit(bitNumber = 3, onTime = 0.1, offTime = 0.3, count = 4)
#TestMoveMotor()
TestIox16Lcd(MCP23017BaseAddressSystemB1)
StopProgram()
# *****************************************************************************
# End of Program
# *****************************************************************************
.END
No comments:
Post a Comment