Monday, December 19, 2016

The idea came from the light-themed Budapest
Makers' Meetup and from the cheap Christmas LED strip that my
wife bought for about 1 euro. Plus my other hobby project has not
gone as smoothly as expected but produced a connection-oriented
nRF51822 code and bang, the idea was born, let's couple the LED
strip with the Bluetooth Low Energy System-on-Chip (SoC), add an
Android application and let's see what comes out of it. This post is
the tale of that adventure.

First, about the LED strip. This is a battery-operated device with
two states: off or on. It has surprisingly low power consumption
considering its 10 LEDs.

I removed the battery case and put it away
- it will serve me well in other projects. Then I hooked up the LED
strip with the nRF51822 as shown in the schematics below (click to enlarge).

As described in some
previous blog posts, I use a breakout board containing little
more than a sole nRF51822 and the Bus Pirate programmer to upload
the application into the chip. The components on the breakout board
(quartz, etc.) are not shown in the schematics. If you use the same
type of breakout board that I do, make sure that you connect both
GNDs together otherwise instability may be the result.

Other than that, the circuit is very simple. The LED strip is driven
by P0.22 of the nRF51822. Even though the strip consumes in the mA
range, I played safe and inserted a 2N7000 FET between the MCU and
the LEDs. The 1 Ohm resistor was already part of the circuit in its
original form so I thought it is a good idea to preserve it. One can
also observe the 3.3V stabilizer circuit that transforms the
POWER_INPUT (5V in my case) to the 3.3V consumed by the circuit. Any
stabilizer circuit will do, I just point out that without the C1
condensator I experienced instability when the Bluetooth radio was
in operation. The whole circuit sits nicely in a plastic electronic
enclosure box.

The programmer software that drives the Bus Pirate tool is the same forked version
that we
used before. The project assumes the 12.1.0 version of the
nRF5 SDK. I propose
that you stick to this version too because upgrading the project to
another version may involve a lot of work (as I experienced
previously). Convert the soft device with the convert_s130.sh
script, upload into the device with the upload_softdevice.sh,
compile the code with the "make" command then upload the application
with the upload.sh. While doing this, you need to modify SDK path
and device files in the scripts/Makefile according to the directory
layout of your system. After a power cycle, you can observe the
device spitting out a large amount of debug messages on the debug
serial port. Also, LED1 starts flashing showing BLE advertising
activity.

Before installing the Android part, let's check that the device
works correctly. Download nRF
Connect from the Google Play store, start scanning for BLE
devices, look for "ledctr" (the default name given to our device),
connect and open the custom service with the 128-bit UUID of
274b15a4-b9cd-4e5e-94c4-1248b42b82f8 that it advertises. You should
see something like this:

Write the following byte array into the characteristic with the UUID
of 274b0000-b9cd-4e5e-94c4-1248b42b82f8.

036000000000000360

This means 3 seconds ramp-up to 0x60 intensity (96%), no flashing, 3
seconds ramp-down from 0x60 intensity. If you see this light effect,
the device is ready. Don't forget to disconnect: the application can
handle only one active connection and there's no timeout mechanism
implemented.

The BLE device implements the following light effect. First there is
the ramp-up phase when the light intensity increases from 0 to a
maximum. The ramp-up time and the maximum intensity can be set by
means of BLE. Then there is the flashing phase when two states with
different intensity come one after the other. The repetition
counter, the length and the intensity of both states can be set.
Then there is the ramp-down phase, when the intensity goes down from
a maximum to zero. Here again the ramp-down time and the initial
intensity can be set. All these phases are optional, if any of the
time value is zero, that phase is skipped, if the repetition counter
is zero then the flashing phase is skipped entirely.

The LED strip is capable of only on and off states hence the
intensity effect is implemented by means of pulse-width modulation
(PWM). The BLE application operates a 100 msec timer that updates
the timeouts, intensity changes and state transitions. Look for the
light_update_timer_handler function in main.c if you want to modify
that functionality.

In order to create the Android project, follow
the instructions in this blog post. Essentially you have to
create an empty Android Studio project then replace the source tree
under app/src with the content of the ZIP file that you downloaded
previously.

