GPIO, ADC and DAC¶
Communicating with busses is easy, just hook everything up, add pull-ups and pull-downs everywhere and stuff starts working. But a lot of devices don’t connect to an I2C or SPI bus but need some GPIO bitbanging. Also a lot of interesting things can be done with analog pins.
The problem is that these pins can be anywhere and be used by anything. So pyElectronics provide a common interface for all digital and analog pins. These can be provided by the gateways themselves (The Raspberry Pi has a lot of GPIO) or by devices connected to a bus like I2C port extenders and ADC/DAC chips.
The provider for the pin provides an instance of one of these classes:
- DigitalInputPin: Can only read a boolean
- DigitalOutputPin: Can only write a boolean
- GPIOPin: Can switch between input and output mode
- AnalogInputPin: Can read a float between 0 and 1
- AnalogOutputPin: Can write a float betwoon 0 and 1
Example¶
The Bus Pirate has an aux pin that can be used as an digital output:
gw = BusPirate("/dev/ttyUSB0")
# Get a reference to the aux pin.
# This is an instance of DigitalOutputPin
aux = gw.get_aux_pin()
# Set the output of the pin
aux.write(True)
Using a pin on a port expander:
gw = BusPirate("/dev/ttyUSB0")
# Initialize a i2c port expander
expander = MCP23017I2C(gw)
# Get a reference to pin 4 on port B
my_own_led_pin = expander.get_pin('B4')
# Obligatory blink-a-led example
for i in range(0, 20):
my_own_led_pin.write(True)
sleep(0.5)
my_own_led_pin.write(False)
sleep(0.5)
display_pins = expander.get_pins()[2:8]
# This also doesn't exist yet.
display = HD4470(display_pins)
display.write_text("Hello World!")
GPIO Bus¶
Sometimes (most of the times) you need to connect a data bus to gpio ports but they don’t line op nice with a whole port. In that case you can use GPIOBus to put a bunch of GPIO pins together to create a virtual port. You can create a bus of any width this way:
gw = BusPirate("/dev/ttyUSB0")
expander = MCP23017I2C(gw)
pins = expander.get_pins()
# Use pin 5,6,7 and 2 from the port expander
buspins = pins[5:8]
buspins.append(pins[2])
# Create a bus
bus = GPIOBus(buspins)
# Write data to the bus
bus.write(13)
The pins in the bus don’t have any relation to eachother, they don’t even have to be on the same chip:
gw = BusPirate("/dev/ttyUSB0")
expander = MCP23017I2C(gw)
# Get references for all the pins on the expander
pins = expander.get_pins()
# Get reference to the aux pin on the Bus Pirate
aux = gw.get_aux_pin()
# Use pin 5,6 and from the port expander
buspins = pins[5:8]
# Add the aux pin from the Bus Pirate
buspins.append(aux)
# Create a bus
bus = GPIOBus(buspins)
# Write data to the bus the same way as the previous example
bus.write(13)
The problem is if your pins are open-drain, you get an even bigger problem if a subset of your pins is open-drain. You can individually invert pins in the bus on definition. This is not handled by the GPIOBus class but by the GPIOPins themselves:
# Get references for a bunch of leds
red = expander.get_pin('A0')
green = expander.get_pin('A1')
blue = gw.get_aux_pin()
# Define a bus with the expander pins inverted
colorbus = GPIOBus([~red, ~green, blue])
# Disco!
for i in range(0,8):
colorbus.write(i)