My life with Android :-)

Saturday, December 23, 2017

Data from the light bulb

Once I read a blog post from Oona Räisänen that really inspired me. In her project she encoded a digital signal into the referee's whistle. I asked myself if there is any other household object that emits a radiation and could be used as a carrier for low-speed digital signal. I looked around and there was a light bulb.

Using light as signal transmitter is not at all a novelty. Beside all that optoelectronics stuff, recently Apple stirred some waves with their Li-Fi announcements that promises ultra-fast communication by means of a light bulb. I had something else in mind. I did not care about the speed, ad-hoc signal transmission of small data chunks that carry location IDs, sensor measurement was much more interesting for me. The use case would look like that you walk with your smartphone into a room lit by an innocently looking light bulb and presto, the smartphone picks up info from the light bulb without any special arrangement, e.g. you don't have to point your device anywhere. Speed and data size is of secondary concern in this use case which is a quite common scenario in the world of Internet of Things (IoT). Also, the light from the light bulb must look completely ordinary for human observer, e.g. no blinking, etc. This post is a tale of that adventure.

As I had prior experience with reading infrared signals from ordinary remote controls and sending them to the smartphone, I started with the method IR remote controls use to communicate with their receivers. Very shortly if you have not yet met this system: the emitter sends out period of "0s" (no light) and "1s" (IR light modulated by a certain frequency, typically 38 kHz). It is the length of these periods that carry the information. The common approach is that after a series of sync bursts, a digital 0 is encoded as a no light-light sequence of specified periods. A digital 1 is encoded similarly, except that the no light-light periods are different. You can observe this operation if you watch the light diode of an ordinary remote control through a smartphone camera. As the smartphone camera sensor "sees" in infrared (even though the manufacturers try to filter out this behaviour), you will see flashes of infrared light if you push a button on the remote.

Compared to the IR remote, we have an additional requirement: the human observer is not allowed to notice that the light bulb is doing something weird. For this purpose, I changed the modulation scheme. "No light" does not mean that the light bulb is switched off (that would result in a very annoying blinking sensation that humans are very sensitive to), only the modulation frequency is changed. In our system, the "light" periods are modulated with 38 kHz so that the popular IR remote decoder chips can be used, and the "no light" periods with 48 kHz. For the steep band pass input filters of those IR receiver chips, 48 kHz is essentially "no light". Considering the very noisy environment in the visible light domain, I also changed a popular IR modulation scheme, now the 0 bit is 564 microsec 48 kHz signal/564 microsec 38 kHz signal, the 1 bit is 1692 microsec 48 kHz signal/564 microsec 38 kHz signal. The whole payload is 20 bit long allowing to transmit a 16-bit value and a 4-bit data type selector. The data type selector lets the emitter send multiple types of data sequentially. In our demo, these are: station ID (for location), temperature and humidity (obtained from a DHT-22 sensor on the emitter board).

The system therefore consists of 3 elements: the emitter circuit that drives the light source, the adapter that receives these light signals and adapts them to the smartphone and finally the smartphone that acts upon those light signals.


  • In the prototype I am about to present the emitter is based on an Atmel Atmega328P microcontroller, in the form of an Arduino Pro Mini board.
  • The smartphone does not have light receiver and the Android application model cannot do real-time processing anyway so there is an adapter in between that on one side receives and decodes the light signals, on the other side interfaces with the smartphone by means of Bluetooth Low Energy (BLE). This element is implemented with two microcontrollers, an Atmega328P that does the real-time light signal processing and an nRF51822 SoC that deals with the BLE interface. As the nRF51822 is a quite capable ARM Cortex-M0 microcontroller, it is an interesting question why the light signal processing had to be offloaded to another microcontroller. The reason is the bad experiences I had regarding the real-time behaviour of the nRF51822 when its Bluetooth stack is operating.
  • The third element is a smartphone that connects to the receiver by means of BLE and displays whatever the adapter receives. This part is implemented in Android.
Let's start with the emitter. Below is the schematic (click to enlarge).






And this is how it looks like with the lighting LED beside the microcontroller card.






The source code can be found in this archive, in the light_sender/sketch subdirectory. You have to adapt the ARDUINO_DIR variable and probably the ISP_PROG and the ISP_PORT variables according to your programming tool. The AC input voltage may need to be adapted according to the lighting LED you choose. 38VAC effective value worked well for me for a wide range of lighting LEDs. The input voltage source also powers the microcontroller and this is really a sensitive area, I burnt a Pro Mini by screwing up something here. The problem is the large voltage drop hetween the LED supply voltage and the 3.3V that supplies the microcontroller. Before you insert the Pro Mini into its socket, make sure that VCC is 3.3V by setting TM1. Also, the Q2 FET has to be chosen carefully, the IRL540N type has drain-to-source breakdown voltage of 100V which is more than enough for this application.