The Android application has two major parts. First, it scans for BLE
devices that advertise that unique UUID that I allocated to the
application and lists those devices in a List. If the user clicks
any of the devices, the Android application connects to the LED
controller service with the unique UUID I mentioned before,
retrieves the current state of the light effects and displays it by
means of some SeekBars. The user can manipulate these parameters
then update them on the device by pushing the "Set values" button.
The device then starts to perform the light effect. The user can
disconnect by pushing the "back" button.

One major deficiency of the application is that disconnection
timeout was not implemented, neither in the device part, nor in the
Android application. This means that the user has to take care that
he/she disconnected from the device after modifications to the light
effects were done. If that does not happen, the device stays forever
in "connected" state which means that it will be impossible to
connect to it again without resetting the device. I leave this
exercise to the interested reader. :-)

The other problematic part is the lack of security. Anyone knowing
how to connect to the device (either by knowing the format of the
light effect blob or by just simply having the Android application
installed) can manipulate the light effect. Personally I don't think
it is a major issue because security can always be added later.
Beside, what could possibly go wrong if a passersby can just change
the light effect in my window?

The idea is the same as with the DHT-22. The nRF51822 combined ARM
Cortex-M0 microcontroller/Bluetooth Low Energy radio unit will make
the sensor data available over Bluetooth Low Energy (BLE) access.
The smartphone will read this data and display it to the user. Later
(not in this post) I intend to upload the data into some web service
for analysis. We have already done this with the DHT-22, now we
extend the sensor range with the BME280.

Let's start with the sensor. Below is the schematic for the
hardware (click to enlarge).

The difference between this and the previous one is that the DHT-22 was
connected to a simple GPIO pin while the BME280 uses the more
sophisticated I2C bus. As the BME280 is quite miniature, I used a breakout board for the sensor too.
LED1 and the serial debug port are optional (but quite useful). Debug
messages are emitted to the serial port, you need a 3.3V-to-RS232
converter on the TxD pin if you want to observe those.

As
described previously, the circuit is realized with a low-cost nRF51822 breakout board and is programmed with the Bus Pirate programmer, adapted to nRF51822 by Florian Echtler. The only thing I changed in this setup is that this time I moved the projects to the latest version of the SDK which is the 12.1.0.
Also, the soft device (the program module implementing the BLE stack)
was bumped from S100 to S130. These decisions caused quite a headache
because there's significant difference between the old SDK and the
12.1.0. Therefore I decided that in the nRF51822 project file I share
not only the sensor project (called adv_bme180) but two simpler ones
(blinky_new and blinky_new_s130) as additions to the instructions on
Florian's page. As a recap: the soft device need to be flashed into the
device before any BLE application is flashed and the starting address of
the BLE application depends on the size of the soft device. This has
changed between S100 and S130, hence the updated projects. In both
blinky_new_s130 and adv_bme280 you will find the convert_s130.sh and
upload_softdevice.sh scripts that convert into binary format and flash
the S130 soft device that came with the Nordic SDK.

Once you uploaded the S130 soft device, compile the project in
adv_bme180 and upload it into the nRF51822. The sensor node works the
same way as the DHT-22 version. The MCU in the nRF51822 acquires
measurements from the BME280 by means of the I2C bus (called Two-Wire
Interface, TWI in the nRF51822 documentation), once in every second.
This includes temperature, humidity and pressure. Then the measurement
values are compensated by the read-only calibration data also stored in
the BME280 that the MCU reads in the initialization phase. The
BME280_compensate_T, BME280_compensate_P and bme280_compensate_H
functions come from the BME280 user's manual. The result is the
compensated temperature, humidity and pressure values that the MCU puts
into the BLE advertisement data. The advertisement data also contains
the nRF51822's unique ID that is used to identify the sensor. The sensor
has no name as the measurement+ID data is now too long to allow sensor
name info too, BLE readers now recognize the sensor purely by its unique
UUID.

Now on to the Android part. The architecture of the application is pretty much the same as described in the previous post.
Creating an Android Studio project works the same way as described
there: create an empty Android Studio project, write over the
app/src/main subtree with the content of the archive that you downloaded
from this post and update app/build.gradle file with the GraphView
dependency.

The BME280 functionalty was inserted in three places. First, BME280 data
has its own data provider (BME280SensorDataProvider.java). This new
provider is able to handle pressure data that DHT-22 measurements don't
have. BLESensorGWService properly recognizes BME280 sensor nodes beside
the DHT-22 sensor nodes (so both are handled), parses BME280
advertisements and puts the measurement data into the BME280 data
provider. MainActivity knows about the BME280 data provider, uses its
data to create the sensor list and invokes
BME280GraphMeasurementActivity if the sensor in question is BME280
sensor. This new visualization activity has pressure graph too.

