In a previous post I signed off with questions about the functionality of the pfc8574. What is all this ‘quasi-bidirectional’ stuff in the data sheet about? It prevented me from implementing a getPin() method in my Android Things things-drivers library. I didn’t know what would happen when I set a pin value making it an output, then read the pin state. Would it be the value I wrote, or the pin state based on the electrical biasing of the pin.

Now that I have the pcf8574 test jig I can see what actually happens when I set pcf8574 pins high or low, and Raspberry Pi pins high or low. I can make a truth table of pin states to see if it would be OK to implement the readPin() method that’s missing from the driver.

The Hardware

The hardware for this experiment is the pcf8574 test jig setup that I used in the test jig experiment.

The PCF8574 Test Jig

The Software

In this experiment I need to write an Android Things application that sets the state of the pcf8574 and some Raspberry Pi GPIO pins. I’m going to use the test application that I wrote in the test jig experiment, extending it to help me construct a truth table of pin states. Previously I had set the Raspberry Pi GPIO pins as inputs, now I want to use some of the Raspberry Pi GPIO pins as outputs. Because I’m using the Raspberry Pi pins as outputs, I’ll need to measure the pin voltage with a multimeter to observe what physically changes.

I added a method to set a Raspberry Pi pin and pcf8574 pin in a given state.

I then used this method with all possible input combinations to create the following truth table.

pcf8574 \ Rpi GPIO LOW HIGH

From this table we can see that when the pcf8574 pin is low, it doesn’t matter what state the Raspberry Pi pin is, it will always read low. This is not what we want for a readPin() method. We want a readPin() method to return the state of the pin biasing, not the state we set it to. When we set the pcf8574 pin high, we read the pin state as set by the Raspberry Pi. This is what we want. This means that we can use the pcf8574 to read the state of the pins, all we need to do is set the pin state high, then the state read will be the actual pin biasing. This confirms the data sheet, which states that to use a pin as an input, first set its state to 1 (high).

Updating the driver

I’ve updated the things-drivers library to have a readPin() method, I’ve also exposed a readByte() method which reads all pins at once. Here’s the updated interface:

Before using getPin() be sure to call setPin(pin, true) to set that pin  high. This means now that readValue() may return a value that is not a representation of actual pin states, but then, the interface documentation does state that readValue() returns the last value written to the port, not the port pin states, so I guess it’s not wrong.


This experiment demonstrates the value of having a test jig to use during driver development. Having a way to validate your work on real hardware removes a lot of the doubt from product development. Although the primary purpose of a test jig may be to validate that hardware has been manufactured correctly, it can also be invaluable to the driver developer. Now that I have a working pcf8574 driver, validated on real hardware, I think I’ll need to use it to control some IO. Maybe drive some relays or LEDs, or perhaps something that goes ‘bing’ or a car eating robot or similar.