The station ID (used for indoor location application) is hardcoded in light_sender.ino (STATION_ID). Optimally, every light bulb should have a different station ID.


Once the emitter is powered, it emits a steady 48 kHz signal which is "no light" in our encoding scheme. Every 1 second the emitter sends an encoded 20-bit value which is sequentially the station ID, temperature and humidity, the last two values are obtained from the DHT-22 sensor (U1). For the human observer, the light bulb is simply lit.


Now on to the adapter. Here is the schematic (click to enlarge).




And here is how it looks like.





The light receiver caused the most trouble for me. For starter, the photodiode required experiments. I played with 5 different diodes and eventually found the Osram SFH203 which worked well for me. If you cannot obtain this type, be prepared that you will also have to experiment. The next source of troubles was the IR receiver. Most IR receivers are integrated with the IR photodiode and these devices are made insensitive to visible light. Eventually I found VSOP58438 which has 2 problems: first it is obsolete and therefore it is hard to get, the second is that it is a 2mmx2mm square. Eventually my colleague helped me out and built a breakout board that you see in the foreground, with the Osram photodiode connected to it.


The rest is simpler. The Atmega328P (also provided in the form of an Arduino Pro Mini board) runs program that was originally designed as IR receiver. It can be found in this archive file (light_receiver/sketch/light_receiver.ino). The receiver library is Chris Young's IRLib with the timings modified for our modulation scheme. If the Atmega328P receives a value, it sends the value out on its serial output which you can observe SER_LIGHT_CODE pin.

The data goes into the nRF51822 SoC that I used in the form of a breakout board (here is an earlier post that describes the board and the development environment). Also, check out this post for instructions, how to compile and upload the project to the board. Here is the archive that contains the code for the nRF51822 SoC. The application in the nRF51822 SoC seems long but it is mostly boilerplate code, in reality its operation is very simple. Whenever it gets a value from the serial port, it writes that value into a BLE characteristic that has notification set. This means that whoever is subscribed to that notification, will get the event immediately, without polling the characteristic.


And finally, the reason why this topic is at all on an Android-themed blog: the detected values are consumed by an Android application. Click here to download the source code and read this blog post on how to convert the sources into an Android Studio project. The Android application is very similar with the previous ones, it scans for BLE endpoints with a unique UUID (274b15b0-b9cd-4e5e-94c4-1248b42b82f8 in our case) and when it finds one, connects to the endpoint using connection-oriented BLE. Then it subscribes to the light data characteristic (274b0100-b9cd-4e5e-94c4-1248b42b82f8) and when a new data comes from that characteristic, it evaluates the data type 4 bit and displays the lower 16 bit according to the data type.




Below is a small video showing how the thing works.




Observe the normal light sources and the small spot of smart light source that emits the data. The data is picked up from 3-4 meter distance.


Wednesday, June 14, 2017

Android weather station with a solar-powered BLE sensor

The ultimate test of the low energy consumption is a sensor that can survive on its own, without maintenance. My Android weather station supported by BLE weather sensors has been functioning for more than a year but this year has not passed without adventures in the battery front. First the station was powered by 2 AA NiMh batteries - that was 2 weeks of lifetime. Then came the motorcycle battery, that took much longer to expire but eventually the battery itself failed. Now the 2 sensors run on a discarded laptop battery which may not be able to power a laptop but powers nicely the two sensors with their combined 5 mA consumption.

5 mA, however, is a lot so when I found this solar-powered lamp at Jysk, I immediately realized that I had to turn the lamp into the solar-powered version of this weather sensor. Why another weather sensor? Because I wanted to concentrate on the solar-powering aspects and wanted to reuse as much as possible from the old sensor. This prototype may serve as a template, however, for different kind of sensors too.

Let's see first the solar lamp that I used as a base.




Solar lamp already containing the weather sensor. The two red LEDs indicate that the solar cell is charging the battery.

This is a quite cheap device with a solar cell on top and a circuit built around the XD5252F LED driver that takes care of everything from the charging of the small NiMh battery (if there's sunlight) to switching on the LED (if there's darkness). Unfortunately the circuit is so specialized to solar LED lamps that I could not reuse too much of it except for the solar panel and the LED itself. The solar panel is not very high-powered, it is a 2V, 20 mA cell. So it became clear immediately that the Android client app has to work more (consuming more energy) to obtain sensor data while the sensor has to sleep more to conserve its own battery that charges only very slowly from the low-powered solar cell. Also, surviving the night (or longer periods without sufficiently strong sunlight) requires a quite beefy battery in the sensor if we want it to transmit BLE messages to the Android application frequently enough.

