It is often interesting to use a microcontroller with Android Things when you need some peripherals that require to send/receive pulses at a really fast frequency, or simply if you are too lazy to create a driver for a given peripheral when you are prototype something quickly.
If you are using, for instance, a DHT11 humidity & temperature sensor module, which sends pulses from 26-28μs (data bit “0”) to 70μs (data bit “1”), you will notice that it won’t work with the current version of Android Things which has a GPIO frequency around 3kHz (~300μs pulse duration).
Today, we will exchange data between an Android Things board and an Arduino over I²C for 3 reasons:
- This way of communication is easy to understand / implement
- I²C only requires 3 wires (Data “SDA”, Clock “SCL”, and Ground “GND”)
- You can connect multiple slaves to the same bus, so if you are building your own custom board and are already using I²C components, you won’t need to add another interface to communicate with the MCU.
Building an I²C fan
We will build an Arduino-powered fan. Using I²C, the Android Things master device should be able to:
- Turn on / off the fan
- Set the fan speed (low / medium / high)
- Get the current fan speed value
Android Things I²C methods
Here’s a sum-up of all the I2cDevice methods provided by the Things Support Library.
With those, you can read or write data (either one byte, two bytes, or as many as you want, in a buffer).
|Data size||Using a register||Read method||Write method|
Registers help understanding where you are reading from or writing to.
You can consider those as categories or actions. When you write some data to a register, it is easier to understand what will be impacted by this write operation.
In our project, we will use 2 different registers
Those 2 registers will be enough to perform the following actions:
|Action||Operation||Register||Data to write|
|Start the fan||Write||0x01||1|
|Stop the fan||Write||0x01||0|
|Set the fan speed||Write||0x02||150 (low), 200 (medium), 250 (high)|
|Get the current speed||Read||0x02|
writeRegByte(0x01, 1.toByte()) call in our Android Things project will turn on the fan, while the
writeRegByte(0x02, 150.toByte()) will set the fan speed to low.
Writing the Android Things driver
We can now write an Android Things driver for our I²C Arduino fan:
We only need to write around 20 lines of code for a full working Android Things driver.
Now we can call the following methods to start the fan, set the speed to high for 5 seconds, query the fan speed, then turn it off:
And we are done with the Android code. Let’s now write the microcontroller code.
Writing the Arduino sketch
We will use the Wire library that allows us to communicate with I²C devices.
First, our Arduino needs an address on the I²C bus, we chose arbitrarily 0x42.
Then we register 2 callbacks:
receiveEventis called when the master writes to this slave
requestEventis called when the master reads from this slave.
Dealing with registers
If you remember well, the
readRegByte(int reg) method from Android Things takes as argument a register.
However, as you may have noticed reading the code above, the
requestEvent callback from Arduino does not take any parameters, so how do we know which register is concerned?
When you call a method that involves a register, such as
receiveEvent callback from Arduino will first be triggered and we can get the register value from here and save it in a variable. Immediately after, the
requestEvent callback will be triggered, and since we know which register is concerned, we can send back the proper data.
|Android Things method||Arduino calls|
With this in mind, here’s the full implementation of the Arduino sketch, given the following constants:
The Arduino sketch is written and deployed, now we have to build the hardware.
Building the physical fan
Our fan is just a simple DC motor, so we will use the following components:
- DC motor
- PN2222 transistor
- 1N4007 diode
- 220Ω resistor
Let’s connect everything together and test it:
Connecting the Arduino to the Android Things board
Ok, it works.
To connect now the Arduino to the Android Things board via I²C, we simply need to connect the SDA, SCL, GND pins of the Android Things board and the Arduino together.
Careful: If your Android Things board is a 3.3V device (such as the Raspberry Pi 3 or NXP Picos boards), you will need a bi-directional level shifter for the I²C bus, so that inputs from the 5V Arduino won’t damage your board.
You can find the complete source code on GitHub:
In the following article, we will re-use this homemade device to demonstrate how we can connect multiple I²C devices to the same bus.