This is how the sensor list looks like with a DHT-22 and a BME280 sensor (DHT-22 does not have pressure data, BME280 does).

And this is how the pressure graph looks like in the BME280 visualization activity.

And at last, some words about the deployment. I got a question, how the
power supply works. After more than half a year of operation, I ended up
with a discarded 12V motorcycle battery as power source. This battery
used to have 6Ah capacity, now it has about half which is not enough to
feed a motorcycle but is quite enough to yield 1-2 mA per sensor node
for a long time. Also, this battery is designed to withstand quite
severe weather conditions. I can only recommend discarded but still
functional motorcycle/car batteries as power source if the place
available for the sensor permits it.

Here is how the BME280 sensor looks like in its protective plastic box. The small panel in the foreground is a cheap DC-DC converter (not shown in the schematics) which makes the step-down from 12V to 3.3V.

And here is how the sensor nodes sit in an outdoor box with the battery.
The lid of the BME280 node is removed for demonstration, the other box contains the DHT-22 sensor.

Now the part that is really missing is the data upload/data analysis functionality.

Wednesday, March 2, 2016

The previous
post was about a low-cost Bluetooth Low Energy sensor (really,
one sensor unit that includes the BLE-enabled microcontroller too
costs less than 15 USD and that's just a single prototype, economies
of scale come on top of that) and its accompanying Android app that
allows obtaining sensor reading manually. That's not bad but
manually reading data is sort of inconvenient. If you want to know,
what the temperature and humidity was in the dawn, you have to be
awake in that early hour. Personally, I prefer to sleep then so I
decided to automate the whole process.

So what can we expect from this new app? In case of the app that
came with the sensor in
the previous post, you started a manual scan and if the sensor
was in range, you got the humidity/temperature data. The new app
scans and stores data in the background. Once it is started, it sets
up a periodic timer (default timeout is 1 hour but can be changed in
the settings menu) and when the timer fires, it makes a scan. If it
finds a BLE node whose advertisement fits our criteria (e.g. it
advertises services with the UUID I allocated) then it extracts the
measurement data from the advertisement message and stores it in a
database on the device. This variant does not yet upload the data to
a server, that may come later. However, it can visualize the
measurements on simple graphs, hence the dependency on GraphView.
Like this:

Let's see the interesting bits of this app.

First and foremost, it is an interesting feature of this application
that the BLE layer is used in such a way that reading the sensor is
not an extra cost for the sensor. As the measurement data is
embedded into the advertisement packets that the device broadcasts
anyway, it does not matter if 1 or 1000 phones read and store data.
So this sort of sensor network can grow into an entire ecosystem -
the more phone users install and use the app, the more precisely the
measured quantity will be available once the phones upload their
catch to the server.

If you observe, how the data is stored
(DHT22SensorDataProvider.java), you can recognize an important
shortcut that I made: the database structure depends on the sensor
being used. This provider depends on the fact that DHT-22 (the
actual measurement device) provides temperature and humidity data in
the same reading. A different sensor (like the Bosch BME280 sensors
sitting in my drawer waiting for their turn) will require a new
provider and also a modification of the visualization part. So
there's significant development potential in making the app more
flexible when it comes to adding a new sensor type.

The actual sampling of the service happens in BLESensorGWService
using the AlarmManager to trigger the scan. Now getting the device
awake if it was just sleeping is not a simple business. Observe in
the list below, that even though there's always an hourly reading,
there's a significant variation when the reading happens.

In case of
our weather reading, it was not a problem but some sensors may have
more variable data. A large number of devices reading and uploading
would solve the problem of reading time variations.

GraphMeasurementActivity is the activity that depends on Jonas
Gehring's GraphView. The graphs are very simple so if you have
another favourite graph view component, just replace it there.

So we are at the point that we added sensors to our Android device
using Bluetooth Low Energy and created an application that samples
them producing nice weather-related data series. The next step will
be the integration of a cloud-based data analysis. I am still
thinking, which one to go for.

And finally, the picture of the sensor, in its "weather-resistant"
box.

Tuesday, February 2, 2016