Click here to download the sources of the Android application. Read this post to figure out, how to create an Android Studio project from the downloaded sources.

The previous Android app has been therefore changed so that instead of 15 seconds of scanning, it now scans for 70 seconds. The sensor sleeps 60 seconds then transmits the measurements for 5 seconds. This results in a quite low, 4 mAh energy consumption daily that even the low-powered solar cell can refill if sunny periods occur time to time. To make sure that the sensor survives long without enough sunlight, a 2700 mAh Li-Ion battery was installed (of the 14500 type, with the AA form factor). As in the previous version, the measurement data is transmitted in the BLE advertisement packets. I wanted to transmit battery indicator in this case too so I dropped one byte from the 8-byte long station ID (so it is now 7 bytes long) and instead of that byte now the supply voltage of the microcontroller is transmitted. It is generally 3.3V, if it drops below that then the battery is really not charging. This additional measurement data required that the sensor's UUID be changed, that's how the Android app recognizes this new parameter and displays in a graph.



Battery indicator in the measurement screen of the new sensor

The schematics of the sensor can be seen below (click to enlarge).







Sensor circuit installed into the solar lamp case

Nothing much changed from the previous version, except for the solar cell-battery charger power chain. I wanted to save myself the pain of designing a Li-Ion charger so I used building block already avalable: this DC-DC converter to produce 5V from the solar cell's varying output voltage and this battery charger circuit to take care of the Li-Ion battery. The result is a less than optimal efficiency (almost 50% of the solar cell's energy is lost during the different up-down conversions) but at least it is easy to reproduce. And if you like the sensor, you can always design a much better charging circuit. :-)

Click here to download the nRF51822 sources. Read this blog post for compilation instructions.

The nRF51822 microcontroller application has not changed a lot either. The most serious modification is the way the delays are implemented, now the sleeping periods between two measurements are implemented in a very low-power way and that results in a consumption in the inactive periods of about 100 microamperes.

And one thing more! Check out my low-cost robot project!

Monday, January 2, 2017

Adding more power to the BLE-enabled Christmas light

The truth is that the low-voltage LED strip I used in the previous post was a backup solution. Originally I bought a 230V-operated Christmas light with two independent LED strips but adapting that beast to Bluetooth Low Energy turned out to be a bit more problematic than I expected. I had to learn a bit about power electronics first.

My LED light I used as a base in this post is a standard-issue Chinese-made device. Below you can see how it looks like, its original controller already stripped of its plastic protective housing.



The circuit is very similar to this one, except that mine had only two LED strips, instead of 4. In my version the controller chip had HN-803 marking and the strip-controlling thyristors are of type PCR 406. The modes the original controller supported were all zero-crossing ones so I retained this operation.

Very shortly about the zero-crossing vs. phase-angle mode of controlling thyristors or triacs. A good introduction can be found here. The thyristor is fed with a current that has frequent zero-crossings. This is necessary because once the thyristor is switched on, the simplest way to turn it off is to remove the current on the load. That is why the Graetz-bridge converting the 230V alternating current into direct current does not have the usual filtering capacitors. This guarantees that the current feeding the LED strips/thyristors has zero-crossings with 100 Hz frequency. After the zero-crossing the thyristor can be switched on again by just a mA-range current applied on its gate electrode. The phase difference between the zero-crossing and the moment the gate current is applied determines whether we use dimming or not. Then the thyristor will remain switched on until the next zero-crossing. As the frequency of these zero-crossings is just 100 Hz, pulse-width modulation we used in the previous post for dimming cannot be used, the human eye would notice the flickering with such a low PWM frequency. So the simple circuit I am going to present here can only be used to flash the LED strips but not for dimming them. Implementing phase angle-based dimming would not be too hard with the features of our microcontroller but I did not want to get into that in this post.

Warning: part of the circuits described in this post use high-voltage 230 V current. Do not try to build them if you do not have experience with high-voltage electronics because you risk electrocuting!

Our exercise looks very simple. We need to remove the HN-803 controller circuit, replace it with our nRF51822 BLE SoC and use 2 of the output pins of the SoC to turn on the thyristors. Once the SoC drives the output pin to low, the thyristor will switch off at the next zero-crossing which allows us to flash the LED strips with frequencies lower than 100 Hz. Unfortunately nothing is simple if high-voltage current is involved because this simple circuit would connect the ground of the microcontroller board to a wire with high-voltage current (HVGND on the schematic) risking electric shock if someone touches the microcontroller board or ground-connected metal parts (like connectors) when the circuit is in operation. So I built an optocoupler-based isolator pictured below (click to enlarge).





