Sunday, March 17, 2013
GZP spi xfer2 debugging notes
I did more and trials and errors and jumped to the following conclusion.
1. Using spidev_module.c - Python bindings for Linux SPI access through spidev, passing the list parameter by reference to the method spi.xfer2 causes problems only after passing the third time, perhaps because of buffer constraints.
2. Brute force getaround of opening and closing spi channel does not solve the problem.
def TestGuzuntyPiSteppingMotor():
PrintDoubleSpaceLine("*** Start testing Guzunty Pi Stepping Motor ***")
guzuntypiSpi = spidev.SpiDev()
guzuntypiSpi.open(0, 0)
Beep(2)
# !!! OK IF PASSING LIST BY VALUE !!!
for i in range(10):
guzuntypiSpi.xfer2([0x05, 0x00])
time.sleep(0.05)
guzuntypiSpi.xfer2([0x0a, 0x00])
time.sleep(0.05)
Beep(4)
# !!! NOT WORKING IF PASSING LIST BY REFERENCE !!!
# Winding13 = [0x05, 0x00]
# Winding24 = [0x0a, 0x00]
# for i in range(10):
# guzuntypiSpi.xfer2(Winding13)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding13) # !!! BUG !!! all windings on !!!
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# !!! NOT WORKING IF PASSING LIST BY REFERENCE !!!
# Winding13 = [0x05, 0x00]
# Winding24 = [0x0a, 0x00]
# for i in range(10):
# guzuntypiSpi.xfer2(Winding13)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# !!! NOT WORKING IF PASSING LIST BY REFERENCE !!!
# Winding13 = [0x05, 0x00]
# Winding24 = [0x0a, 0x00]
# for i in range(10):
# guzuntypiSpi.open(0, 0) # open close each loop
# guzuntypiSpi.xfer2(Winding13)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# guzuntypiSpi.close()
guzuntypiSpi.close()
PrintDoubleSpaceLine("*** Stop testing GuzuntyPi ***")
.END
# *****************************************************************************
# !/usr/bin/python2.7
#
# Hardware/Software
# FongLab Fp70 - 2013feb
# Author
# tlfong01 <http://tlfong01.blogspot.hk/>
# Configuration
# Raspberry Pi Bv2 512MB, Raspbian Wheezy, Python 2.7.3, RPI.GPIO 0.5.0a,
# PythonWiringPi 1.0.5, RPIO v0.8.4
# License
# GNU GPLv3
# Warranty
# For hobbist only. Use at your own risk. There is not any warranty.
# 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 ************************************************************
ProgramTitle1 = "GuzuntyPi Test01"
ProgramTitle2 = "FPL706 20130316b"
# ProgramTitle1 = "RPIO.PWM 2013"
# ProgramTitle2 = "Servo testing"
# ProgramTitle1 = "Guzunty Pi 2013"
# ProgramTitle2 = "XC9572XL M12"
# ProgramTitle1 = "SPI603 20130312a"
# ProgramTitle2 = "FPL603 20130312a"
# 2 Python imports ***********************************************************
import sys
import time
import select
# import RPi.GPIO as GPIO # Use RPi.GPIO
import RPIO as GPIO # Use RPIO
import smbus
import spidev
from RPIO import PWM
smBus1 = smbus.SMBus(1)
# GPIO.setmode(GPIO.BOARD) # Use Raspberry Pi P1 header pin numbering
GPIO.setmode(GPIO.BCM) # Use BMC GPIO channel number
# 3. GPIO and IO Expander pin/address assignments *****************************
I2cBaseAddress0 = 0x20
I2cBaseAddress1 = 0x21
I2cBaseAddress2 = 0x22
I2cBaseAddress3 = 0x23
I2cBaseAddress4 = 0x24
I2cBaseAddress5 = 0x25
I2cBaseAddress6 = 0x26
I2cBaseAddress7 = 0x27
# System A I2C base address assignment *
Mcp23017BaseAddress1 = 0x22 # LED, button
Mcp23008BaseAddress1 = 0x24 # stepping motors
Mcp23008BaseAddress2 = 0x25 # keypad
Mcp23008BaseAddress3 = 0x26 # LCD1602
# System B I2C base address assignment *
Mcp23017BaseAddressSystemB1 = 0x20
Mcp23008BaseAddressSystemB1 = 0x21
Mcp23008BaseAddressSystemB1 = 0x21
# * GPIO pin numbering *
# GPIO.setwarnings(False) # Disable linux's "pin already in use warning" !!! DO NOT DISABLE !!!
# * 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-13 RPi GPIO_GEN2 (BCM17) LED (P1-13 > LED > 330R > Gnd) !!! New
# P1-14 Gnd
# P1-20 Gnd
# P1-22 GPIO_GEN6 - Mcp23008 INT / Mcp23017 INTA
# P5-05 GPIO_GEN9 - Buzzer, 3V3 5mA (P5-05 > Buzzer > Gnd) !!! New
# P5-06 GPIO_GEN10 Button (3V3 > 10K > Contact 1/2 > 330R > Gnd) !!! New
# * BCM GPIO channel numbering *
RPiGPIOgen2 = 27 # (P1-13, BCM GPIO 27) Test LED
RPiGPIOgen9 = 30 # (P5-05, BCM GPIO 30) Buzzer
RPiGPIOgen10 = 31 # (P5-06, BCM GPIO 31) Button
LEDpin = RPiGPIOgen2
BuzzerPin = RPiGPIOgen9
ButtonPin = RPiGPIOgen10
RPiTxD = 14 # (P1-08, BCM GPIO 14) UART TxD
RPiRxD = 15 # (P1-10, BCM GPIO 15) UART RxD
TxdPin = RPiTxD
RxdPin = RPiRxD
RPiGPIOgen6 = 25 # (P1-22, BCM GPIO 25) IOx/keypad interrupt
RPiGPIOgen1 = 18 # (P1-12, BCM GPIO 18) PCM_CLK
RPiGPIOGclk = 04 # (P1-07, BCM GPIO 04) GPIO_GCLK
RPiPcm = RPiGPIOgen1
RPiGpclk0 = RPiGPIOGclk
# * I2C, SPI, JTAG,
RpiGpioSpiSelect0 = 7 # SPI_CE1_N (P1-26, BCM GPIO 7)
RpiGpioSpiSelect1 = 8 # SPI_CE0_N (P1-24, BCM GPIO 8)
RpiGpioSpiMiso = 9 # SPI_MISO (P1-21, BCM GPIO 9)
RpiGpioSpiMosi = 10 # SPI_MOSI (P1-10, BCM GPIO 10)
RpiGpioSpiClk = 11 # SPI_SCLK (P1-23, BCM GPIO 11)
SpiClockPin = RpiGpioSpiClk
SpiMosiPin = RpiGpioSpiMosi
SpiMisoPin = RpiGpioSpiMiso
SpiSelect0Pin = RpiGpioSpiSelect0
SpiSelect1Pin = RpiGpioSpiSelect1
RPiGPIOgen1 = 18 # PCM_CLK (P1-12, BCM GPIO 18) used
RPiGPIOGclk = 4 # GPIO_GCLK (P1-07, BCM GPIO 04) not used
RpiGpioGen0 = 17 # GPIO_GEN0 (P1-11, BCM GPIO 17, Alt Jtag TCK)
RpiGpioGen3 = 22 # GPIO_GEN0 (P1-15, BCM GPIO 22, Alt Jtag TDO)
RpiGpioGen4 = 23 # GPIO_GEN4 (P1-16, BCM GPIO 23, Alt Jtag TDI)
RpiGpioGen5 = 24 # GPIO_GEN5 (P1-18, BCM GPIO 24, Alt Jtag TMS)
JtagTckPin = RpiGpioGen0
JtagTdoPin = RpiGpioGen3
JtagTdiPin = RpiGpioGen4
JtagTmsPin = RpiGpioGen5
# * GPIO input/output pins list *
#OutputPinList = [LEDpin, BuzzerPin, TxdPin, SpiClockPin, SpiMosiPin, SpiSelect0Pin, SpiSelect1Pin]
#InputPinWithPullUpList = [ButtonPin, RxdPin, RPiGPIOgen6, SpiMisoPin]
OutputPinList = [LEDpin, BuzzerPin, TxdPin]
InputPinWithPullUpList = [ButtonPin, RxdPin, RPiGPIOgen6]
InputPinWithNoPullUpList = []
JtagOutputPinList = [JtagTckPin, JtagTdoPin, JtagTmsPin]
JtagInputPinList = [JtagTdiPin]
#JtagOutputPinList = [JtagTckPin, JtagTdoPin, JtagTmsPin, JtagTdiPin] # debug only
#JtagInputPinList = [] # debug only
# 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 )
def CleanUpGpio(): #
GPIO.cleanup()
def SetupJtagGpio():
SetupGPIOpins(outputPinList = JtagOutputPinList, inputPinWithNoPullUpList = JtagInputPinList, inputPinWithPullUpList = [])
def TestJtagGpio():
SetupGPIOpins(outputPinList = JtagOutputPinList, inputPinWithNoPullUpList = JtagInputPinList, 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 TestGpioPin(oPin, toggleTime, toggleCount):
for i in range(toggleCount):
togglePin(oPin, toggleTime)
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"
def TestJtagPins(toggleTime, testCount):
SetupJtagGpio()
Beep(1)
for i in range(testCount):
togglePin(JtagTckPin, toggleTime)
Beep(1)
for i in range(testCount):
togglePin(JtagTdoPin, toggleTime)
Beep(1)
for i in range(testCount):
togglePin(JtagTmsPin, toggleTime)
# Beep(1)
# for i in range(testCount):
# togglePin(JtagTdiPin, toggleTime)
# Beep(2)
# for i in range(testCount):
# if readInputPin(JtagTdiPin) == High:
# print "JtagTdiPin = High"
# else:
# print "JtagTdiPin = Low"
# for i in range(testCount):
# writeOutputPin(JtagTdoPin, On)
# if readInputPin(JtagTdiPin) == High:
# print "JtagTdiPin = High"
# else:
# print "JtagTdiPin = Low"
# time.sleep(1)
# writeOutputPin(JtagTdoPin, Off)
# if readInputPin(JtagTdiPin) == High:
# print "JtagTdiPin = High"
# else:
# print "JtagTdiPin = Low"
# time.sleep(1)
for i in range(testCount):
writeOutputPin(JtagTdoPin, 1)
if readInputPin(JtagTdiPin) == 1:
print "JtagTdiPin = 1"
else:
print "JtagTdiPin = 0"
time.sleep(1)
writeOutputPin(JtagTdoPin, 0)
if readInputPin(JtagTdiPin) == 1:
print "JtagTdiPin = 1"
else:
print "JtagTdiPin = 0"
time.sleep(1)
Beep(3)
GPIO.cleanup()
# 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 - " + ProgramTitle1 + " ***" + "\n"
CleanUpGpio()
SetupGPIO()
StartBeep()
print message
def StopProgram():
SetupGPIO()
StopBeep()
# print "\n" + "*** Resetting GPIO input, no pull up/down, no event detect. ***" + "\n"
CleanUpGpio()
print "\n" + "*** Stop Program ***" + "\n"
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# 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 *
Mcp23008RegisterAddressOffsetArray = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a]
RegisterAddressOffsetArrayBank0 = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x1d, 0x0f, 0x11, 0x13, 0x15]
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * Mcp23008 Functions *
def SetupPortAllOutputMcp23008(registerBaseAddress):
WriteDataByteMcp23008(registerBaseAddress, InputOutputDirection, AllOutputByte)
def SetupPortAllInputMcp23008(registerBaseAddress):
WriteDataByteMcp23008(registerBaseAddress, InputOutputDirection, AllInputByte)
def WriteDataByteMcp23008(registerBaseAddress, dataRegisterIndex, dataByte):
addressOffset = Mcp23008RegisterAddressOffsetArray[dataRegisterIndex]
smBus1.write_byte_data(registerBaseAddress, addressOffset, dataByte)
def ReadDataByteMcp23008(registerBaseAddress, dataRegisterIndex):
addressOffset = Mcp23008RegisterAddressOffsetArray[dataRegisterIndex]
dataByte = smBus1.read_byte_data(registerBaseAddress, addressOffset)
return dataByte
def WriteDataBitMcp23008(registerBaseAddress, dataRegisterIndex, bitNumber, dataBit):
addressOffset = Mcp23008RegisterAddressOffsetArray[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 ToggleGpMcp23008(registerBaseAddress, toggleTime, toggleCount):
SetupMcp23008PortAllOutput(registerBaseAddress)
for i in range(toggleCount):
WriteDataByteMcp23008(registerBaseAddress, OutputLatch, AllHighByte)
time.sleep(toggleTime)
WriteDataByteMcp23008(registerBaseAddress, OutputLatch, AllLowByte)
time.sleep(toggleTime)
def ReadGpMcp23008(registerBaseAddress, count):
SetupMcp23008PortAllInput(registerBaseAddress)
for i in range(count):
dataByte = ReadDataByteMcp23008(registerBaseAddress, PortStatus)
PrintEightBitPattern("Data byte read = ", dataByte)
time.sleep(1)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * Mcp23017 Functions *
def SetupMcp23017BothPortAllOutput(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortB, AllOutputByte)
def SetupPortAoutputPortBinputPullUpMcp23017(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortA, AllOutputByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InputOutputDirection, PortB, AllInputByte)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PullUp, PortB, AllPullUpByte)
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 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 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
SetupPortAoutputPortBinputPullUpMcp23017(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 TestToggleMcp23017PortAoutput(registerBaseAddress, toggleTime, toggleCount):
SetupPortAoutputPortBinputPullUpMcp23017(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 TestReadMcp23017SystemB1(count):
registerBaseAddress = Mcp23017BaseAddressSystemB1
SetupPortAoutputPortBinputPullUpMcp23017(registerBaseAddress)
for i in range(count):
dataByte = ReadDataByte(Mcp23017BaseAddressSystemB1, RegisterAddressOffsetArrayBank0, PortStatus, PortB)
PrintEightBitPattern("Data byte read = ", dataByte)
time.sleep(1)
def TestReadMcp23017PortBinput(registerBaseAddress, readTime, readCount):
SetupPortAoutputPortBinputPullUpMcp23017(registerBaseAddress)
for i in range(readCount):
dataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortB)
PrintEightBitPattern("MCP23x17 Port B data byte read = ", dataByte)
time.sleep(1)
def TestBlinkMcp23017SystemB1GPIObit(bitNumber, onTime, offTime, count) :
registerBaseAddress = Mcp23017BaseAddressSystemB1
SetupPortAoutputPortBinputPullUpMcp23017(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
SetupPortAoutputPortBinputPullUpMcp23017(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 v4.17 2013feb15 *
# * Configuration *
# Mcp23017 GPIO direction - Port A = output, Port B = input
# Keypad pin assignment - GPA0~A2 = Col0~2, GPB0~B3 = Row0~3
KeypadInterruptPinMcp23017 = RPiGPIOgen6
# * Local constants *
RegisterBaseAddress = 0x20
OutputLatchRegisterResetValue = 0x00
PortStatusRegisterResetValue = 0x00
InterruptCaptureRegisterResetValue = 0x00
InterruptFlagRegisterResetValue = 0x00
# * Polling modes *
NoPollJustGetKeyEverySecond = 0
PollRowStatusNibble = 1
PollMcp23017Interrupt = 2
# * Setup keypad *
def SetupKeypadMcp017(registerBaseAddress):
SetupPortAoutputPortBinputPullUpMcp23017(registerBaseAddress)
SetupKeypadInterruptMcp23017(registerBaseAddress) # buggy !!!!!!!!!!
ClearKeypadInterruptMcp23017(registerBaseAddress)
WriteKeypadColumnsAllLowMcp23017(registerBaseAddress)
# * Setup/Clear/Check keypad interrupt *
def SetupKeypadInterruptMcp23017(registerBaseAddress):
SetKeypadInterruptEnableMcp23017(registerBaseAddress)
SetKeypadDefaultValueMcp23017(registerBaseAddress)
SetKeypadEnableCompareDefaultValueMcp23017(registerBaseAddress)
SetKeypadBankInterruptDriverModeMcp23017(registerBaseAddress)
def SetKeypadInterruptEnableMcp23017(registerBaseAddress):
EnableInterruptLowNibble = 0x0f
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortB, EnableInterruptLowNibble)
def SetKeypadInterruptDisableMcp23017(registerBaseAddress):
DisableInterruptByte = 0x00
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortB, DisableInterruptByte)
def SetKeypadDefaultValueMcp23017(registerBaseAddress):
DefaultValueByte = 0x0f # row status nibble is all bits high if no key pressed
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, DefaultValue, PortB, DefaultValueByte)
def SetKeypadEnableCompareDefaultValueMcp23017(registerBaseAddress):
InterruptOnChangeDefaultValueLowNibble = 0x0f # GPB0~3 change from default value will cause interrupt
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, CompareMode, PortB, InterruptOnChangeDefaultValueLowNibble)
def SetKeypadBankInterruptDriverModeMcp23017(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 ClearKeypadInterruptMcp23017(registerBaseAddress):
WriteKeypadColumnsAllLowMcp23017(registerBaseAddress)
time.sleep(0.5)
dummyRead = ReadInterruptCaptureLowNibble(registerBaseAddress)
# * Write columns *
def WriteKeypadColumnsMcp23017(registerBaseAddress, columnDataByte):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, columnDataByte)
def WriteKeypadColumnsAllLowMcp23017(registerBaseAddress):
WriteKeypadColumnsMcp23017(registerBaseAddress, AllLowByte)
# * Read rows *
def GetKeypadRowDataNibbleMcp23017(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, PortStatus, PortB)
rowDataNibble = rowDataByte & 0x0f
return rowDataNibble
# * Get Row Number, Column Number, and Key Number *
def GetKeypadRowNumberMcp23017(registerBaseAddress):
RowDataNibbleTuple = 0b1110, 0b1101, 0b1011, 0b0111, 0b1111, 0b0000
rowDataNibble = GetKeypadRowDataNibbleMcp23017(registerBaseAddress)
# *** Begin debugging *****************************************************
PrintFourBitPattern("Row pattern = ", rowDataNibble)
rowNumber = RowDataNibbleTuple.index(rowDataNibble)
print ("Row number = ", rowNumber)
# *** End debugging *******************************************************
rowNumber = RowDataNibbleTuple.index(rowDataNibble)
return rowNumber
def GetKeypadColumnNumberMcp23017(registerBaseAddress):
ColumnNibbleTuple = 0b1110, 0b1101, 0b1011
NoKeyPressNibble = 0b1111
for columnNibble in (ColumnNibbleTuple):
WriteKeypadColumnsMcp23017(registerBaseAddress, columnNibble)
rowDataNibble = GetKeypadRowDataNibbleMcp23017(registerBaseAddress)
if rowDataNibble != NoKeyPressNibble:
break
columnNumber = ColumnNibbleTuple.index(columnNibble)
return columnNumber
def GetKeypadKeyNumberMcp23017(registerBaseAddress):
rowNumber = GetKeypadRowNumberMcp23017(registerBaseAddress)
columnNumber = GetKeypadColumnNumberMcp23017(registerBaseAddress)
keyNumber = (rowNumber * 3) + (columnNumber + 1)
return keyNumber
# * Get keys *
def GetKeypadKeyMcp23017(registerBaseAddress, checkPressingKeyMode):
if (checkPressingKeyMode == NoPollJustGetKeyEverySecond):
print "Read key every second"
time.sleep(1)
LoopUntilOneSecondEnded()
elif (checkPressingKeyMode == PollRowStatusNibble):
print "Polling Gpio"
LoopUntilKeypadRowDataNibbleChangeMcp23017(registerBaseAddress)
elif (checkPressingKeyMode == PollMcp23017Interrupt):
print "Polling Mcp23017 interrupt INTB"
LoopUntilKeypadInterruptPinMcp23017Active(registerBaseAddress)
keyNumber = GetKeypadKeyNumberMcp23017(registerBaseAddress)
return keyNumber
def GetKeypadKeySequenceMcp23017(registerBaseAddress, checkPressingKeyMode, count):
for i in range (count):
OneBeep()
keyNumber = GetKeypadKeyMcp23017(registerBaseAddress, checkPressingKeyMode)
print "Key", i + 1, " = ", keyNumber
time.sleep(0.25)
# * No polling, just read key at the end of each second *
def LoopUntilOneSecondEnded():
time.sleep(1)
# * Poll row status *
def LoopUntilKeypadRowDataNibbleChangeMcp23017(registerBaseAddress):
WriteKeypadColumnsMcp23017(registerBaseAddress, AllLowByte)
NoKeyPressedNibble = 0xf
rowDataNibble = NoKeyPressedNibble
while (rowDataNibble == NoKeyPressedNibble):
rowDataNibble = GetKeypadRowDataNibbleMcp23017(registerBaseAddress)
time.sleep(0.05) # debouncing time 50mS
# * Poll Mcp23017 interrupt pin *
def LoopUntilKeypadInterruptPinMcp23017Active(registerBaseAddress):
# Mcp23017 INTB shifted up to 5V) logical level, then connected to Mcp23017 GPB5
KeypadInterruptPinNumber = 5
ClearKeypadInterruptMcp23017(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 TestKeypadMcp23017(registerBaseAddress, checkPressingKeyMode, keyCount):
SetupKeypadMcp017(registerBaseAddress)
GetKeypadKeySequenceMcp23017(registerBaseAddress, checkPressingKeyMode, keyCount)
SetupKeypadMcp017(registerBaseAddress)
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
# * Decimal keypad using 2x Mcp23008 v4.19 2013feb17 *
RegisterBaseAddress1 = 0x21
RegisterBaseAddress1 = 0x22
# Mcp23008 #1 0x21 port = output, GP0~2 = Rows 0~2
# Mcp23008 #2 0x22 port = input, GP0~3 = Columns 0~3
KeypadInterruptPinMcp23008 = RPiGPIOgen6
# * Local constants *
OutputLatchRegisterResetValue = 0x00
PortStatusRegisterResetValue = 0x00
InterruptCaptureRegisterResetValue = 0x00
InterruptFlagRegisterResetValue = 0x00
# * Polling modes *
NoPollJustGetKeyEverySecond = 0
PollRowStatusNibble = 1
PollMcp23017Interrupt = 2
# * Setup keypad *
def SetupKeypadMcp23008(registerBaseAddress1, registerBaseAddress2):
SetupPortAllOutputMcp23008(registerBaseAddress1)
SetupPortAllInputMcp23008(registerBaseAddress2)
#SetupKeypadInterruptMcp23008(registerBaseAddress)
#ClearKeypadInterruptMcp23008(registerBaseAddress)
WriteKeypadColumnsAllLowMcp23008(registerBaseAddress1)
# * Setup/Clear/Check keypad interrupt *
#def SetupKeypadInterruptMcp23008(registerBaseAddress):
# SetKeypadInterruptEnableMcp23008(registerBaseAddress)
# SetKeypadDefaultValueMcp23008(registerBaseAddress)
# SetKeypadEnableCompareDefaultValueMcp23008(registerBaseAddress)
# SetKeypadBankInterruptDriverModeMcp23008(registerBaseAddress)
#def SetKeypadInterruptEnableMcp23008(registerBaseAddress):
# EnableInterruptLowNibble = 0x0f
# WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortB, EnableInterruptLowNibble)
#def SetKeypadInterruptDisableMcp23008(registerBaseAddress):
# DisableInterruptByte = 0x00
# WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, InterruptEnable, PortB, DisableInterruptByte)
#def SetKeypadDefaultValueMcp23008(registerBaseAddress):
# DefaultValueByte = 0x0f # row status nibble is all bits high if no key pressed
# WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, DefaultValue, PortB, DefaultValueByte)
#def SetKeypadEnableCompareDefaultValueMcp23008(registerBaseAddress):
# InterruptOnChangeDefaultValueLowNibble = 0x0f # GPB0~3 change from default value will cause interrupt
# WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, CompareMode, PortB, InterruptOnChangeDefaultValueLowNibble)
#def SetKeypadBankInterruptDriverModeMcp23008(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 ClearKeypadInterruptMcp23008(registerBaseAddress):
# WriteKeypadColumnsAllLowMcp23008(registerBaseAddress)
# time.sleep(0.5)
# dummyRead = ReadInterruptCaptureLowNibble(registerBaseAddress)
# * Write columns *
def WriteKeypadColumnsMcp23008(registerBaseAddress, columnDataByte):
WriteDataByteMcp23008(registerBaseAddress, OutputLatch, columnDataByte)
def WriteKeypadColumnsAllLowMcp23008(registerBaseAddress):
WriteKeypadColumnsMcp23008(registerBaseAddress, AllLowByte)
# * Read rows *
def GetKeypadRowDataNibbleMcp23008(registerBaseAddress):
rowDataByte = ReadDataByteMcp23008(registerBaseAddress, PortStatus)
rowDataNibble = rowDataByte & 0x0f
return rowDataNibble
# * Get Row Number, Column Number, and Key Number *
def GetKeypadRowNumberMcp23008(registerBaseAddress):
RowDataNibbleTuple = 0b1110, 0b1101, 0b1011, 0b0111, 0b1111, 0b0000
rowDataNibble = GetKeypadRowDataNibbleMcp23008(registerBaseAddress)
# *** Begin debugging *****************************************************
PrintFourBitPattern("Row pattern = ", rowDataNibble)
rowNumber = RowDataNibbleTuple.index(rowDataNibble)
print ("Row number = ", rowNumber)
# *** End debugging *******************************************************
rowNumber = RowDataNibbleTuple.index(rowDataNibble)
return rowNumber
def GetKeypadColumnNumberMcp23008(registerBaseAddress1, registerBaseAddress2):
ColumnNibbleTuple = 0b1110, 0b1101, 0b1011
NoKeyPressNibble = 0b1111
for columnNibble in (ColumnNibbleTuple):
WriteKeypadColumnsMcp23008(registerBaseAddress1, columnNibble)
rowDataNibble = GetKeypadRowDataNibbleMcp23008(registerBaseAddress2)
if rowDataNibble != NoKeyPressNibble:
break
columnNumber = ColumnNibbleTuple.index(columnNibble)
return columnNumber
def GetKeypadKeyNumberMcp23008(registerBaseAddress1, registerBaseAddress2):
rowNumber = GetKeypadRowNumberMcp23008(registerBaseAddress2)
columnNumber = GetKeypadColumnNumberMcp23008(registerBaseAddress1, registerBaseAddress2)
keyNumber = (rowNumber * 3) + (columnNumber + 1)
return keyNumber
# * Get keys *
def GetKeypadKeyMcp23008(registerBaseAddress1, registerBaseAddress2, checkPressingKeyMode):
if (checkPressingKeyMode == NoPollJustGetKeyEverySecond):
print "Read key every second"
time.sleep(1)
LoopUntilOneSecondEnded()
elif (checkPressingKeyMode == PollRowStatusNibble):
print "Polling Gpio"
LoopUntilKeypadRowDataNibbleChangeMcp23008(registerBaseAddress1, registerBaseAddress2)
elif (checkPressingKeyMode == PollMcp23017Interrupt):
print "Polling Mcp23017 interrupt INTB"
LoopUntilKeypadInterruptPinMcp23008Active(registerBaseAddress2)
keyNumber = GetKeypadKeyNumberMcp23008(registerBaseAddress1, registerBaseAddress2)
return keyNumber
def GetKeypadKeySequenceMcp23008(registerBaseAddress1, registerBaseAddress2, checkPressingKeyMode, count):
for i in range (count):
OneBeep()
keyNumber = GetKeypadKeyMcp23008(registerBaseAddress1, registerBaseAddress2, checkPressingKeyMode)
print "Key", i + 1, " = ", keyNumber
time.sleep(0.25)
# * No polling, just read key at the end of each second *
def LoopUntilOneSecondEnded():
time.sleep(1)
# * Poll row status *
def LoopUntilKeypadRowDataNibbleChangeMcp23008(registerBaseAddress1, registerBaseAddress2):
WriteKeypadColumnsMcp23008(registerBaseAddress1, AllLowByte)
NoKeyPressedNibble = 0xf
rowDataNibble = NoKeyPressedNibble
while (rowDataNibble == NoKeyPressedNibble):
rowDataNibble = GetKeypadRowDataNibbleMcp23008(registerBaseAddress2)
time.sleep(0.05) # debouncing time 50mS
# * Poll interrupt pin *
def LoopUntilKeypadInterruptPinMcp23008Active(registerBaseAddress):
# 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 Decimal keypad Mcp23008 *
def TestKeypadMcp23008(registerBaseAddress1, registerBaseAddress2, checkPressingKeyMode, keyCount):
SetupKeypadMcp23008(registerBaseAddress1, registerBaseAddress2)
GetKeypadKeySequenceMcp23008(registerBaseAddress1, registerBaseAddress2, checkPressingKeyMode, keyCount)
SetupKeypadMcp23008(registerBaseAddress1, registerBaseAddress2)
def TestKeypadMcp23017PollingMode(i2cRegisterBaseAddress):
TestKeypadMcp23017(i2cRegisterBaseAddress, checkPressingKeyMode = PollRowStatusNibble, keyCount = 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
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * LCD functions Mcp23008 v4.15 2013feb15 *
def LcdGpioSetupMcp23008(registerBaseAddress):
SetupPortAllOutputMcp23008(registerBaseAddress)
def LcdConfigurationMcp23008(registerBaseAddress):
dataControlByte = AllZeroDataByte
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
LcdDisableWriteMcp23008(registerBaseAddress, dataControlByte)
time.sleep(PowerOnResetDelay)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, VeryLongOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte03 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte04 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, FourBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte05 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte06 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte07 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte08 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte09 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, ClearDisplay1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte10 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, ClearDisplay2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte11 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte12 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte13 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, CursorHome1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte14 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, CursorHome2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte15 = ", dataControlByte)
return dataControlByte
def LcdSelectDataRegisterMcp23008(registerBaseAddress, dataByte):
dataByte = dataByte | SelectDataRegisterMask
LcdWriteDataByteMcp23008(registerBaseAddress, dataByte)
return dataByte
def LcdSelectInstructionRegisterMcp23008(registerBaseAddress, dataByte):
dataByte = dataByte & SelectInstructionRegisterMask
LcdWriteDataByteMcp23008(registerBaseAddress, dataByte)
return dataByte
def LcdEnableWriteMcp23008(registerBaseAddress, dataByte):
dataByte = dataByte | EnableWriteMask
LcdWriteDataByteMcp23008(registerBaseAddress, dataByte)
return dataByte
def LcdDisableWriteMcp23008(registerBaseAddress, dataByte):
dataByte = dataByte & DisableWriteMask
LcdWriteDataByteMcp23008(registerBaseAddress, dataByte)
return dataByte
def LcdWritePulseMcp23008(registerBaseAddress, dataByte):
LcdEnableWriteMcp23008(registerBaseAddress, dataByte)
time.sleep(WritePulseLength)
LcdDisableWriteMcp23008(registerBaseAddress, dataByte)
return dataByte
def LcdWriteDataByteMcp23008(registerBaseAddress, dataByte):
WriteDataByteMcp23008(registerBaseAddress, OutputLatch, dataByte)
return dataByte
def LcdWriteDataNibbleMcp23008(registerBaseAddress, dataByte, dataNibble, registerType, operationDelay):
dataNibble = dataNibble << 2
dataByte = dataByte & 0b11000011
dataByte = dataByte | dataNibble
if (registerType == InstructionRegister):
dataByte = LcdSelectInstructionRegisterMcp23008(registerBaseAddress, dataByte)
elif (registerType == DataRegister):
dataByte = LcdSelectDataRegisterMcp23008(registerBaseAddress, dataByte)
LcdDisableWriteMcp23008(registerBaseAddress, dataByte)
dataByte = LcdWriteDataByteMcp23008(registerBaseAddress, dataByte)
LcdWritePulseMcp23008(registerBaseAddress, dataByte)
time.sleep(operationDelay)
return dataByte
def LcdWriteCharFourBitModeMcp23008(registerBaseAddress, dataControlByte, asciiChar, registerType):
charUpperNibble = ord(asciiChar) >> 4
charLowerNibble = ord(asciiChar) & 0x0f
LcdWriteCharTwoNibblesMcp23008(registerBaseAddress, dataControlByte, charUpperNibble, charLowerNibble, registerType)
return dataControlByte
def LcdWriteDataByteFourBitModeMcp23008(registerBaseAddress, dataControlByte, dataByte, registerType):
upperNibble = dataByte >> 4
lowerNibble = dataByte & 0x0f
LcdWriteCharTwoNibblesMcp23008(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType)
return dataControlByte
def LcdWriteCharTwoNibblesMcp23008(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType):
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, upperNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23008(registerBaseAddress, dataControlByte, lowerNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
return dataControlByte
def LcdWriteCharStringMcp23008(registerBaseAddress, dataControlByte, string):
for asciiChar in (string):
LcdWriteCharFourBitModeMcp23008(registerBaseAddress, dataControlByte, asciiChar, DataRegister)
return dataControlByte
def LcdMoveCursorMcp23008(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
LcdWriteDataByteFourBitModeMcp23008(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 Mcp23008 *
def TestLcdMcp23008(registerBaseAddress):
LcdGpioSetupMcp23008(registerBaseAddress)
dataControlByte = LcdConfigurationMcp23008(registerBaseAddress)
dataControlByte = LcdMoveCursorMcp23008(registerBaseAddress, dataControlByte, 1, 1)
dataControlByte = LcdWriteCharStringMcp23008(registerBaseAddress, dataControlByte, ProgramTitle1)
dataControlByte = LcdMoveCursorMcp23008(registerBaseAddress, dataControlByte, 2, 1)
dataControlByte = LcdWriteCharStringMcp23008(registerBaseAddress, dataControlByte, ProgramTitle2)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * LCD functions Mcp23017 v4.15 2013feb15 *
def LcdGpioSetupMcp23017(registerBaseAddress):
#registerBaseAddress = Mcp23017BaseAddressSystemB1
SetupPortAoutputPortBinputPullUpMcp23017(registerBaseAddress)
def LcdConfigurationMcp23017(registerBaseAddress):
dataControlByte = AllZeroDataByte
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
LcdDisableWriteMcp23017(registerBaseAddress, dataControlByte)
time.sleep(PowerOnResetDelay)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, VeryLongOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte03 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, EightBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte04 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, FourBitInstructionMode, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte05 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte06 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, TwoLineFiveTimesEightDot2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte07 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte08 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, DisplayOnCursorOnCursorBlinkOff2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte09 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, ClearDisplay1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte10 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, ClearDisplay2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte11 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte12 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, CursorIncrementDisplayNoShift2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte13 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, CursorHome1, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte14 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, CursorHome2, InstructionRegister, LongOperationDelay)
# PrintEightBitPattern("dataControlByte15 = ", dataControlByte)
return dataControlByte
def LcdSelectDataRegisterMcp23017(registerBaseAddress, dataByte):
dataByte = dataByte | SelectDataRegisterMask
LcdWriteDataByteMcp23017(registerBaseAddress, dataByte)
return dataByte
def LcdSelectInstructionRegisterMcp23017(registerBaseAddress, dataByte):
dataByte = dataByte & SelectInstructionRegisterMask
LcdWriteDataByteMcp23017(registerBaseAddress, dataByte)
return dataByte
def LcdEnableWriteMcp23017(registerBaseAddress, dataByte):
dataByte = dataByte | EnableWriteMask
LcdWriteDataByteMcp23017(registerBaseAddress, dataByte)
return dataByte
def LcdDisableWriteMcp23017(registerBaseAddress, dataByte):
dataByte = dataByte & DisableWriteMask
LcdWriteDataByteMcp23017(registerBaseAddress, dataByte)
return dataByte
def LcdWritePulseMcp23017(registerBaseAddress, dataByte):
LcdEnableWriteMcp23017(registerBaseAddress, dataByte)
time.sleep(WritePulseLength)
LcdDisableWriteMcp23017(registerBaseAddress, dataByte)
return dataByte
def LcdWriteDataByteMcp23017(registerBaseAddress, dataByte):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArrayBank0, OutputLatch, PortA, dataByte)
return dataByte
def LcdWriteDataNibbleMcp23017(registerBaseAddress, dataByte, dataNibble, registerType, operationDelay):
dataNibble = dataNibble << 2
dataByte = dataByte & 0b11000011
dataByte = dataByte | dataNibble
if (registerType == InstructionRegister):
dataByte = LcdSelectInstructionRegisterMcp23017(registerBaseAddress, dataByte)
elif (registerType == DataRegister):
dataByte = LcdSelectDataRegisterMcp23017(registerBaseAddress, dataByte)
LcdDisableWriteMcp23017(registerBaseAddress, dataByte)
dataByte = LcdWriteDataByteMcp23017(registerBaseAddress, dataByte)
LcdWritePulseMcp23017(registerBaseAddress, dataByte)
time.sleep(operationDelay)
return dataByte
def LcdWriteCharFourBitModeMcp23017(registerBaseAddress, dataControlByte, asciiChar, registerType):
charUpperNibble = ord(asciiChar) >> 4
charLowerNibble = ord(asciiChar) & 0x0f
LcdWriteCharTwoNibblesMcp23017(registerBaseAddress, dataControlByte, charUpperNibble, charLowerNibble, registerType)
return dataControlByte
def LcdWriteDataByteFourBitModeMcp23017(registerBaseAddress, dataControlByte, dataByte, registerType):
upperNibble = dataByte >> 4
lowerNibble = dataByte & 0x0f
LcdWriteCharTwoNibblesMcp23017(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType)
return dataControlByte
def LcdWriteCharTwoNibblesMcp23017(registerBaseAddress, dataControlByte, upperNibble, lowerNibble, registerType):
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, upperNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte01 = ", dataControlByte)
dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, lowerNibble, registerType, ShortOperationDelay)
# PrintEightBitPattern("dataControlByte02 = ", dataControlByte)
return dataControlByte
def LcdWriteCharStringMcp23017(registerBaseAddress, dataControlByte, string):
for asciiChar in (string):
LcdWriteCharFourBitModeMcp23017(registerBaseAddress, dataControlByte, asciiChar, DataRegister)
return dataControlByte
def LcdMoveCursorMcp23017(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
LcdWriteDataByteFourBitModeMcp23017(registerBaseAddress, dataControlByte, cursorByte, InstructionRegister)
# charUpperNibble = cursorByte >> 4
# charLowerNibble = cursorByte & 0x0f
# dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, charUpperNibble, InstructionRegister, ShortOperationDelay)
# dataControlByte = LcdWriteDataNibbleMcp23017(registerBaseAddress, dataControlByte, charLowerNibble, InstructionRegister, ShortOperationDelay)
return dataControlByte
# * Test LCD1602 functions *
def TestLcdMcp23017(i2cRegisterBaseAddress):
LcdGpioSetupMcp23017(i2cRegisterBaseAddress)
dataControlByte = LcdConfigurationMcp23017(i2cRegisterBaseAddress)
dataControlByte = LcdMoveCursorMcp23017(i2cRegisterBaseAddress, dataControlByte, 1, 1)
dataControlByte = LcdWriteCharStringMcp23017(i2cRegisterBaseAddress, dataControlByte, ProgramTitle1)
dataControlByte = LcdMoveCursorMcp23017(i2cRegisterBaseAddress, dataControlByte, 2, 1)
dataControlByte = LcdWriteCharStringMcp23017(i2cRegisterBaseAddress, dataControlByte, ProgramTitle2)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# 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):
SetupPortAoutputPortBinputPullUpMcp23017(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 = 0x20
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)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * SPI using bit banging *
# SpiClockPin = RPiGpioGen11
# SpiMosiPin = RPiGpioGen10
# SpiMisoPin = RPiGpioGen9
# SpiSelect0Pin = RPiGpioGen8
# SpiSelect1Pin = RPiGpioGen7
def TestRfm12b(registerBaseAddress):
SetupGPIOpins(OutputPinList, InputPinWithNoPullUpList, InputPinWithPullUpList )
def SpiSelectDevice(deviceNumber):
if (deviceNumber == 0):
writeOutputPin(SpiSelect0Pin, Low)
else:
writeOutputPin(SpiSelect1Pin, Low)
def SpiDisSelectDevice(deviceNumber):
if (deviceNumber == 0):
writeOutputPin(SpiSelect0Pin, High)
else:
writeOutputPin(SpiSelect1Pin, High)
def SpiClockPulse():
writeOutputPin(SpiClockPin, High)
time.sleep(1)
writeOutputPin(SpiClockPin, Low)
time.sleep(1)
def SpiWriteBit(dataBit):
if (dataBit == 1):
writeOutputPin(SpiMosiPin, High)
else:
writeOutputPin(SpiMosiPin, Low)
def SpiReadBit(inputPin):
dataBit = readInputPin(inputPin)
# print dataBit
return dataBit
# * Test Spi functions *
def TestSpiSelectDevice(deviceNumber, count):
print "Now testing SPI device select pin", deviceNumber, ",..."
for i in range (count):
SpiSelectDevice(deviceNumber)
time.sleep(1)
SpiDisSelectDevice(deviceNumber)
time.sleep(1)
def TestSpiClockPulse(count):
for i in range (count):
SpiClockPulse()
def TestSpiWriteBit(count):
for i in range (count):
SpiWriteBit(1)
time.sleep(1)
SpiWriteBit(0)
time.sleep(1)
def TestSpiReadBit(inputPin, count):
for i in range (count):
dataBit = SpiReadBit(inputPin)
if (dataBit == True):
dataLevel = "High"
else:
dataLevel = "Low"
print "dataBitRead at pin number ", inputPin, " = ", dataLevel
time.sleep(1)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * SPI using wiringPi with Python wrapping 2013feb22 *
def TestWiringPiSpi():
print "\n" + "*** Start testing wiringPi SPI, ... ***" + "\n"
spi = spidev.SpiDev() # create spidev object
spi.open(0,0) # open SPI0, CE0_N
SendByteList = [0x55, 0xaa, 0xAA]
ReadByteList = spi.xfer2(SendByteList)
print "Bytes read = " + hex(ReadByteList[0]) + " " + hex(ReadByteList[1]) + " " + hex(ReadByteList[2])
print "\n" + "*** Stop testing wiringPi SPI, ... ***" + "\n"
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * RFM12b 434Mhz Wireless Transceiver testing v1.0 tlfong01 2013feb23 *
# * Arduino C++ functions *
# define wkupOn 0x820E // turn on wake up timer (also xtl, lvd)
# define wkupOff 0x820C // turn off wake up timer (xtl, lvd still on)
# define wkup2ms 0XE002 // wake up every 2mS
# define config01 0x80D7
# define power01 0x8239
# define freq01 0xA640
# define drate01 0xC647
# define rxctrl01 0x94A0
# define fifors01 0xCA81
# define syncpt01 0xCED4
# define afc01 0xC483
# define txctrl01 0x9850
# define pll01 0xCC77
# define wkup01 0xE000
# define ldc01 0xC800
# define lbdclk01 0xC400
# define lvdOn 0x820C // turn on low voltage detection (also xtal, mcu clk)
# define lvd27 0xC064 // set low voltage threshold 2.7V (2.2 + 0.1 * 4) 2MHz,
# define status 0x0000 // read status to execute command and clear interrupt
#void RFM12B01::setupRfm12b()
# {
# putWord(0x80D7); //enable tx, rx fifo, 433MHz, 12.0pF
# // putWord(0x8239); //enable xmitt, syn, xtal, disable clk
# putWord(0xA640); //operation frequency ???
# putWord(0xC647); //data rate 4.8kbps
# putWord(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
# putWord(0xC2AC); //clk rec auto, digi fltr,DQD4
# putWord(0xCA81); //fifo8,sync 1, sync, no fifo fill
# putWord(0xCED4); //sync pattern d4
# putWord(0xC483); //offset VDI hi, no restrict, afc, afc out
# putWord(0x9850); //90kHz, max o/p pwr (odBm)
# putWord(0xCC17); //10MHz, 620uA, disable pll dit, 256kbps
# putWord(0xE000); //wake up timer not used
# putWord(0xC800); //low duty cycle not used
# putWord(0xC040); //1.66MHz,2.2V low battery
# }
#void RFM12B01::testSetupClock2Mhz()
# {
# putWord(0xC064);
# }
def PrintDoubleSpaceLine(line):
print "\n" + line + "\n"
def WaitSeconds(count):
time.sleep(count)
# * Rfm12b 2 byte commands *
SetExternalMpuClockFrequency1Mhz = [0xc0, 0x04] # 1 MHz, 2.7V (2.2 + 0.1 * 4)
SetExternalMpuClockFrequency2Mhz = [0xc0, 0x64] # 2 MHz, 2.7V (2.2 + 0.1 * 4)
SetExternalMpuClockFrequency5Mhz = [0xc0, 0xc4] # 5 MHz, 2.7V (2.2 + 0.1 * 4)
SetExternalMpuClockFrequency10Mhz = [0xc0, 0xe4] # 10 MHz, 2.7V (2.2 + 0.1 * 4)
EnableWakeupTimerEnableXtlLvd = [0x82, 0x0e]
DisableWakeupTimerEnableXtlLvd = [0x82, 0x0c]
SetWakeUpTimer2Ms = [0xe0, 0x02]
ClearInterrupt = [0x00, 0x00]
def TestRfm12bSet2Mhz():
PrintDoubleSpaceLine("*** Start testing RFM12B 2 MHz ***")
rfm12bSpi = spidev.SpiDev() # create spi object to entertain RFM12B
rfm12bSpi.open(0,0) # open sci channel 0 and select slave device 0
ExternalMpuClockFrequency2Mhz = [0xC0, 0x64]
receiveByteList = rfm12bSpi.xfer2(ExternalMpuClockFrequency2Mhz)
print "Bytes read = " + hex(receiveByteList[0]) + " " + hex(receiveByteList[1])
PrintDoubleSpaceLine("*** Stop testing RFM12B ***")
def TestRfm12bSet1Mhz():
PrintDoubleSpaceLine("*** Start testing RFM12B 1 MHz ***")
rfm12bSpi = spidev.SpiDev() # create spi object to entertain RFM12B
rfm12bSpi.open(0,0) # open sci channel 0 and select slave device 0
ExternalMpuClockFrequency2Mhz = [0xc0, 0x04]
receiveByteList = rfm12bSpi.xfer2(ExternalMpuClockFrequency2Mhz)
print "Bytes read = " + hex(receiveByteList[0]) + " " + hex(receiveByteList[1])
PrintDoubleSpaceLine("*** Stop testing RFM12B ***")
def OpenSpiChannel(spiObject, spiChannelNumber, spiDeviceNumber):
spiObject.open(spiChannelNumber, spiDeviceNumber)
def Rfm12bSendCommand1(spiChannelNumber, spiDeviceNumber, sendByteList):
rfm12bSpi = spidev.SpiDev()
rfm12bSpi.open(spiChannelNumber, spiDeviceNumber)
receiveByteList = rfm12bSpi.xfer2(sendByteList)
def Rfm12bSendCommand2(rfm12bSpi, sendByteList):
receiveByteList = rfm12bSpi.xfer2(sendByteList)
def Rfm12bTest1(spiChannelNumber, spiDeviceNumber):
PrintDoubleSpaceLine("*** Start Test 1 ***")
rfm12bSpi = spidev.SpiDev() # create spi object to entertain RFM12B
rfm12bSpi.open(0,0) # open sci channel 0 and select slave device 0
Rfm12bSendCommand1(spiChannelNumber, spiDeviceNumber, SetExternalMpuClockFrequency2Mhz)
WaitSeconds(2)
Rfm12bSendCommand1(spiChannelNumber, spiDeviceNumber, SetExternalMpuClockFrequency5Mhz)
WaitSeconds(2)
Rfm12bSendCommand1(spiChannelNumber, spiDeviceNumber, SetExternalMpuClockFrequency10Mhz)
WaitSeconds(2)
Rfm12bSendCommand1(spiChannelNumber, spiDeviceNumber, SetExternalMpuClockFrequency1Mhz)
WaitSeconds(2)
PrintDoubleSpaceLine("*** Stop Test 1 ***")
def Rfm12bTest2(spiChannelNumber, spiDeviceNumber):
PrintDoubleSpaceLine("*** Start Test 2 ***")
rfm12bSpi = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi, spiChannelNumber, spiDeviceNumber)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency2Mhz)
WaitSeconds(2)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency5Mhz)
WaitSeconds(2)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency10Mhz)
WaitSeconds(2)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency1Mhz)
WaitSeconds(2)
PrintDoubleSpaceLine("*** Stop Test 2 ***")
def Rfm12bTest3a(spiChannelNumber, spiDeviceNumber):
PrintDoubleSpaceLine("*** Start Test 3a ***")
rfm12bSpi = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi, spiChannelNumber, spiDeviceNumber)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency2Mhz)
WaitSeconds(2)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency5Mhz)
WaitSeconds(2)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency1Mhz)
WaitSeconds(2)
Rfm12bSendCommand2(rfm12bSpi, TurnOnWakeupXtlLvd)
Rfm12bSendCommand2(rfm12bSpi, WakeUpEvery2Ms)
# WaitSeconds(2)
# Rfm12bSendCommand2(rfm12bSpi, TurnOffWakeupTurnOnXtlLvd)
PrintDoubleSpaceLine("*** Stop Test 3a ***")
def Rfm12bTest3b(spiChannelNumber, spiDeviceNumber):
PrintDoubleSpaceLine("*** Start Test 3b 2013feb2601 ***")
rfm12bSpi = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi, spiChannelNumber, spiDeviceNumber)
Rfm12bSendCommand2(rfm12bSpi, SetExternalMpuClockFrequency2Mhz)
Rfm12bSendCommand2(rfm12bSpi, TurnOnWakeupXtlLvd)
for i in range (100000):
Rfm12bSendCommand2(rfm12bSpi, WakeUpEvery2Ms)
time.sleep(0.005)
Rfm12bSendCommand2(rfm12bSpi, ClearInterrupt)
time.sleep(0.010)
Rfm12bSendCommand2(rfm12bSpi, TurnOffWakeupTurnOnXtlLvd)
PrintDoubleSpaceLine("*** Stop Test 3b ***")
def Rfm12bTest3c(spiChannelNumber, spiDeviceNumber0, spiDeviceNumber1):
PrintDoubleSpaceLine("*** Start Test 3c 2013feb2602 ***")
rfm12bSpi00 = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi00, spiChannelNumber, spiDeviceNumber0)
Rfm12bSendCommand2(rfm12bSpi00, SetExternalMpuClockFrequency5Mhz)
rfm12bSpi01 = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi01, spiChannelNumber, spiDeviceNumber1)
Rfm12bSendCommand2(rfm12bSpi01, SetExternalMpuClockFrequency10Mhz)
PrintDoubleSpaceLine("*** Stop Test 3c ***")
def Rfm12bTest3d(spiChannelNumber, spiDeviceNumber0, spiDeviceNumber1):
PrintDoubleSpaceLine("*** Start Test 3d 2013feb2603 ***")
rfm12bSpi00 = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi00, spiChannelNumber, spiDeviceNumber0)
Rfm12bSendCommand2(rfm12bSpi00, SetExternalMpuClockFrequency2Mhz)
rfm12bSpi01 = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi01, spiChannelNumber, spiDeviceNumber1)
Rfm12bSendCommand2(rfm12bSpi01, SetExternalMpuClockFrequency5Mhz)
for i in range(4):
Beep(1)
Rfm12bSendCommand2(rfm12bSpi00, DisableWakeupTimerEnableXtlLvd)
Rfm12bSendCommand2(rfm12bSpi00, ClearInterrupt)
time.sleep(2)
Beep(2)
Rfm12bSendCommand2(rfm12bSpi00, EnableWakeupTimerEnableXtlLvd)
Rfm12bSendCommand2(rfm12bSpi00, SetWakeUpTimer2Ms)
time.sleep(2)
Beep(3)
Rfm12bSendCommand2(rfm12bSpi01, DisableWakeupTimerEnableXtlLvd)
Rfm12bSendCommand2(rfm12bSpi01, ClearInterrupt)
time.sleep(2)
Beep(4)
Rfm12bSendCommand2(rfm12bSpi01, EnableWakeupTimerEnableXtlLvd)
Rfm12bSendCommand2(rfm12bSpi01, SetWakeUpTimer2Ms)
time.sleep(2)
PrintDoubleSpaceLine("*** Stop Test 3d ***")
def TestRfm12bExtMpuClock(spiChannelNumber, Rfm12bSpiDeviceNumber0, Rfm12bSpiDeviceNumber1):
PrintDoubleSpaceLine("*** Start RFM12B Test ***")
rfm12bSpi00 = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi00, spiChannelNumber, Rfm12bSpiDeviceNumber0)
Rfm12bSendCommand2(rfm12bSpi00, SetExternalMpuClockFrequency5Mhz)
rfm12bSpi01 = spidev.SpiDev()
OpenSpiChannel(rfm12bSpi01, spiChannelNumber, Rfm12bSpiDeviceNumber1)
Rfm12bSendCommand2(rfm12bSpi01, SetExternalMpuClockFrequency2Mhz)
PrintDoubleSpaceLine("*** Stop Test ***")
def TestDualRfm12bExtMpuClock(spiChannelNumber):
TestRfm12bExtMpuClock(spiChannelNumber, Rfm12bSpiDeviceNumber0 = 0, Rfm12bSpiDeviceNumber1 = 1)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * Test RPIO.PWM v1.0 tlfong01 2013mar13 *
# RPIO.PWM, PWM via DMA for the Raspberry Pi
# http://pythonhosted.org/RPIO/pwm_py.html
# PCA9685 16-channel, 12-bit PWM Fm+ I2 C-bus LED controller
# http://www.nxp.com/documents/data_sheet/PCA9685.pdf
# TSSOP28\SSOP28\DIP28 Adapter
# http://item.taobao.com/item.htm?spm=a230r.1.14.108.UHRZYa&id=12717853271
# Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface - PCA9685
# http://www.adafruit.com/products/815
# http://learn.adafruit.com/adafruits-raspberry-pi-lesson-8-using-a-servo-motor/servo-motors
# http://learn.adafruit.com/adafruits-raspberry-pi-lesson-8-using-a-servo-motor/the-pwm-and-servo-kernel-module
# *** Seeeduino & Towerpro SG90 Test Program - TL Fong 2009jan08
# http://www.todopic.com.ar/foros/index.php?topic=24768.5;wap2
# /******************************************************************************
# * Hello Servo - Turn TowerPro SG90 servo to middle position
# * Created - 2009jan07, Last update - 2008jan07
# * Function - Turn servo to middle position
# * MPU/Programming language - Seeeduino v1.1/Arduino v12.0
# * Author - TL Fong (tlfong01, TaoBao)
# * Copyright - Creative Commons Attribution - ShareAlike 3.0 Licence
# *
# * Test procedure
# * (1) FIRST run the program, [!!! DO NOT POWER ON YET !!! tlfong01 2013mar13]
# * (2) Manually turn servo clockwise or counterclock to limit,
# * (3) Connect 5V power and MPU signal to servo,
# * (4) WARNING - Disconnect 5V power before stopping program,
# *
# * TowerPro SG90 Spec
# * CCW end 900uS, CW end 2100uS, middle 1500uS, 3.0 to 6.0V,
# * 9g, 22 * 11.5 * 27mm, 0.12sec/60 degrees (4.8V no load),
# * stall torque 17.5ozin/1.2 kgcm) (4.8V), dead band 7usec,
# * coreless motor, all nylon gear, RMB30 (TaoBao).
# *
# * Notes
# * 1. To turn counter clockwise limit, change pulse width from 1500 to 900.
# * 2. To turn clockwise limit, change pulse width from to 2100.
# RPiGPIOgen1 = 18 # (P1-12, BCM GPIO 18) PCM_CLK
# RPiGPIOGclk = 04 # (P1-07, BCM GPIO 04) GPIO_GCLK
# RPiPcm = RPiGPIOgen1
# RPiGpclk0 = RPiGPIOGclk
def TestRpioServo():
CounterClockwiseLimitPulseWidth = 900 # CCW limit = 900 uS = 0.9 mS
ClockwiseLimitPulseWidth = 2100 # CW limit = 2100 uS = 2.1 mS
MiddlePositionPulseWidth = 1500 # Middle position = 1500 uS = 1.5 mS
PrintDoubleSpaceLine("*** Testing RPIO.PCM tlfong01 2013mar13 ***")
RpioServoController = PWM.Servo() # default 20ms subcycle
RpioServoController.set_servo(RPiPcm, CounterClockwiseLimitPulseWidth)
RpioServoController.set_servo(RPiGpclk0, MiddlePositionPulseWidth)
time.sleep(60)
def TestRpioClock01():
PrintDoubleSpaceLine("*** Testing RPIO.PCM tlfong01 2013mar13 ***")
TenMilliSeconds = 10000
RpioServoController = PWM.Servo() # default 20ms subcycle
RpioServoController.set_servo(RPiGpclk0, TenMilliSeconds)
time.sleep(60)
def SetClock(channelNumber, frequency, rpiPin, timeSeconds): # maximum frequency = 100 Hz
cycleTime = 1000000 / frequency
startTime = (cycleTime / 2) / 10
pulseWidth = ((cycleTime / 2) / 10) - 1
PWM.setup()
PWM.init_channel(channelNumber, cycleTime)
PWM.add_channel_pulse(channelNumber, rpiPin, startTime, pulseWidth)
time.sleep(timeSeconds)
PWM.clear_channel_gpio(channelNumber, rpiPin)
PWM.cleanup()
def SetRpiGpClk0(frequencyHz, waitTime):
SetClock(channelNumber = 0, frequency = frequencyHz, rpiPin = RPiGpclk0, timeSeconds = waitTime)
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# * Guzunty Pi test functions v1.0 tlfong01 2013mar16 *
# XC9572XL-5-PC44 gz_16o8i Fitter Report 2013-01-05
# https://raw.github.com/Guzunty/Pi/master/src/gz_16o8i/gz_16o8i.rpt
#** 17 Outputs **
# Signal Name Loc Pin
# outputs<0> FB1_2 1
# outputs<1> FB1_5 2
# outputs<2> FB1_6 3
# outputs<3> FB1_8 4
# outputs<4> FB1_15 8
# outputs<5> FB1_17 9
# outputs<6> FB2_2 35
# outputs<7> FB2_5 36
# outputs<8> FB2_6 37
# outputs<9> FB2_8 38
# outputs<10> FB2_15 43
# outputs<11> FB2_17 44
# outputs<12> FB3_2 11
# outputs<13> FB3_5 12
# outputs<14> FB3_8 13
# outputs<15> FB3_9 14
# miso FB4_17 34
# ** 11 Inputs **
# Signal Name Loc Pin Type
# inputs<6> FB1_11 6~ GCK/I/O [GCK2]
# inputs<7> FB1_14 7~ GCK/I/O [GCK3]
# inputs<0> FB3_14 19 I/O
# inputs<1> FB3_15 20 I/O
# inputs<2> FB3_16 24 I/O
# inputs<3> FB3_17 22 I/O
# inputs<4> FB4_2 25 I/O
# inputs<5> FB4_5 26 I/O
# sclk FB4_11 28 I/O
# mosi FB4_14 29 I/O
# sel FB4_15 33 I/O
# ** Device Pin Out **
# --------------------------------
# /6 5 4 3 2 1 44 43 42 41 40 \
# | 7 39 |
# | 8 38 |
# | 9 37 |
# | 10 36 |
# | 11 XC9572XL-5-PC44 35 |
# | 12 34 |
# | 13 33 |
# | 14 32 |
# | 15 31 |
# | 16 30 |
# | 17 29 |
# \ 18 19 20 21 22 23 24 25 26 27 28 /
# --------------------------------
# Pin Signal Pin Signal
# No. Name No. Name
# 1 outputs<0> 23 GND
# 2 outputs<1> 24 inputs<2>
# 3 outputs<2> 25 inputs<4>
# 4 outputs<3> 26 inputs<5>
# 5 KPR 27 KPR
# 6 inputs<6> 28 sclk
# 7 inputs<7> 29 mosi
# 8 outputs<4> 30 TDO
# 9 outputs<5> 31 GND
# 10 GND 32 VCC
# 11 outputs<12> 33 sel
# 12 outputs<13> 34 miso
# 13 outputs<14> 35 outputs<6>
# 14 outputs<15> 36 outputs<7>
# 15 TDI 37 outputs<8>
# 16 TMS 38 outputs<9>
# 17 TCK 39 KPR
# 18 KPR 40 KPR
# 19 inputs<0> 41 VCC
# 20 inputs<1> 42 KPR
# 21 VCC 43 outputs<10>
# 22 inputs<3> 44 outputs<11>
# Legend :
# NC = Not Connected, unbonded pin
# PGND = Unused I/O configured as additional Ground pin
# TIE = Unused I/O floating -- must tie to VCC, GND or other signal
# KPR = Unused I/O with weak keeper (leave unconnected)
# VCC = Dedicated Power Pin
# GND = Dedicated Ground Pin
# TDI = Test Data In, JTAG pin
# TDO = Test Data Out, JTAG pin
# TCK = Test Clock, JTAG pin
# TMS = Test Mode Select, JTAG pin
# PROHIBITED = User reserved pin
#def SpiWriteTwoByteArray(spiChannel, outputTwoByteArray):
# inputTwoByteArray = spiChannel.xfer2(outputTwoByteArray)
# print "Input Two Byte Array = " + hex(inputTwoByteArray[0]) + " " + hex(inputTwoByteArray[1])
# time.sleep(2)
# return inputTwoByteArray
def TestGuzuntyPi16o8iCoreOutputTwoBytes():
PrintDoubleSpaceLine("*** Start testing Guzunty Pi Core 16o8i ***")
AllHighTwoByteArray = [0xff, 0xff]
AllLowTwoByteArray = [0x00, 0x00]
AlternateTwoByteArray = [0x55, 0xaa]
TestTwoByteArrayList = (AllHighTwoByteArray, AlternateTwoByteArray, AllLowTwoByteArray)
guzuntypiSpi = spidev.SpiDev() #create spi object for quzuntypi
guzuntypiSpi.open(0, 0) # open spi channel 0 and select slave device 0
Beep(1)
for i in range(2):
guzuntypiSpi.xfer2([0x00, 0x00])
time.sleep(1)
guzuntypiSpi.xfer2([0xff, 0xff])
time.sleep(1)
guzuntypiSpi.xfer2([0x55, 0x55])
time.sleep(1)
Beep(2)
for i in range(2):
guzuntypiSpi.xfer2(AllLowTwoByteArray)
time.sleep(1)
guzuntypiSpi.xfer2(AllHighTwoByteArray)
time.sleep(1)
guzuntypiSpi.xfer2(AlternateTwoByteArray)
time.sleep(1)
Beep(3)
for outputTwoByteArray in (TestTwoByteArrayList):
guzuntypiSpi.xfer2(outputTwoByteArray)
time.sleep(1)
PrintDoubleSpaceLine("*** Stop testing GuzuntyPi ***")
def TestGuzuntyPiSteppingMotor():
PrintDoubleSpaceLine("*** Start testing Guzunty Pi Stepping Motor ***")
guzuntypiSpi = spidev.SpiDev()
guzuntypiSpi.open(0, 0)
Beep(2)
# !!! OK IF PASSING LIST BY VALUE !!!
for i in range(10):
guzuntypiSpi.xfer2([0x05, 0x00])
time.sleep(0.05)
guzuntypiSpi.xfer2([0x0a, 0x00])
time.sleep(0.05)
Beep(4)
# !!! NOT WORKING IF PASSING LIST BY REFERENCE !!!
# Winding13 = [0x05, 0x00]
# Winding24 = [0x0a, 0x00]
# for i in range(10):
# guzuntypiSpi.xfer2(Winding13)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding13) # !!! BUG !!! all windings on !!!
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# !!! NOT WORKING IF PASSING LIST BY REFERENCE !!!
# Winding13 = [0x05, 0x00]
# Winding24 = [0x0a, 0x00]
# for i in range(10):
# guzuntypiSpi.xfer2(Winding13)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# !!! NOT WORKING IF PASSING LIST BY REFERENCE !!!
# Winding13 = [0x05, 0x00]
# Winding24 = [0x0a, 0x00]
# for i in range(10):
# guzuntypiSpi.open(0, 0) # open close each loop
# guzuntypiSpi.xfer2(Winding13)
# time.sleep(2)
# guzuntypiSpi.xfer2(Winding24)
# time.sleep(2)
# guzuntypiSpi.close()
guzuntypiSpi.close()
PrintDoubleSpaceLine("*** Stop testing GuzuntyPi ***")
# 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)
#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()
#TestLcd(Mcp23017BaseAddressSystemB1)
#ToggleGpMcp23008(registerBaseAddress = 0x21, toggleTime = 0.25, toggleCount = 4)
#ReadGpMcp23008(registerBaseAddress = 0x22, count = 100)
#TestKeypadMcp23017(registerBaseAddress = 0x20, checkPressingKeyMode = NoPollJustGetKeyEverySecond, keyCount = 4)
#TestKeypadMcp23017(registerBaseAddress = 0x20, checkPressingKeyMode = PollRowStatusNibble, keyCount = 4)
#TestKeypadMcp23017(registerBaseAddress = 0x20, checkPressingKeyMode = PollMcp23017Interrupt, keyCount = 4)
#TestKeypadMcp23008(registerBaseAddress1 = 0x21, registerBaseAddress2 = 0x22, checkPressingKeyMode = NoPollJustGetKeyEverySecond, keyCount = 4)
#TestKeypadMcp23008(registerBaseAddress1 = 0x21, registerBaseAddress2 = 0x22, checkPressingKeyMode = PollRowStatusNibble, keyCount = 4)
#TestSpiSelectDevice(deviceNumber = 0, count = 4)
#TestSpiSelectDevice(deviceNumber = 1, count = 4)
#TestSpiClockPulse(count = 10)
#TestSpiWriteBit(count = 100)
#TestSpiClockPulse(count = 10)
#TestSpiWriteBit(count = 10)
#TestSpiSelectDevice(deviceNumber = 0, count = 10)
#TestSpiSelectDevice(deviceNumber = 1, count = 4)
#TestSpiReadBit(ButtonPin, count = 10) *** OK ***
#TestSpiReadBit(SpiMisoPin, count = 10) !!! Not working !!!
#TestSpiReadBit(RxdPin, count = 10) !!! Not working !!!
#TestSpiReadBit(ButtonPin, count = 4) # *** OK ***
#TestSpiReadBit(SpiMisoPin, count = 4) # !!! Not working !!!
#TestSpiReadBit(RxdPin, count = 4) # !!! Not working !!
#PrintDoubleSpaceLine("*** Start Test x ***")
#TestRfm12bSet2Mhz()
#WaitSeconds(2)
#TestRfm12bSet1Mhz()
#WaitSeconds(2)
#PrintDoubleSpaceLine("*** Stop Test x ***")
# Rfm12bTest2(spiChannelNumber = 0, spiDeviceNumber = 0)
# Rfm12bTest3b(spiChannelNumber = 0, spiDeviceNumber = 0)
# Rfm12bTest3d(spiChannelNumber = 0, spiDeviceNumber0 = 0, spiDeviceNumber1 = 1)
#TestLcdMcp23017(registerBaseAddress = 0x20)
#TestLcdMcp23008(registerBaseAddress = 0x21)
# TestToggleMcp23017PortAoutput(registerBaseAddress = 0x20, toggleTime = 0.5, toggleCount = 100)
# TestReadMcp23017PortBinput(registerBaseAddress = 0x20, readTime = 2, readCount = 100)
# TestKeypadMcp23017(registerBaseAddress = 0x20, checkPressingKeyMode = PollRowStatusNibble, keyCount = 4)
# TestLcdMcp23017(registerBaseAddress = 0x20)
# TestBuzzer() # beep system buzzer 4 times
# TestLED() # blink system LED 4 tmes
# TestButtonEchoBuzzer() # echo system buton with system buzzer 4 times
# TestButtonEchoLED() # echo system button with system LED 4 times
# TestGpioPin(oPin = TxdPin, toggleTime = 0.5, toggleCount = 10)
# TestLcdMcp23017(registerBaseAddress = 0x21)
# TestKeypadMcp23017(registerBaseAddress = 0x21, checkPressingKeyMode = PollRowStatusNibble, keyCount = 4)
# TestRfm12bExtMpuClock(spiChannelNumber = 0, Rfm12bSpiDeviceNumber0 = 0, Rfm12bSpiDeviceNumber1 = 1)
# TestJtagPins(toggleTime = 1, testCount = 2)
# TestLcdMcp23017(i2cRegisterBaseAddress = 0x21) #I2C1
# TestKeypadMcp23017PollingMode(i2cRegisterBaseAddress = 0x21) #I2C1
# TestDualRfm12bExtMpuClock(spiChannelNumber = 0) # SPI0
# TestRpioServo()
# SetClock(channelNumber = 0, frequency = 100, rpiPin = RPiGpclk00, timeSeconds = 4)
# SetClock(channelNumber = 0, frequency = 100, rpiPin = RPiPcm)
# SetRpiGpClk0Frequency64Hz()
# SetRpiGpClk0(frequencyHz = 100, waitTime = 60)
# TestLcdMcp23017(i2cRegisterBaseAddress = 0x21) #I2C1
# TestKeypadMcp23017PollingMode(i2cRegisterBaseAddress = 0x21) #I2C1
# TestDualRfm12bExtMpuClock(spiChannelNumber = 0) # SPI0
# TestRpioServo()
# 13. Main program ************************************************************
StartProgram()
TestLcdMcp23017(i2cRegisterBaseAddress = 0x21) #I2C1
#TestGuzuntyPi16o8iCoreOutputTwoBytes()
TestGuzuntyPiSteppingMotor()
StopProgram()
# *****************************************************************************
# End of Program
# *****************************************************************************
.END
No comments:
Post a Comment