Making Rainbow HAT Work with the Android Things

Google's IoT platform has recently been updated with a couple of exciting new tools: Android Things and Weave. Android Things allows developers to use familiar Android dev tools, such as Android Studio, Android SDK and Google Play Services, to build hardware solutions for the IoT. Android Things can be installed on popular boards, such as Raspberry Pi 3 and Intel Edison, and comes with a Developer Preview of the SDK.

I'm totally new to the world of IoT, but I was quite intrigued by the announcement, so I decided to order myself one of the supported boards and tinker with the SDK. My choice fell on the Raspberry Pi 3 with the Rainbow HAT set of peripherals: it's officially supported by the Android Things project, and most of the samples inside the official GitHub repo play really well with this setup. Rainbow HAT is a fun little piece of hardware to program, here's just a subset of niceties it includes:

a set of multicolor LEDs

an alphanumeric display

three capacitive touch buttons

a piezo buzzer

temperature and pressure sensors and more

The device itself comes with a Python library and a number of samples, available on GitHub. I decided to grab the demo.py sample and translate it into an Android Things project. This exercise helped me understand how the SDK works and play with various device drivers. This article will guide you through the process of setting up an Android Things project and adding code to interact with various peripherals. But first, let's see the demo!

Ahoy Rainbow HAT!

Here's what the Rainbow HAT demo looks like:

We're doing a ton of fun stuff here:

playing a melody using the piezo buzzer

blinking RGB LEDs along with the melody

changing the text on the display in response to button touch events

That looks like a lot, so let's break this functionality down into pieces and see how the interaction with different hardware components works.

Adding the libraries

First of all, let's add all necessary libraries to our app/build.gradle file:

We'll need the main Android Things SDK dependency, and a number of driver modules for hardware components that we'll be using. Notice that we're declaring the SDK dependency as provided instead of the usual compile: this means that the SDK is a compile-only dependency and will not be packaged along with the app, at runtime our code will run against the version of the SDK that's present on the device.

Creating the RainbowHATDemoActivity

Cool thing about the Android Things SDK is that IoT apps follow the same structure as the usual Android apps. This means that with some modifications you can make existing apps run on embedded hardware, which sounds pretty cool. This also means that the entry point to our IoT app will be a good ol' Activity class, so let's create one (code examples are presented in Kotlin, which I hope you're familiar with):

We're using the ButtonInputDriver class to map each button, represented by its GPIO pin name, to a keycode value from the KeyEvent class, and register the driver with the system. Names for all Rainbow HAT pins can be found on the official Pinout page. We're also introducing the close() method, since it's important to unregister the drivers when the app doesn't need them anymore. After we instantiate Buttons inside the RainbowHATDemoActivity, we'll be able to listen to key presses inside the onKeyUp() method:

We're using the AlphanumericDisplay class, which has very straightforward API and can easily display a String. Still, it's important to not forget to clear() the display after we're done, otherwise the text will remain displayed even after our app gets closed.

At this point, we can already publish messages to the display and react to button clicks, so let's put this functionality to use. First let's define some fancy messages inside RainbowHATDemoActivity:

Each LED is represented by an instance of Gpio, and we use PeripheralManagerService to obtain instances using GPIO pin names of each of the LEDs. Once we've got those, we set their initial state to Gpio.DIRECTION_OUT_INITIALLY_LOW. Then, turning an LED on or off is just a matter of setting its value to either true or false. Same as with the other devices, it's important to disconnect them after they're not needed anymore, therefore we introduce the close() method which closes each of the LEDs.

We're almost there, let's now connect the last piece of hardware - the buzzer.

We rely on the Speaker class to implement the functionality. Speaker has a play() method, which takes a frequency value and plays a sound at that frequency. The sound will play until stop() method is called. Since we'd like to have pauses between sounds in our demo, we'll introduce another version of play() that takes a duration parameter, and uses a Handler to post a stopRunnable. close() contains code for stopping and closing the speaker instance.

Putting everything together

Now that all our drivers are ready, we can play a melody at startup and blink the LEDs. First, let's instantiate remaining classes in onCreate():

NOTES and TIMES contain sound frequencies and playback durations respectively. We're using a Handler and looping until all the notes are played. Each iteration will also turn the LEDs on and off, one after the other. Job well done!

Last but not least, we have to close all resources we've been using when our Activity gets destroyed:

Conclusion

This article described the process of setting up an Android Things project and programming various hardware components to perform a number of different tasks. What's great is that we achieved it by using familiar Android development tools, thanks to the Android Things SDK and the driver libraries.

Playing with Rainbow HAT is super fun, and its wide range of peripherals provides a great opportunity for learning about different Android Things driver libraries. If you're thinking about ordering hardware to play with Android Things during the holidays - I can highly recommend the Raspberry Pi 3 + Rainbow HAT setup. Enjoy Android Things, and Happy New Year!

If you've enjoyed this article, please don't forget to share it with your network using one of the buttons below. If you've noticed any mistakes in the code or the terminology used in the article, please don't hesitate to add a comment - I highly appreciate your feedback!