The isolator ensures that the microcontroller-side has nothing to do with high-voltage current so no special precautions need to be done when handling the MCU board. The isolator itself, along with the remaining parts of the original controller circuit (D1-D4, T1/T2 and of course, LED1 and LED2 representing the two LED strips) are placed in a separate enclosure box. R3 dissipates around 1W so make sure that the resistor in question can withstand this power, I used a 2W resistor.

Driving the low-voltage side of the optocoupler still requires about 5 mA so I introduced additional FETs on the SoC side to provide this current. The updated circuit looks like below (click to enlarge). This circuit can control one low-voltage LED strip (with dimming) and two high-voltage strips (with no dimming) at the same time.




In my implementation the isolator and the MCU boards are located in two enclosure boxes which allows modular deployment - if there are no high-voltage strips then the isolator box is not needed. The connection between the MCU and the isolator boxes are 4 mA current loops which is quite resistant to noise. So the connecting cable could be  much longer than in the image below.




Now on to the software.

Click here to download the nRF51822 code.

Click here to download the Android code.

Compilation instructions can be found in the previous post. One warning: if you built the previous version and uploaded into the SoC, make sure that you mass-erase the chip (mass-erase.sh script provided in the download bundle) and upload everything again (soft device and updated application) because the BLE service description has changed and the nRF51822 SDK writes data into the flash about the service characteristics.

Again I propose that before you start to experiment with the Android application, test the BLE device with a BLE debug tool like the nRF Connect for Mobile. You will see that the high-voltage LED strips are controlled by a new BLE characteristic (the old one controlling the low-voltage strip is still available unchanged).



The byte array written into this characteristic is a blob that describes the light effect. The blob has two identical sections, each of them 9 bytes long. One section starts with 1 byte for the repetition counter then 4 times 2 bytes, each 2 byte subsection having 1 byte for the time duration (in 0.1 sec units) and one byte for the bit mask of the LED strips (bit 0->1 if LED strip #1 is to be on, bit 1->1 if LED strip #2 is to be on).

Regarding the Android application, there are no too many surprises. I used the now deprecated TabActivity because I did not feel like playing around with fragments for this simple prototype. The screen has separate tabs for the low- and the high-voltage strips like this:



The disconnection deficiency described in the previous post is still there. Make sure that you disconnect from the device after each manipulation (by pressing the Back button) because neither the device nor the Android application implements disconnection timeout so if you stay connected, nobody else will be able to connect to the LED strip controller. Otherwise have fun with these BLE-enabled Christmas lights!

Monday, December 19, 2016

BLE-enabled Christmas light

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.





Now on to the software.

Click here to download the nRF51822 sources.

Click here to download the Android sources.

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?

Tuesday, October 18, 2016

Android phone as weather station with improved sensor

The previous two posts introduced a BLE-enabled weather sensor (temperature and humidity) and the Android application that extracts data from this sensor. I hinted that I intend to proceed with a more sophisticated sensor, Bosch Sensortech's BME280 but other projects diverted my attention (shameless self-promotion: read this paper about microcontrollers, image processing and low-power wide area networks if you are curious, what kind of projects took my time). But I never forgot my BME280 temperature/humidity/pressure sensors sitting in my drawer and once I had a bit of time, I resurrected the project.

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.

Click here to download the Android application. Click here to download the nRF51822 projects that are running on the sensor hardware.

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

Android phone as weather station

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.

Click here to download the sources of the Android application. The content of the archive is the app/src/main subtree of an Android Studio project. In addition to extracting the sources into the app/src/main subtree, update app/build.gradle like this:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.jjoe64:graphview:4.0.1'
}


The project depends on Jonas Gehring's GraphView project, hence this new dependency.

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

Thermometer application with nRF51822 and Android

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.

This is how I stumbled into Florian Echtler's page about low-cost BLE development environment based on the nRF51822 and the Bus Pirate programming tool. So I quickly ordered a no-name variant of Waveshare's Core51822 breakout board, a Bus Pirate tool and a bunch of DHT-22 sensors (because I wanted to measure something in the environment). Also note that the breakout board has a connector with 2 mm pin spacing which is not the usual 0.1 inch pitch. It helps if you have a prototyping board with both 2 mm and 0.1 inch pitch like this one which cannot be found in every store.

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.






Click here (adv_dht22.zip (nRF51822), bledht22.zip (Android)) to download the example programs related to this blog post.

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.