I built quite many prototypes on this blog with RFDuino
based on Nordic Semiconductor's nRF51822 and I can still recommend
that small development board to people who want to get initiated
quickly and painlessly into the world of Bluetooth Low Energy
programming. The limitations of RFDuino became apparent quite soon
and it was time to get deeper. On the other hand, I wanted to stay
with the excellent nRF51822 so I looked for a breakout board - as
simple as possible.

Generally speaking, following the instructions on Florian's page was
easy enough. I ran into two issues. First, I had no success with the SWD
programming software he refers to but Florian's fork
(which is based on an earlier version of the programming software)
worked well for me. Second, I experienced instability if the GND pins of
the breakout are not connected (there are 2 of them).

First about the hardware. The schematic below show only the parts that are connected to the pins of the breakout board, the schematic of the breakout board itself is not included.

Highlights:

DHT-22 is connected to P0.17 which is both input and output depending on the communication phase.

P0.21 LED provides a feedback about the BLE activities. This is a
convention coming from the PCA10028 dev board that we lied to the Nordic
tool chain that we have. You can omit this LED if you want to save some
energy.

SV1 header is a TTL serial port where the example program emits
some debug messages. You can omit this header if you are extremely
confident. I use a level converter like this to connect this port to a standard RS232C port. The UART operates on P0.18 (RxD) and P0.20 (TxD).

SV2 header goes to the Bus Pirate. Check out Florian's document
about the connection. Make sure that this cable is as short as possible.

Here is how the board looks in all its glory, the Bus Pirate and the
RS232C level converter boards in the background. These are of course not
needed for deployment, the board runs standalone after the testing is
successful.

Let's start with the code that goes into the nRF51822 which can be found
in adv_dht22.zip. The assumption is that you completed Florian's
instructions, including the upload of the S110 soft device. Then unzip
adv_dht22.zip and do the following modifications:

Edit Makefile and make sure that the RF51_SDK_PATH variable points to the location where you installed the Nordic SDK.

Edit upload.sh and make sure that the paths point to the location
where you installed Florian's version of the SWD programmer. Also, make
sure that the USB device is correct (/dev/ttyUSB0 by default).

Now you can say "make" and then "upload.sh". If all goes well, the code
is installed in the nRF51822 and you get debug messages on the serial
port. At this moment, the nRF51822 is already advertising the
measurements it obtained from the DHT-22 sensor. You can check the
content of the advertisements with this test tool.

The code looks quite frightening compared to the super-simple RFDuino equivalent but most of it is just template. My highlights:

Check out in advertising_init(), how the advertisement packet is
set up. We transfer the measurements in a service data GAP field and I
took the liberty to allocate a 16-bit UUID for it (quite far from the
standard service UUIDs).

Check out timers_init(), timers_start() and
sampler_timer_handler() methods how the periodic reading of the sensor
and the update of the advertisement packet is accomplished.

DHT-22 sensor handling is done in dht22.c. This sensor has a somewhat peculiar 1-wire interface. Read this document and the code will be easy to understand.

Regarding the Android code: this is just the app/src part of the source
tree of an Android Studio project. I adopted this rather primitive
export method as this super-advanced IDE still does not have code export
option that its obsolete predecessor, the Eclipse IDE used to have.
Check out onLeScan method in MainActivity.java to see, how the BLE GAP
parser introduced in this blog post is used to take apart the advertisement message and filter BLE nodes that advertise DHT-22 measurements.

The outcome looks like this:

Note that each sensor is identified by a 64-bit unique ID (a service of
the nRF51822). Now this data just needs to be uploaded into some sort of
service and then the big data analysis can start ;-). More about that
later.

Thursday, January 7, 2016

The three previous parts (here, here and here)
of this series introduced the infrared-to-Android gateway. Even though
those prototypes captured the signals of an ordinary IR remote, I
already hinted that I was aiming for something more exciting. In this
part, we will replace the IR remote with our own IR transmitter. Once we
have our own IR transmitter, we will be able to transfer our own data
over IR light. This data link is not reliable enough to transfer large
amount of data but in lot of the cases that's not required. E.g. to
transfer the data of a temperature/humidity sensor, 32 bit is more than
enough.

So what can we expect from IR-based data transfer with respect to more
popular, radio-based transfer? There are advantages and disadvantages.

Advantage for the IR solution is that it is extremely cheap and also extremely power-efficient.

Advantage for radio is that IR-based solution always requires line
of sight, while radio waves can - to some extent - traverse walls, etc.

