Now I have modified the program to do the following sequence.
1. Toggle MCP23017 PortA and PortB 4 times
2. Toggle MCP23008 Port 4 times
But there is one strange bug I could not get rid off.
In the writePortLow08 function, if I set dataBye = 0x00, then there will be IO error. But it is OK if I set other values like 0xf0, ox55 etc.
def writePortHigh08(registerBaseAddress, registerAddressArray):
dataByte = 0xf0 # All 8 bits High
writeData08(registerBaseAddress, registerAddressArray, dataByte)
def writePortLow08(registerBaseAddress, registerAddressArray):
# dataByte = 0x00 # All 8 bits Low # !!! IO error for 0x00, but OK for 0x0f !!!
dataByte = 0x0f # All 8 bits Low
writeData08(registerBaseAddress, registerAddressArray, dataByte)
def togglePort08(registerBaseAddress, registerAddressArray, onTime, offTime, count):
setPortOutput08(registerBaseAddress, registerAddressArray)
for i in range(count):
writePortHigh08(registerBaseAddress, registerAddressArray)
sleep(onTime)
writePortLow08(registerBaseAddress, registerAddressArray)
sleep(offTime)
# *****************************************************************************
# *** tiox1a.py ***
# Program - Test MCP23008
# Version - 1.a
# Date - 2012nov30
# Update - 2013jan04
# Author - tlfong01
# File - tiox1a_2013jan04.py
# Blog - http://tlfong01.blogspot.hk/
# Purpose - test basics of Raspberry Pi GPIO
# Hardware - Raspberry Pi Model B Revsion 2.0 [2012oct/nov/dec]
# Software - Raspbian Wheezy (2012sep15), Python 2.7.3
# GPIO 0.4.1a http://pypi.python.org/pypi/RPi.GPIO/0.4.1a
# Wiring - RPi Board Numbering
# P1-02 5V, P1-04 5V, P1-06 Gnd
# P1-01 3V3, P1-03 I2C SDA1, P1-05 I2C SCL1
# P1-08 UART TxD (MCP23017 Reset)
# P1-10 UART RxD (MCP23017 INTB)
# P1-12 RPi GPIO_GEN1 (BCM18) LED (P1-12 > LED > 330R > Gnd)
# P1-14 Gnd
# P1-16 GPIO_GEN4 - Buzzer, 3V3 5mA (P1-16 > Buzzer > Gnd)
# P1-18 GPIO_GEN5 Button (3V3 > 10K > Contact 1/2 > 330R > Gnd)
# P1-20 Gnd
# P1-22 GPIO_GEN6 - MCP23008 INT / MCP23017 INTA
# *****************************************************************************
# *** Import Python modules ***
import smbus
import sys
import RPi.GPIO as GPIO
from time import sleep
import select
# *****************************************************************************
# *** Configure RPi GPIO pins ***
# * RPi.GPIO setting *
GPIO.setmode(GPIO.BOARD) # Use RPi GPIO numbering, Not BCM numbering
GPIO.setwarnings(False) # Disable linux's "pin already in use warning"
# * P1 pins numbering *
RPiGPIOgen1 = 12 # Brown (P1-12, BCM GPIO 18) LED
RPiGPIOgen4 = 16 # Yellow (P1-16, BCM GPIO 23) Buzzer
RPiGPIOgen5 = 18 # Green (P1-18, BCM GPIO 24) Button
RPiGPIOgen6 = 22 # Blue (P1-22, BCM GPIO 25) IOx Interrupt
RPiTxD = 8 # Orange (P1-08) UART TxD
RPiRxD = 10 # Yellow (P1-10) UART RxD
# * IO device pins assignment *
LEDpin = RPiGPIOgen1
BuzzerPin = RPiGPIOgen4
ButtonPin = RPiGPIOgen5
InterruptPin = RPiGPIOgen6
TxDpin = RPiTxD
RxDpin = RPiRxD
# * IO pins list *
OutputPinList = [LEDpin, BuzzerPin, TxDpin]
InputPinWithNoPullUpList = [ButtonPin, RxDpin]
InputPinWithPullUpList = [InterruptPin]
# * No need to set the I2C pins SCL1 and SDA1, because they are automatically set by
# Raspbian Wheezy
# *****************************************************************************
# *** Constants ***
# * General - counts, time periods, nibble types *
TwoTimes = 2
FourTimes = 4
EightTimes = 8
TenTimes = 10
TwentyTimes = 20
FiftyTimes = 50
OneHundredTimes = 100
TwoHundredTimess = 200
FourHundredTimes = 400
TWENTY_MILLI_SECONDS = 0.02
FIFTY_MILLI_SECONDS = 0.05
TENTH_SECOND = 0.1
QUARTER_SECOND = 0.25
HALF_SECOND = 0.5
ONE_SECOND = 1
ONE_AND_HALF_SECONDS = 1.5
TWO_SECONDS = 2
ON_TIME = TENTH_SECOND
OFF_TIME = QUARTER_SECOND
BUTTON_DEBOUNCING_TIME = QUARTER_SECOND
TEST_TIME = 0.05
LOW_NIBBLE = 0
HIGH_NIBBLE = 1
BOTH_NIBBLE = 2 # full byte of 8 bits
# * Device constants *
# LED and buzzer states
OFF = False
ON = True
# Button states
PRESSED = False
RELEASED = True
# *****************************************************************************
# *** RPi GPIO functions ***
# Reference - Raspberry Pi Python GPIO Version - GPIO 0.4.1a
# http://pypi.python.org/pypi/RPi.GPIO/0.4.1a
# RPi Model B 5V0 max current draw: 50 mA
# RPi Model B 3V3 max current draw: 300 mA
# GPIO maximum current draw per pin: 17mA source, 12mA sink
# * 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:
setupInputPinWithPullUp(iPin)
for iPin in inputPinWithPullUpList:
setupInputPinWithPullUp(iPin)
def setupGPIO(): # set up GPIO pins
setupGPIOpins(OutputPinList, InputPinWithNoPullUpList, InputPinWithPullUpList )
# * pulse and echo functions *
def pulsePin(oPin, onTime, offTime): # blink LED or beep buzzer
writeOutputPin(oPin, ON)
sleep(onTime)
writeOutputPin(oPin, OFF)
sleep(offTime)
def echoPin(iPin, oPin): # echo input pin to output pin, e.g. button to LED or buzzer
while True:
if readInputPin(iPin) == RELEASED:
pass
else:
pulsePin(oPin, ON_TIME, OFF_TIME)
break
continue
def togglePin(oPin, toggleTime): # toggle pin
writeOutputPin(oPin, ON)
sleep(toggleTime)
writeOutputPin(oPin, OFF)
sleep(toggleTime)
# * Test GPIO functions *
def testBuzzer(): # beep 4 times
setupGPIO()
for i in range (FourTimes):
pulsePin(BuzzerPin, ON_TIME, OFF_TIME)
def testLED(): # blink 8 times
setupGPIO()
for i in range (EightTimes):
pulsePin(LEDpin, ON_TIME, OFF_TIME)
def testButtonEchoBuzzer(): #
setupGPIO()
for i in range (TenTimes):
echoPin(ButtonPin, BuzzerPin)
def testButtonEchoLED(): #
setupGPIO()
for i in range (TenTimes):
echoPin(ButtonPin, LEDpin)
def testToggleTxDpin():
while True:
togglePin(TxDpin, TWO_SECONDS)
# *****************************************************************************
# *** Beep functions ***
def beep(count):
for i in range(count):
pulsePin(BuzzerPin, ON_TIME, OFF_TIME)
def startBeep():
beep(TwoTimes)
sleep(1)
def endBeep():
beep(FourTimes)
def oneBeep():
beep(1)
# *****************************************************************************
# *** IO Expander MCP23008 / MCP23017 ***
# * Bash script using i2cTools's i2cset command to toggle GPIO pins *
#!/bin/bash
# i2cset -y 1 0x20 0x00 0x00
# count=0
# while [ $count -lt 10 ];
# do
# i2cset -y 1 0x20 0x0a 0x00
# sleep 0.5
# i2cset -y 1 0x20 0x0a 0xff
# sleep 0.5
# let count++
# done
# To run i2c-X commands in user mode: sudo chmod 666 /dev/i2c-X
# sudo chmod 666 /dev/i2c-1
# * Setup SMBus *
I2C_BUS_NUMBER = 1 # P1-03 = SDA1, P1-05 = SCL1
smBus1 = smbus.SMBus(I2C_BUS_NUMBER) # global variable, cannot be set by a function
# * Register address array indexes (for both MCP23008 and MCP23017)*
InputOutputDirection = 0
InputPolarity = 1
InterruptOnChangeEnable = 2
InterruptOnChangeDefaultValue = 3
InterruptOnChangeMode = 4
Configuration = 5
PullUpResistor = 6
InterruptFlag = 7
InterruptCapture = 8
PortStatus = 9
OutputLatch = 10
# * MCP23008 Functions *
Mcp23008RegisterAddressArray = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a]
Mcp23008BaseAddress1 = 0x24
MCP23008_1_REGISTER_BASE_ADDRESS = 0x20
MCP23008_2_REGISTER_BASE_ADDRESS = 0x21
def setIoDirection08(registerBaseAddress, registerAddressArray, directionByte):
addressOffset = registerAddressArray[InputOutputDirection]
smBus1.write_byte_data(registerBaseAddress, addressOffset, directionByte)
def setPortOutput08(registerBaseAddress, registerAddressArray):
directionByte = 0x00 # all output
setIoDirection08(registerBaseAddress, registerAddressArray, directionByte)
def writeData08(registerBaseAddress, registerAddressArray, dataByte):
addressOffset = registerAddressArray[OutputLatch]
smBus1.write_byte_data(registerBaseAddress, addressOffset, dataByte)
def writePortHigh08(registerBaseAddress, registerAddressArray):
dataByte = 0xf0 # All 8 bits High
writeData08(registerBaseAddress, registerAddressArray, dataByte)
def writePortLow08(registerBaseAddress, registerAddressArray):
# dataByte = 0x00 # All 8 bits Low # !!! IO error for 0x00, but OK for 0x0f !!!
dataByte = 0x0f # All 8 bits Low
writeData08(registerBaseAddress, registerAddressArray, dataByte)
def togglePort08(registerBaseAddress, registerAddressArray, onTime, offTime, count):
setPortOutput08(registerBaseAddress, registerAddressArray)
for i in range(count):
writePortHigh08(registerBaseAddress, registerAddressArray)
sleep(onTime)
writePortLow08(registerBaseAddress, registerAddressArray)
sleep(offTime)
def testTogglePort08():
togglePort08(Mcp23008BaseAddress1, Mcp23008RegisterAddressArray, 0.5, 0.5, 4) # on x second, off x second, times
# ****************************************************************************
# * MCP23017 functions *
# * Base addresses *
Mcp23017BaseAddress1 = 0x22
# * Port type *
PortA = 0
PortB = 1
# * Registerr address arrays *
MCP23017Band0RegisterAddressArray = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a]
MCP23017Band1RegisterAddressArray = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x11, 0x13, 0x15, 0x17, 0x19,
0x01, 0x03, 0x05, 0x07, 0x09, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a]
# * Set IO direction *
def setIoDirection(registerBaseAddress, registerAddressArray, portType, directionByte):
if portType == 0:
addressOffset = registerAddressArray[InputOutputDirection]
else:
addressOffset = registerAddressArray[InputOutputDirection + 11]
smBus1.write_byte_data(registerBaseAddress, addressOffset, directionByte)
def setBothPortsOutput(registerBaseAddress, registerAddressArray):
directionByte = 0x00 # all output
portType = 0 # Port A
setIoDirection(registerBaseAddress, registerAddressArray, portType, directionByte)
portType = 1 # Port B
setIoDirection(registerBaseAddress, registerAddressArray, portType, directionByte)
# * Write data *
def writeData(registerBaseAddress, registerAddressArray, portType, dataByte):
if portType == 0:
addressOffset = registerAddressArray[OutputLatch]
else:
addressOffset = registerAddressArray[OutputLatch + 11]
smBus1.write_byte_data(registerBaseAddress, addressOffset, dataByte)
def writeAportHigh(registerBaseAddress, registerAddressArray):
dataByte = 0xff # All 8 bits High
portType = 0 # Port A
writeData(registerBaseAddress, registerAddressArray, portType, dataByte)
def writeBportHigh(registerBaseAddress, registerAddressArray):
dataByte = 0xff # All 8 bits High
portType = 1 # Port B
writeData(registerBaseAddress, registerAddressArray, portType, dataByte)
def writeBothPortsHigh(registerBaseAddress, registerAddressArray):
writeAportHigh(registerBaseAddress, registerAddressArray)
writeBportHigh(registerBaseAddress, registerAddressArray)
def writeAportLow(registerBaseAddress, registerAddressArray):
dataByte = 0x00 # All 8 bits Low
portType = 0 # Port A
writeData(registerBaseAddress, registerAddressArray, portType, dataByte)
def writeBportLow(registerBaseAddress, registerAddressArray):
dataByte = 0x00 # All 8 bits Low
portType = 1 # Port B
writeData(registerBaseAddress, registerAddressArray, portType, dataByte)
def toggleAport(registerBaseAddress, registerAddressArray, time, count):
for i in range(count):
writeAportHigh(registerBaseAddress, registerAddressArray)
sleep(time)
writeAportLow(registerBaseAddress, registerAddressArray)
sleep(time)
def toggleBport(registerBaseAddress, registerAddressArray, time, count):
for i in range(count):
writeBportHigh(registerBaseAddress, registerAddressArray)
sleep(time)
writeBportLow(registerBaseAddress, registerAddressArray)
sleep(time)
def toggleBothPorts(registerBaseAddress, registerAddressArray, time, count):
for i in range(count):
writeAportHigh(registerBaseAddress, registerAddressArray)
writeBportHigh(registerBaseAddress, registerAddressArray)
sleep(time)
writeAportLow(registerBaseAddress, registerAddressArray)
writeBportLow(registerBaseAddress, registerAddressArray)
sleep(time)
def testTogglePortA17():
setBothPortsOutput(Mcp23017BaseAddress1, MCP23017Band0RegisterAddressArray)
toggleAport(Mcp23017BaseAddress1, MCP23017Band0RegisterAddressArray, 0.5, 2) # toggle x second, y times
def testTogglePortB17():
setBothPortsOutput(Mcp23017BaseAddress1, MCP23017Band0RegisterAddressArray)
toggleBport(Mcp23017BaseAddress1, MCP23017Band0RegisterAddressArray, 0.5, 2) # toggle x second, y times
def testToggleBothPorts17():
setBothPortsOutput(Mcp23017BaseAddress1, MCP23017Band0RegisterAddressArray)
toggleBothPorts(Mcp23017BaseAddress1, MCP23017Band0RegisterAddressArray, 0.5, 2) # toggle x second, y times
# ****************************************************************************
# * Direction setting *
DIRECTION_BYTE_ALL_OUTPUT = 0x00
DIRECTION_BYTE_LOW_NIBBLE_OUTPUT_HIGH_NIBBLE_INPUT = 0xf0
# * Data pattern *
DATA_BYTE_ALL_ZERO = 0x00
DATA_BYTE_ALL_ONE = 0xff
DATA_BYTE_HIGH_NIBBLE_ONE_LOW_NIBBLE_ZERO = 0xf0
DATA_BYTE_HIGH_NIBBLE_ZERO_LOW_NIBBLE_ONE = 0x0f
# * Interrupt setting *
ENABLE_INTERRUPT_HIGH_NIBBLE = 0xf0
DEFAULT_COMPARE_VALUE_HIGH_NIBBLE = 0xf0
INTERRUPT_CONTROL_COMPARE_DEFAULT_HIGH_NIBBLE = 0xf0
INTERRUPT_PIN_PUSH_PULL_DRIVER_HIGH_ACTIVE = 0b00111010 # 0x3a, no auto add incre, no slew rate
INTERRUPT_PIN_OPEN_DRAIN = 0b00111000 # 0x38, no auto add incre, no slew rate
# * Setup IO direction *
def setIOxPinsAllOutput(registerBaseAddress): # set up all 8 IOx pins as output
smBus1.write_byte_data(registerBaseAddress, IO_DIRECTION_REGISTER, DIRECTION_BYTE_ALL_OUTPUT)
def setIOxPinsLowNibbleOutputHighNibbleInput(registerBaseAddress): # set low nibble output, high nibble input
smBus1.write_byte_data(registerBaseAddress, IO_DIRECTION_REGISTER, DIRECTION_BYTE_LOW_NIBBLE_OUTPUT_HIGH_NIBBLE_INPUT)
# * Writing data *
def writeIOxPinsAllLow(registerBaseAddress): # write zeros to all 8 IOx output pins
smBus1.write_byte_data(registerBaseAddress, OUTPUT_LATCH_REGISTER, DATA_BYTE_ALL_ZERO)
def writeIOxPinsAllHigh(registerBaseAddress): #write ones to all 8 IOx output pins
smBus1.write_byte_data(registerBaseAddress, OUTPUT_LATCH_REGISTER, DATA_BYTE_ALL_ONE)
def writeIOxPins(registerBaseAddress, dataHexString): # write 8 bit hex string to IOx output pins
smBus1.write_byte_data(registerBaseAddress, OUTPUT_LATCH_REGISTER, dataHexString)
# * Reading data *
def readIOxPinsByte(registerBaseAddress): # read 8 bit hex data from GPIO register (= 8 output pin)
hexByte = smBus1.read_byte_data(registerBaseAddress, GPIO_REGISTER)
return hexByte
def readIOxPinsHighNibble(registerBaseAddress): # read high nibble from GPIO resister (= upper nible of output pins)
hexByte = readIOxPinsByte(registerBaseAddress)
hexNibble = hexByte >> 4
return hexNibble
# * Interrupt setting *
def enableInterruptOnChangeHighNibble(registerBaseAddress): # enable high nibble interrupt on change
smBus1.write_byte_data(registerBaseAddress, INTERRUPT_ON_CHANGE_REGISTER, ENABLE_INTERRUPT_HIGH_NIBBLE)
def setInterruptOnChangeDefaultHighNibble(registerBaseAddress): # set high nibble default compare values
smBus1.write_byte_data(registerBaseAddress, DEFAULT_COMPARE_VALUE_REGISTER, DEFAULT_COMPARE_VALUE_HIGH_NIBBLE)
def setInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress): # enable high nibble compare default
smBus1.write_byte_data(registerBaseAddress, INTERRUPT_CONTROL_REGISTER, INTERRUPT_CONTROL_COMPARE_DEFAULT_HIGH_NIBBLE)
def setHighNibbleCompareDefault(registerBaseAddress): # set high nibble compare default
enableInterruptOnChangeHighNibble(registerBaseAddress)
setInterruptOnChangeDefaultHighNibble(registerBaseAddress)
setInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress)
def setInterruptPinPushPullHighActive(registerBaseAddress): # interrupt pin push pull high active, no auto add inc, no slew rate
smBus1.write_byte_data(registerBaseAddress, IO_CONTROL_REGISTER, INTERRUPT_PIN_PUSH_PULL_DRIVER_HIGH_ACTIVE)
def setInterruptPinOpenDrain(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
smBus1.write_byte_data(registerBaseAddress, IO_CONTROL_REGISTER, INTERRUPT_PIN_OPEN_DRAIN)
# * Interrupt reading *
def readInterruptFlagPinsHighNibble(registerBaseAddress): # read high nibble interrupt flag register
hexByte = smBus1.read_byte_data(registerBaseAddress, INTERRUPT_FLAG_REGISTER)
hexNibble = hexByte >> 4
return hexNibble
def readInterruptCapturePinsHighNibble(registerBaseAddress): # read high nibble interrupt capture register
hexByte = smBus1.read_byte_data(registerBaseAddress, INTERRUPT_CAPTURE_REGISTER)
hexNibble = hexByte >> 4
return hexNibble
# * Blink LED *
def switchOffAll8LEDs(RegisterBaseAddress):
writeIOxPinsAllLow(RegisterBaseAddress)
def switchOnfAll8LEDs(RegisterBaseAddress):
writeIOxPinsAllHigh(RegisterBaseAddress)
def blink8LEDs(RegisterBaseAddress, OnTime, OffTime, Count):
setIOxPinsAllOutput(RegisterBaseAddress)
for i in range(Count):
writeIOxPinsAllHigh(RegisterBaseAddress)
sleep(OnTime)
writeIOxPinsAllLow(RegisterBaseAddress)
sleep(OffTime)
def blink4LEDs(RegisterBaseAddress, OnTime, OffTime, Count):
setIOxPinsLowNibbleOutputHighNibbleInput(RegisterBaseAddress)
for i in range(Count):
writeIOxPinsAllHigh(RegisterBaseAddress)
sleep(OnTime)
writeIOxPinsAllLow(RegisterBaseAddress)
sleep(OffTime)
# * Testing *
def blink8LEDsMCP230080x20():
blink8LEDs(MCP23008_1_REGISTER_BASE_ADDRESS, HALF_SECOND, ONE_SECOND, FourTimes)
def blink4LEDsMCP230080x21():
blink4LEDs(MCP23008_2_REGISTER_BASE_ADDRESS, HALF_SECOND, ONE_SECOND, FourTimes)
def blink8LEDsMCP23017(deviceAddress, bankNumber, portGroup):
setBankNumberPortGroup(bankNumber, portGroup)
blink8LEDs(deviceAddress, HALF_SECOND, HALF_SECOND, FourTimes)
def testInterruptPinFallingEdgeDetection():
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
sleep(1)
continue
GPIO.set_low_event(InterruptPin, enable = False) # disable detection
print "End of test, or interrupt detected"
# *****************************************************************************
# *** Unipolar Stepping Motor 28BYJ48 etc ***
# 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 Blue Pink Yellow Orange Red
# PX245 Black Green Blue Red Yellow/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
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))
# * Move unipolar stepping motor *
def writeSequence_13_24(RegisterBaseAddress, NibbleType, StepCount, StepTime): # move motor using 13-24 sequence
setIOxPinsAllOutput(RegisterBaseAddress)
if NibbleType == LOW_NIBBLE:
hexString1 = convert2PinToHex(1, 3)
hexString2 = convert2PinToHex(2, 4)
else:
hexString1 = convert2PinToHighNibble(1, 3)
hexString2 = convert2PinToHighNibble(2, 4)
for i in range(StepCount):
writeIOxPins(RegisterBaseAddress, hexString1)
sleep(StepTime)
writeIOxPins(RegisterBaseAddress, hexString2)
sleep(StepTime)
def writeSequence_13_23_24_14(RegisterBaseAddress, NibbleType, StepCount, StepTime): #move motor using 13-23-24-14 sequence
setIOxPinsAllOutput(RegisterBaseAddress)
if NibbleType == LOW_NIBBLE:
motorWindingActivationPatternArray = (0x05, 0x06, 0x0a, 0x09)
else:
motorWindingActivationPatternArray = (0x50, 0x60, 0xa0, 0x90)
for i in range(StepCount):
for pattern in motorWindingActivationPatternArray:
writeIOxPins(RegisterBaseAddress, pattern)
sleep(StepTime)
def move2MotorsUsingMCP23008_1(): # move 2 motors one after another
oneBeep()
writeSequence_13_24(MCP23008_1_REGISTER_BASE_ADDRESS, LOW_NIBBLE, TwentyTimes, FIFTY_MILLI_SECONDS)
oneBeep()
writeSequence_13_24(MCP23008_1_REGISTER_BASE_ADDRESS, HIGH_NIBBLE, OneHundredTimes, TWENTY_MILLI_SECONDS)
oneBeep()
writeSequence_13_23_24_14(MCP23008_1_REGISTER_BASE_ADDRESS, LOW_NIBBLE, TwentyTimes, FIFTY_MILLI_SECONDS)
oneBeep()
writeSequence_13_23_24_14(MCP23008_1_REGISTER_BASE_ADDRESS, HIGH_NIBBLE, OneHundredTimes, TWENTY_MILLI_SECONDS)
def move1MotorUsingMCP23008_2(RegisterBaseAddress, OnTime, OffTime, BlinkCount, CycleCount, StepTime ): # move motor on MCP23008 #2
setIOxPinsLowNibbleOutputHighNibbleInput(RegisterBaseAddress)
oneBeep
for i in range(BlinkCount):
writeIOxPinsAllHigh(RegisterBaseAddress)
sleep(OnTime)
writeIOxPinsAllLow(RegisterBaseAddress)
sleep(OffTime)
oneBeep()
writeSequence_13_24(RegisterBaseAddress, LOW_NIBBLE, CycleCount, StepTime)
# *****************************************************************************
# *** Keypad ***
# Keypad scanning procedure version 1.0
# 1. Set 3 column ports GP0, GP1, GP2 as output (GP3 don't care)
# 2. Set 4 row ports GP4, GP5, GP6, GP7 as input
# 3. Write LOW to all row ports
# 4. Wait for interrupt
# 5. Pressing any key would cause an interrupt
# 6. When interrupt occurs check which row reads LOW
# 7. Write LOW only to column GP0, if row port still LOW, then this column 0
# has a key pressed, if not, check if column 1, if not column 3.
# 8. Calculate the key using the column and row data.
# Read MCP23008 GP4 ~ GP7
def testReadGP4567(): # read keypad input rows 0~3
RegisterBaseAddress = MCP23008_2_REGISTER_BASE_ADDRESS
setIOxPinsLowNibbleOutputHighNibbleInput(RegisterBaseAddress)
writeIOxPinsAllLow(RegisterBaseAddress)
nibble = 0xf0
while True:
oneBeep()
sleep(1)
nibble = smBus1.read_byte_data(RegisterBaseAddress, GPIO_REGISTER)
print "GP4 to GP7 = ", hex(nibble)
## * keypad base address and smBus setting *
keypadRegisterBaseAddress = MCP23008_2_REGISTER_BASE_ADDRESS
keypadSmBus = smBus1
# * Keypad columns numbering *
ColumnOutputPin0 = 0
ColumnOutputPin1 = 1
ColumnOutputPin2 = 2
ColumnOutputPinTuple = ColumnOutputPin0, ColumnOutputPin1, ColumnOutputPin2
# * Keypad row numbering *
RowInputPin0 = 0
RowInputPin1 = 1
RowInputPin2 = 2
RowInputPin3 = 3
RowInputPinTuple = RowInputPin0, RowInputPin1, RowInputPin2, RowInputPin2
# * Keypad matrix numbering *
KeyPadMatrixTuple = ColumnOutputPinTuple, RowInputPinTuple
# * Write keypad column data patterns *
ColumnAllLow = 0b000
Column0Low = 0b110
Column1Low = 0b101
Column2Low = 0b011
ColumnLowTuple = Column0Low, Column1Low, Column2Low
# * Read keypad data patterns *
RowAllHigh = 0b1111
Row0Low = 0b1110
Row1Low = 0b1101
Row2Low = 0b1011
Row3Low = 0b0111
RowLowTuple = Row0Low, Row1Low, Row2Low, Row3Low
# * Set, write, read keypad pins *
def assignKeypadReadWritePins(keypadRegisterBaseAddress):
setIOxPinsLowNibbleOutputHighNibbleInput(keypadRegisterBaseAddress)
def writeColumnPins(keypadRegisterBaseAddress, columnPattern):
hexString = 0xff & columnPattern
writeIOxPins(keypadRegisterBaseAddress, hexString)
def readRowPins():
hexNibble = readIOxPinsHighNibble(keypadRegisterBaseAddress)
return hexNibble
# * test polling/interrupt keypad *
def scanKeypad(registerBaseAddress):
assignKeypadReadWritePins(registerBaseAddress)
setInterruptPinOpenDrain(registerBaseAddress) # *** interrupt pin open drain !!!
writeColumnPins(registerBaseAddress, ColumnAllLow)
setHighNibbleCompareDefault(registerBaseAddress) # *** testing interrupt ***
# Loop until one key pressed
keyPressed = False
while True:
nibble = readRowPins()
if nibble == Row0Low:
row = 0
keyPressed = True
print "Row 0 key pressed"
elif nibble == Row1Low:
row = 1
keyPressed = True
print "Row 1 key pressed"
elif nibble == Row2Low:
row = 2
keyPressed = True
print "Row 2 key pressed"
elif nibble == Row3Low:
row = 3
keyPressed = True
print "Row 3 key pressed"
else:
row = 9
#print "No key or more than one key pressed"
if keyPressed == True:
# Check which column the key is pressed
column = 9
writeColumnPins(registerBaseAddress, Column0Low)
nibble = readRowPins()
if nibble != RowAllHigh:
column = 0
print "Column 0 key pressed"
else:
writeColumnPins(registerBaseAddress, Column1Low)
nibble = readRowPins()
if nibble != RowAllHigh:
column = 1
print "Column 1 key pressed"
else:
writeColumnPins(registerBaseAddress, Column2Low)
nibble = readRowPins()
if nibble != RowAllHigh:
column = 2
print "Column 2 key pressed"
else:
print "Error"
# Calculate which key pressed
keyNumber = (row * 3) + (column + 1)
print "Key pressed = ", '{0:8}'.format(str(keyNumber).zfill(2).rjust(10))
# *******************************************************************************
# checking interrupt
# *******************************************************************************
# Check which column interrupt
interruptFlagNibble = readInterruptFlagPinsHighNibble(registerBaseAddress)
interruptCaptureNibble = readInterruptCapturePinsHighNibble(registerBaseAddress)
print "Interrupt flag nibble = ", '{0:8}'.format((str(bin(interruptFlagNibble)).zfill(4)).rjust(10))
print "Interrupt capture nibble = ", '{0:8}'.format((str(bin(interruptCaptureNibble)).zfill(4)).rjust(10))
keyPressed = False
sleep(1)
else:
pass
def testScanKeypad():
scanKeypad(MCP23008_2_REGISTER_BASE_ADDRESS)
# *****************************************************************************
# * Old test functions *
# testLEDandBuzzer()
# testButton() !!! not working !!!
# blink8LEDsIOx1()
# blink4LEDsIOx2()
# testConvert1PinToHex()
# blink4LEDsIOx2()
# move1MotorUsingMCP23008_2(MCP23008_2_REGISTER_BASE_ADDRESS, HALF_SECOND,
# ONE_SECOND, FourTimes, TwentyTimes, ONE_SECOND)
# *****************************************************************************
# *** Old test functions ***
#setupGPIO()
#startBeep()
#blink4LEDsIOx2() # OK 2012dec14
#testReadGP4567() # OK 2012dec14
#testScanKeypad()
#endBeep()
# *****************************************************************************
# *** Current test functions ***
#testBuzzer() # beep buzzer 4 times
#testLED() # blink LED 8 tmes
#testButtonEchoBuzzer() # echo buton with buzzer 10 times
#testButtonEchoLED() # echo buton with LED 10 times
#testToggleTxDpin() # toggle TxD pin every 2 seconds
setupGPIO()
startBeep()
#testTogglePortA17()
#testTogglePortB17()
testToggleBothPorts17()
testTogglePort08()
# *****************************************************************************
# End of Program
# *****************************************************************************
No comments:
Post a Comment