I want to add a new sensor type to Android Things using the user-space driver extension mechanism provided by the API. The new sensor type is ‘Distance’ and comes from a Laser Range Finder (LRF) connected via a UART. The goal for this project is to read data from the LRF over a UART, add ‘distance’ from the LRF as a new type of sensor, and display the distance on an LCD.

This task is about adding a new sensor type to Android Things. This is something you can’t do in Android (without modifying AOSP and building your own ROM) so I’m interested to see how the process goes.

The Setup

The setup is similar to my previous experiments with the addition of a laser range finder.

  • Raspberry Pi 3 running Android Things preview image 1,
  • LCM1602 (clone),
  • character LCD,
  • level shifter for I2C,
  • laser range finder.

Disclaimer: I have access to this LRF because I work for the company that makes them. This is not something you can buy off the shelf.

Using the UART on the Raspberry Pi

In the Android Things preview image for the Raspberry Pi, the UART is used for kernel console output. To use it to connect to a peripheral you need to disable this output as described in this StackOverflow answer.

Adding a new sensor type to Android Things.

In Android proper you are limited to the sensors already defined in the framework. This means that if you want to add a sensor that’s not defined you have to modify the framework to add you own, create a driver for it, and build your own Android image.

In Android Things there is a new extension mechanism that lets you create sensors without modifying the framework. You can use the user-space driver mechanism to add your own instance of an already existing sensor type, or you can add a completely new sensor type.

Reviewing the defined sensor types you can see there is no distance sensor type. The closest is TYPE_PROXIMITY which can give you a range in centimetres. A laser range finder can give you a distance of many, even hundreds, of meters so I don’t think ‘proximity’ is quite the right type.

The Process

To add a new sensor to Android Things you create a UserSensorDriver to return a UserSensorReading when polled by the system, create the UserSensor defining your sensor’s parameters, and register it and the driver with the UserDriverManager.

Creating a User Driver

To add a new sensor you need to write a driver for it. The details of this will depend on how your sensor is connected to your board. The LRF I am using is connected to the Raspberry Pi via a UART and provides a ‘sort of’ NMEA interface. The LRF periodically sends a distance measurement over the UART to the Raspberry Pi. My driver reads this distance measurement and provides the framework with an updated distance when polled. The key this is to create a UserSensorDriver and implement the read() method. You can also control power to you sensor by implementing power control in the setEnabled() method of UserSensorDriver. For the moment I’m not implementing power control features, but I could have  GPIO control power to the LRF here if it was connected to a controllable power supply.

My driver saves the latest distance provided by the LRF and converts it to a UserSensorReading, which takes an array of floats.

Creating a UserSensor with UserSensor.Builder

The Android Things API provides a builder you can use to describe the features of your sensor. This lets you set the type, name, vendor and other parameters. It’s also how you associate your driver implementation with your sensor. In my case, since I am creating a sensor type that doesn’t exist in the framework, I’ll use the customSensorType() method of the builder to tell it about my sensor type. The builder creates the UserSensor that will be registered with the framework later.

LRF_SENSOR_NAME, LFR_SENSOR_TYPE, and LRF_SENSOR_VENDOR are just strings I’ve defined in my driver.

Registering the Sensor with the Framework

Once UserSensorDriver and UserSensor objects are created, register the new sensor with the framework.

That’s it for the driver side. Now, from the sensor consumer, I need to access the new sensor.

Accessing the Sensor

To access your sensor you implement the SensorEventListener interface, as you would normally with Android, and register to receive updates from the SensorManager. The only slight complication with Android Things is that your sensor may not exist when you ask the sensor manager about it, especially if your driver and consumer code are in the same process. You can wait for your driver to be registered and available by implementing a SensorManager.DynamicSensorCallback

and registering it with the SensorManager

Once that’s done and everything is registered I use the sensor reading in my main activity. In this project I’m displaying it on the LCD using my things-drivers.

Go Outside and Play

Once the driver is setup and working the next thing any budding IoT enthusiast should do is bolt it all to a piece of wood and point it at something far away 🙂

 

 

How far away is that?

That’s far.

Conclusion

In this experiment I’ve defined a new sensor type in Android Things, created a driver for it using Android Thing’s use space driver mechanism, and pointed lasers at houses in my neighbourhood.  The Android Things user space sensor driver mechanism does what it says on the box. Good job Android Things! Now I need to find a shark to bolt this laser to…