Advantage for radio is that the IR transmitter has to be aimed at
the receiver, if for some reason the receiver and the transmitter move
with respect to each other, they lose contact very easily.

There's also the question of range. Ordinary TV remotes work up to 3-4
meters of distances which is nice for an inexpensive consumer device but
is not enough even for indoor sensor network use cases. In this part I
try to figure out what the distance limit may be.

For starter, this question is not defined precisely. With sophisticated
optics, high-powered transmitters and careful targeting, IR data
transfer can be accomplished over significant distances. But we said
that we are looking for cheap hardware so we can't rely on sophisticated
devices. We need some sort of optics but this should be simple and
cheap. That's why I went to a second-hand toy shop and bingo, I found
the IR transmitter of Thinkway Toys' Lazer Stunt Chaser.
The small toy car has long been lost, but the handgun-like IR
transmitter somehow made its way to Hungary. This cheap, plastic toy is a
marvelous device. It promises 12 meters of effective range and even
though the mounting of the IR light source and the plastic optics is
made of cheap materials, it is surprisingly efficient. It even has a
normal (red) LED emitting its light through the transparent housing of
the infrared LED which produces visible red light circle of about 10 cm
of diameter facilitating the targeting of the IR transmitter.

So how far can it transmit our IR codes? In order to try it out, I took
apart Thinkway's IR transmitter and replaced the circuitry driving the
IR LED with mine. The new emitter circuit is based on an Arduino Pro
Mini 3.3V/8MHz and the schematics looks like this:

The software works on any Atmel ATmega328p-based boards, e.g. on Arduino
Uno. If your MCU uses power source with higher voltage than 3.3V, adapt
R2 accordingly. E.g. for an 5V Arduino Uno board, you need about 160
Ohm.

So this is how I hacked my circuit into the IR transmitter.

Note the two LEDs: the IR led in the tube-like mounting and the ordinary
red LED behind it that is used for targeting. Also, note how the IR LED
is connected to the ATmega328p's PD3 pin - IRLib which is the software
used to construct the transmitter selects OC2B PWM output so the primary
Timer2 PWM pin (PB3) would not work.

Open sketch/Makefile and update the ARDUINO_DIR according to your
installation. Also, update ISP_PROG according to the programming tool
you use to deploy the code. I used USBtinyISP,
the Makefile is set accordingly. If your board has USB programming port
(like the Arduino Uno has), then setting ISP_PROG is unnecessary.

In order to deploy the code into the ATmega328p, say:

make ispload

if you use a programming tool or simply

make upload

if you don't need a tool.

About the code. The application emits a 32-bit NEC IR code every 4
seconds. The value of the code is increasing. The application is based
on the same IRLib library
as the receiver was, this time the only modification necessary was that I
disabled all the receiver routines as this device does not receive any
data. And that's my response to all the people worrying about the
security of the Internet of Things: if the Thing is physically unable to
receive any data then it cannot be hacked, period.

Even though this application is not particularly energy-efficient, care
was taken to implement the sleeping part with the lowest possible energy
consumption. Hence the delay logic does not use the Arduino delay()
function but puts the MCU into deep sleep and triggers the watchdog
timer to launch a new iteration. Read Nick Gammon's excellent analysis of ATmega328p power saving techniques for further explanation.

So what are my experiences? Using the infrared-to-Android gateway I
presented previously which is based on a basic IR receiver circuit
(TSOP1738) without any optics and the IR transmitter hacked into a
Thinkway toy, which uses cheap plastic optics, I was able to transmit
codes to a distance of about 10 meters (and then receive the code on the
Android device over BLE). Of course, not every transmission was
successful. My experience is that the code needs to be repeated about 5
times if you want to be nearly 100% sure that it arrives (100% can never
be achieved). One important take-away is that the targeting LED in the
Thinkway toy was not there by chance, in order to target the IR
receiver, you really need that aid of visible red light circle. But
that's about it: 2 LEDs, a cheap MCU and some optics and you can connect
sensors from an entire room to one relatively expensive BLE unit. Also,
these IR-connected sensors need very little energy. So it is worth
considering the advantages/disadvantages.

About the blog

This blog is a personal diary about my adventures with the Google Android platform. I write it in the hope that others may find my experiences useful but please, beware. The blog is created as I gain experience about the platform myself so errors, omissions, etc. may be found in the entries.