In this experiment I’m going to add buttons to Android Things using the user space input driver extension mechanism provided by the platform. I’ll be using momentary push buttons connected to a Raspberry Pi running the Android Things preview image. The buttons will be connected via an I2C IO port, the PCF8574. I’ll use one GPIO on the Raspberry Pi as an ‘interrupt’ line to detect a button press, then I’ll read the button states and report button presses to the framework as input events.

The setup with buttons

Reading button states via I2C is relatively slow. I’m expecting that rapid key presses will be missed. I’ve used buttons connected via I2C in projects before, the advantage of this method is that switch de-bouncing is usually not necessary.

New things I’ll be trying in this experiment are:

  1. The Android Things GPIO API configured as an ‘interrupt’
  2. The Android Things Input user space driver

Connecting the Hardware

The hardware for this experiment is similar to that used for my previous experiments except for the addition of another PCF8574. I’ve set this up to have an address of 0. I’ve added buttons and pull up resistors to the PCF8574 IO pins. I’ve connected the INT line of the PCF8574 to a GPIO on the Raspberry Pi via the level shifter.

The Software

This experiment uses the GPIO API from the Android Things SDK. This enables us to configure a GPIO on the Raspberry Pi and have the framework notify us of changes on the GPIO pin. The PCF8574 asserts this line (active low) whenever any of the IO lines change state. Pressing a button changes an IO line from high to low, causing the PCF8574 to assert the INT line, The Android Things framework notifies us when this happens and we read the state of the IO pins on the PCF8574. Reading the PCF8574 clears the interrupt and the INT line is de-asserted. This takes ‘an age’ in computer terms so I’m not expecting blistering fast button performance. The advantage of this method is that we can have up to 8 buttons for the cost of one GPIO and two I2C lines that we’d be using anyway.

Add the Library

To use the things-drivers library containing the button driver, after you have set up a standard Android Things, add the following to the dependencies section of your app’s build.gradle

compile 'nz.geek.android.things:things-drivers:1.1.1'

Adding Buttons

Access buttons by instantiating an I2cButton using the I2cButton.I2cButtonBuilder.

 

The withInterrupt() method takes a Gpio. This is initialised by the I2cButton which listens for changes on the GPIO. The main activity listens to key events from the framework by overriding Activity methods onKeyDown() and onKeyUp(). I’ve added three buttons with the addButton() method, this takes the IO port pin number and keycode of the button as arguments. I’m using KeyEvent codes from the Android framework. In my example code I’m updating the LCD display when key events are received.

 

 

LCD with button pressed

Conclusion

This experiment shows that buttons can be connected to the Raspberry Pi running Android Things preview image and hooked into the framework with KeyEvents. Button performance is acceptable and probably fit for purpose for navigation buttons, but maybe not good enough for game controllers or anything needing super fast button response. In a future experiment I plan to use GPIOs directly as button inputs, bypassing the PCF8574, to compare the speeds of the two methods.

Resources

Driver source code