In Pelican Crossing – Part 1 software threads were used to provide timing to both the lights and the buzzer at the same time. In Part 2, the I2C MCP23017 is used again but instead of using software to time the operations, the intermittent buzzer is implemented in hardware using a 555 timer. This simplifies the code but makes the hardware more complex. I learned something from both versions.
I found some great information on 555 timers from The Electronics Club – 555 and 556 Timer Circuits page. This version creates an astable multivibrator running at 6.8Hz. The timer is enabled & disabled on command from an output from the MCP23017 via a transistor.
Figure 2 below shows the schematic:
Below is the Python code:
import threading import smbus from time import sleep bus = smbus.SMBus(0) address = 0x20 # I2C address of MCP23017 iodirA = 0x00 # Register for Bank A I/O Direction iodirB = 0x01 # Register for Bank B I/O Direction gpioA = 0x12 # Register for Bank A GPIO gpioB = 0x13 # Register for Bank B GPIO address = 0x20 # I2C address of MCP23017 bus.write_byte_data(address, iodirA, 0x00) # Set all of bank A to outputs bus.write_byte_data(address, iodirB, 0xff) # Set all of bank B to inputs # GPIOA0 - Red # GPIOA1 - Amber # GPIOA2 - Green # GPIOA3 - Buzzer # GPIOA4 - Ped Red # GPIOA5 - Ped Green # GPIOB0 - Button delayOnWalk = 4; intraChangeDelay = 1 delayButtonServicing = 0.2 def sequenceLights(): bus.write_byte_data(address, gpioA, 0x12) sleep(intraChangeDelay) bus.write_byte_data(address, gpioA, 0x29) sleep(delayOnWalk) bus.write_byte_data(address, gpioA, 0x2A) sleep(intraChangeDelay) bus.write_byte_data(address, gpioA, 0x14) sleep(intraChangeDelay) try: bus.write_byte_data(address, gpioA, 0x14) while True: mybutton = bus.read_byte_data(address,0x13) if mybutton == False: sequenceLights() sleep(delayButtonServicing) except KeyboardInterrupt: print "Caught Keyboard" bus.write_byte_data(address, gpioA, 0x00)