Skip navigation
1 2 3 Previous Next

In the Air Design Challenge

36 Posts authored by: amgalbu Top Member

This will probably be my last post  for this challenge as I will leave tomorrow morning for a business strip and returning next monday.

hen I experiment, when I test new components and ideas, and also every time I fail, I have fun. So this challenge was really funny to me!


This is my second challenge. The first one (ForgetMeNot) was bit disappointing to me because I have not been able to focus on the challenge requirements. On the contrary in this challenge, in my opinion, I met the requirements and I have been able to work out a working project (obviously with all the limitations due to both limited time frame available and limited personal skills). In more detail


Use of components and services from the sponsors


Texas Instruments


The MSP430FR5969 is the heart of the AirMobile sensor. It's really a good MCU, shipped with good development tools. "Thanks" to delays in the shipping of some components, I had the opportunity to dig into some interesting feature like FRAM retention, in-RAM execution and code protection


Wurth Elektronik


From Wurth, I got the transformer for interfacing the Peltier cell to the step-up converter. Also, they made the AirMobile sensors PCB. In this case, I appreciated the quality of the PCB and the timely delivery




All the data is stored to and retrieved from the Sierra AirVantage cloud infrastructure. Even if I initially was a bit perplexed because it was not possible to subscribe to data changes, I then realized the rationale behind that choice. Use of REST API make the AirVantage cloud easily accessible from any platform. Also the use of an XML document to describe data assets makes the tool easy to configure for your own application






Low maintenance


The requirements asked for "low maintenance (for example no need for battery)". I tried to push this requirement to the extreme by completing removing batteries and rely only on energy harvesting. Should I go back in time, I will add a backup battery. According to the experience I made, energy harvesting through a Peltier celle is not enough to provide reliable operations in all conditions. Even If I designed the board to use delta-T on Peltier cell's faces as low as 30 degrees, I think it would be very difficult to achieve this in a hot summer day. Also, operations are unreliable when you slow down and there is not enough airflow to cool down the cold face of the cell


Smartphone app


With some minor changes, I adapted an existing application to push data to AirVantage cloud. App lloks good and provides a lot of interesting features




Thanks to the OpenHAB platform, adding automation based on collected data was not a huge task. I developed two bindings: one to get data from the AirVantage cloud and one to drive a servo control

In this post, a complete overview of the implemented solution will be provided


Data collection

The first step is to collect data by simply driving around while the smartphone app records data



Pushing data to the cloud

When data is stored on smartphone, t can be analyzed on the msartphone itself and eventually pushed to the AirVantage cloud



Data visualization

Data store in the AriVantage cloud can be seen by means of a web application. Here only a quick overview is shown. For details about the data map, please check this post




Using data read out from the AirVantage cloud, it's possible to create automatic controls. In this example, I show how to drive a servo control to move a gauge. In a real application, an output could be driven to close an air intake or to adjust the speed of a fan


After recording this video, I closed down the bonnet with the intent to go around and collect some data. But as soon as I closed the bonnet, AirMobile sensor disconnected from the smartphone. I reopened the bonnet, and connection was back

The problem was clear, the reason less. I didn't expect the steel of the bodyshell to shield Bluetooth 2.4 GHz frequencies to that extent

In my opinion, the possible causes could be


Antenna / module position: the Bluetooth module was placed between the LaunchPad board and the AirMobile board. While the LaunchPad has a ground plane, the AirMobile hasn't. But the LaunchPad in on the "line of sight" between the Bluetooth module and the smartphone, so the ground plane could actually act as a shield

Bodyshell grounded: the steel the bodyshell is made of shields Bluetooth frequencies more than I expected because the bodyshell connected to the ground. I assumed that the simple equation "tyre = rubber = insulation" is not completely true. I found out that tyre's compound contains a certain amount f graphene (to reduce internal friction and hence fuel consumption) and graphene is a conductor...

High-frequency noise due to sparks: the last hypothesis is that high frequency noise are produced by the electrical system of the engine, in particular by the high voltages involved in generating sparks


Because I was not able to determine the root cause, I moved the Bluetooth module outside the case and placed it directly on the bonnet in a protective bag



This is the video of the first run of the AirMobile sensor installed in a real car



The crucial moment has come: it's time to install the board in a real car

Here is the sensor mounted in the car







The case is fixed to the bodyshell by means of plastic strips. The cell is kept in contact with the radiator using a spring bolt to an existing shell screw...

Installation does not look very professional, but I accumulated so may delays due to hardware problems I has not enough time to study a better way to install sensor on car

It's time to finalize the OpenHAB setup on the BeagleBoneBlack, which will collect and analyze data stored on the AirVantage cloud.

The steps required to complete the installation are

Install web server

A web server is required to serve the files for the web page that shows collected data. I chose lighttpd because it's lightweight and easy to configure.

To install lighttpd, simply type


sudo apt-get install lighttpd


First, let's check that your configuration is ok:

$ lighttpd -t -f lighttpd.conf


Now let's start the server for testing:

$ lighttpd -D -f lighttpd.conf


I edited the config file in /etc/lighttpd/lighttpd.conf

server.document-root = "/var/www/airmobile/pages/" 
server.port = 8082

mimetype.assign = (
  ".html" => "text/html", 
  ".js" => "application/javascript", 
  ".txt" => "text/plain",
  ".jpg" => "image/jpeg",
  ".png" => "image/png" 

index-file.names = ( "index.html" )


Then I started the webserver by typing

/etc/init.d/lighttpd start


Copy web page files

AirMobile web files (HTML and Javascript) have been copied to




Copy bindings

The binding bundles developed (namely gpio and iarvantage) needs to be copied to the openhab/addons folder. To create the bundle, right click on the project and select Export. In the Export wizard, select Deployable  plugins and fragments.



In the next step, enter the folder where you want the plugin to be generated and check the options as shown




During the deployment, I experienced a Java ClassNotFoundException. I was not able to completely understand the reason for that exception, and the only way to solve this issue was to create a bundle for each jar the AirVantage binding depends on (okhttp, Gson, scribe and org.json). I created bundle projects by selecting File -> New -> Project -> Bundle and following the wizard steps



Finally, I added the bundles to the Import-Package section of manifest file of the AirVantage binding.

Manifest-Version: 1.0
Bundle-Version: 1.6.0.qualifier
Bundle-Activator: org.openhab.binding.airvantage.internal.AirVantageActivator
Bundle-ManifestVersion: 2
Bundle-Description: This is the AirVantage binding of the open Home Automation Bus (openHAB)
Export-Package: org.openhab.binding.airvantage
Service-Component: OSGI-INF/binding.xml, OSGI-INF/genericbindingprovider.xml
Bundle-ClassPath: .,

Define the items and the sitemap

First, a set of items that show the last sensor readings are defined

Number Home_Temperature "Temperature [%.1f]" <temperature> {airvantage="system=AirMobile1,measure=temperature"}
Number Home_Humidity "Humidity [%.0f]" <humidity> {airvantage="system=AirMobile1,measure=humidity"}
Number Home_CO "CO [%.3f]" <co> {airvantage="system=AirMobile1,measure=co"}
Number Home_NO2 "NO2 [%.3f]" <no2> {airvantage="system=AirMobile1,measure=no2"}
Number Home_Dust "Dust [%.0f]" <dust> {airvantage="system=AirMobile1,measure=dust"}
Number Home_AQI "AQI [%.2f]" <gauge> 


Second, a set of items that show pollutant levels at a certain location (in this case the location of a public garden where I typically go for a run) are define


Number PB_Temperature "Temperature [%.1f]" <temperature> {airvantage="system=AirMobile1,measure=temperature"}
Number PB_Humidity "Humidity [%.0f]" <humidity> {airvantage="system=AirMobile1,measure=humidity"}
Number PB_CO "CO [%.3f]" <co> {airvantage="system=AirMobile1,measure=co"}
Number PB_NO2 "NO2 [%.3f]" <no2> {airvantage="system=AirMobile1,measure=no2"}
Number PB_Dust "Dust [%.0f]" <dust> {airvantage="system=AirMobile1,measure=dust"}
Number PB_AQI "AQI [%.2f]" <gauge>       


Finally, the item for controlling the servo for the Air Quality Index (see below) indicator is defined


Number Home_Servo "Servo [%.0f]" {gpio="pin:13 name:pwm_test_P8_13.11"}



Define the rule to compute AQI

In order to provide an easy to understand measure of the air quality, I defined a custom Air Quality Index. Unfortunately widely-used Air Quality indexes are based also on measure of the ozone concentration at ground level. Since the Air Mobile does not have a ozone sensor, I defined my own Air Quality index.

The index formula is


  homeAQI = 1 -
((((homeCO - 30.0)/(1000.0-30.0))* 0.4) +
(((homeNO2 - 200.0)/(2000.0-200.0))*0.4) +


The index is basically a weighted average of the percentage of the three pollutants detected by the AirMobile sensor

The value of the index range from 0 (worst air quality) to 1 (best air quality)

The index is calculate by an OpenHAB rule

rule "Home_AQI_Calculation"
      Item Home_CO changed or
      Item Home_NO2 changed or
      Item Home_Dust changed
  homeCO = Home_CO.state as DecimalType
  homeNO2 = Home_NO2.state as DecimalType
  homeDust = Home_Dust.state as DecimalType

  homeAQI = 1 - ((((homeCO - 30.0)/(1000.0-30.0))* 0.4) + (((homeNO2 - 200.0)/(2000.0-200.0))*0.4) + (((homeDust-0.0)/(500.0-0.0))*0.2))
      postUpdate(Home_AQI, homeAQI)
  homeServo = 1500 + (homeAQI * 1000)
  postUpdate(Home_Servo, homeServo)


This rule also updates the servo position by converting the index value (from 0 t 1) to a PWM duty cycle value (from 600 to 2400 microseconds). The PWM duty cycle is then posted to the Home_Servo item


AirMobile - Data map demo

Posted by amgalbu Top Member Feb 16, 2015

After setting up the PWM outputs on BeagleBoneBlack, I created a binding for OpenHAB. In this way, I can create items and widgets that controls servos and are fully integrated into the OpenHAB UI.

What I basically did was to make some changes in the existing GPIO binding to accomodate some new configuration keywords.

The original GPIO binding accepts the following configuration settings

gpio="pin:PIN_NUMBER [debounce:DEBOUNCE_INTERVAL] [activelow:yes|no]"


After the changes, the binding accepts the following


gpio="pin:PIN_NUMBER [debounce:DEBOUNCE_INTERVAL] [activelow:yes|no] [name:PIN_NAME] pwm:[PWM period]"


The name is the name of the pin configured for PWM as I talked about in my previous post. When either a name is supplied, the output is assumed to be a PWM output

The pwm parameter allows user to set PWM period in microseconds. By default, this parameter is set to 20000 us, that is to say 20 ms which is the typical PWM period for controlling a servo

For example, on my BBB I set


gpio="pin:13 name:pwm_test_P8_13.11"


I also made some changes to the library


I added some new function overrides to accept an integer parameter that represent the duty cycle to set. Both the PWM and duty cycle are set by writing the values to the corresponding files. For example, to set the PWM the following code is executed

Files.write(runPath, "0".getBytes());
Files.write(periodPath, Long.valueOf(this.pwmPeriod).toString().getBytes());
Files.write(runPath, "1".getBytes());


In the same way, to set duty cycle the following code is executed


Files.write(runPath, "0".getBytes());
Files.write(dutyPath, value.toString().getBytes());
Files.write(runPath, "1".getBytes());


Note that both PWM and duty cycle values are passed to the class functions expressed in microseconds and hence they are multiplied by 1000 before being written.

runPath, dutyPath and periodPath are respectively set to

/sys/devices/ocp.3/<pin name>/run
/sys/devices/ocp.3/<pin name>/duty

/sys/devices/ocp.3/<pin name>/period


I finally created a test configuration with a single item


Number Home_Servo "Servo [%.0f]" {gpio="pin:13 name:pwm_test_P8_13.11"}


and a page with two controls: a setpoint to change the PWM duty cycle and a Text to provide feedback about the current PWM duty cycle


sitemap demo label="Main Menu"
                Frame label="Home"{
    Setpoint item=Home_Servo label="PWM" minValue=1500 maxValue=2500 step=100
    Text item=Home_Servo

After a week of hardware and mechanical issues with the AirMobile sensor, my self-esteem was at an alarming low level.

So I switched to tasks that could bring me some satisfaction.

I started wondering how to demonstrate some automation capabilities as required by the challenge.

So I decided to build a "Air Quality" gauge.

The gauge will have a moving needle that will notify about the current air quality. The handle will be moved by means of servo control.

To control the servo, I need two things:

  1. a PWM output on the BeagleBoardBlack Cape connectors
  2. a piece of software that make it possible to drive the servo from OpenHAB


In this post I will focus on how to configure an output of the BeagleBoneBlack for PWM


PWM Output

The BBB was specifically designed to be a dynamic piece of hardware, enabling third-party developers to create their own custom configurations and extensions known as capes. The board is so flexible, it can change its hardware configuration at runtime using an in-kernel mechanism known as the Cape Manager in conjunction with Device Tree Overlays.

The Device Tree consists of a set of human readable text files known as DTS files that end in the “.dts” extension.  DTS files can be edited using a simple text editor to set the configuration for a particular pin. These source files then get compiled into DTB files, a binary format ending in the “.dtbo” extension.  This process creates what are known as device tree fragments or overlays.  The kernels Cape Manager can then dynamically load and unload the DTB files post-boot as well as at runtime to set the hardware configuration.  For a more in-depth look on how to use device tree overlays, The following links have been very useful to understand how overlays work:


Beaglebone and the 3.8 Kernel

Derek Molloy, Beaglebone: Introduction to GPIOs – Using Device Tree Overlays under Linux 3.8+


Luckily for our purposes, creating a new overlay for configuring PWM is not necessary. Turns out a set of overlays are already present in the “/lib/firmware” directory:








root@beaglebone:/lib/firmware# ls *pwm*



All we need to do is load them using the Cape Manager, but first, lets get acquainted with a very useful command that will help us determine if our overlays were properly loaded:


root@beaglebone:~# more /sys/devices/bone_capemgr.9/slot
0: 54:PF---
1: 55:PF---
2: 56:PF---
3: 57:PF---
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI


Out of the box, the BBB shows the above slots.  Lets add two more slots to configure pin 13 on header P8 for PWM by executing the following commands:


root@beaglebone:~# echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots
root@beaglebone:~# echo bone_pwm_P8_13 > /sys/devices/bone_capemgr.9/slots


To confirm the overlays loaded properly we run the slots command again:


root@beaglebone:~#  more /sys/devices/bone_capemgr.9/slots
0: 54:PF---
1: 55:PF---
2: 56:PF---
3: 57:PF---
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
7: ff:P-O-L Override Board Name,00A0,Override Manuf,am33xx_pwm
8: ff:P-O-L Override Board Name,00A0,Override Manuf,bone_pwm_P8_13

Our board is now configured for PWM on pin13 of the P8 header!  Before we move on, however, it’s worth noting these changes are not permanent. If you power off the board, the PWM slots we just added will disappear.  Thankfully, we don’t have to repeat the above steps each time we power up the board.  The Cape Manager supports a method to load the overlays at boot time by adding the following argument to the “uEnv.txt” file:


Make sure to append the argument in a single line like this:


root@beaglebone:~# more /media/BEAGLEBONE/uEnv.txt
optargs=quiet drm.debug=7 capemgr.enable_partno=am33xx_pwm,bone_pwm_P8_13


Once the pwm_test_P8_13 directory exists you'll want to move to it and set run to 0 to disable output while you configure the PWM. Below, I set the period to 20 ms and a starting duty of 1 ms, after enabling output again the servo will swing to left of its central position. After echoing 2 ms into the duty the servo should move to right of its center.


# cd /sys/devices/ocp.3/pwm_test_P8_13.*
# echo 0 >run
# cat period 
# cat duty 
# cat duty
# echo 0 > polarity
# echo 20000000 > period 
# echo 1000000 > duty 
# echo 1 >run

The crucial moment is coming: installing the sensor in a real car

Before of that, all the components have been mounted in a case, as shown in pictures below.






Particular care has been taken to thermally insulate the electronics components from the heat. I placed some foam on the side that faces the car radiators. This, and the air that flows from the holes in the front-facing side of the case, should prevent electronics from overheating




Care has been taken in order to make the airflow slowdown inside the case, so that measure are not affected by air speed (especially for temperature and humidity) and particles concentration increases. The idea is that air enters through the tow holes (see picture below), passes through the hole in the dust sensor and then between the two boards, where sensors are mounted. Air have to bend by 90 degrees because of the back case and this should slow it down. This is just my thought, that needs to be proven by a test on field. It could worth the while to spend some time studying how to implement a simple model in one of free CFD software, just to have an idea of air speed and pressure...

The case will be installed at a certain distance from the radiator, whereas the Peltier cell needs to be placed in contact with the radiator itself.

To increase cell efficiency, I glued a PC heatsink to the clod face of the cell itself.



The last step before installing the AirMobile board on a real car is to test the Bluetooth connection


What you see in the video is the AirMobile board mated with the TI LaunchPad board and powered by a Peltier cell. The gray box you see in the video is a PC power supply unit that cools down the cold side of the Peltier cell.

In this condition, there is enough energy to power up the Bluetooth module (you see the module's LED blinking)


On the smartphone, I installed an open-source application that I modified to meet my requirements. The application continuously tries to connect to the AirMobile board. When connection succeeds, sensors data is shown (you see 5 new rectangles appearing on the smartphone's screen). The smartphone's app is also already capable of pushing data to the AirVantage cloud infrastructure (see here for details about how AirMobile handles data)


Here is the video of the test



Hopefully I will be able to install the sensor in the car by the end of the week and see how it behaves!

After testing most of the hardware to detect short-circuits that could burn the MSP430 pins, I mated the AirMobile board to the TI LaunchPad board


Before proceeding, I had to set the TI LaunchPad's jumpers properly.

The configuration is as follow

  1. all the jumpers in the isolation jumpers block (J13) have been removed
  2. all the jumpers on J10 have been removed
  3. jumper on J11 has been removed
  4. jumper on J12 has been removed and the header pin "In use" has been connected to the AirMobile board
  5. jumper on J9 has been removed


Power supply 2.png


I finally connected the Capacitor with the header pin on the AirMobile sensor board so that the capacitor is charged through the LTC3108 circuit


The MSP430 runs a simple application that switches on the  Launchpad's red LED when the application itself  is running and blinks the Launchpad's green LED when the PGOOD output from LTC3108 is detected high. PGOOD is high when enough power is harvested to provide a stable 5V output


In the video the green LED can not be seen clearly. It starts blinking after 5 to 10 seconds since the Peltier cell is put in contact with the radiator. Please note that in the video the capacitor is not connected, so the MCU is switched off as soon as the Peltier cell is removed from the radiator




Today I tested the power supply section of the AirMobile board.

As you can read in this post, the feature of this board is that it is powered up by a Peltier cell, thus harvesting the wasted heat of a car radiator.

First of all, a note about the The step-up transformer turns ratio will determine how low the input voltage can be for the converter to start. Using a 1:100 ratio can yield start-up voltages as low as 20mV.

To make the test, I placed the hot face Peltier cell on a house radiator. I simulated the car movement by means of a fan that cools down the cool face of the cell itself.

Because the header pins is connected to the commanded 5V output, I pulled up the "5V-Enable" input pin of the LTC3108 circuit.


In video below the board being powered by the radiator heat can be seen.


During these first experiments, there are some aspects that needs further investigation:

  1. where is the high-frequency ripple on the Peltier cell's output from? It is present also when the cell has no load connected so it should not be due to an error in the board...
  2. when connected to the LTC3108 the cell's output voltage is constantly around 50 mV. Is it the LTC3108 that varies its input impedance to make the cell work with that specific output voltage? When tested with no load, the output of the Peltier cell is much higher than that..
  3. it would be very interesting to monitor the difference of temperature between the two surfaces of the Peltier cell
  4. It would be very interesting the measure the current that flows, but I don't have a multimeter that is enough precise
  5. It would be very interesting (may be later during this challenge) to compare the efficiency of different step-up transformers

Finally I (almost) completed the AirMobile sensor board

Here it is




If you think it's awful, I agree with you... I made too many mistakes, but component's  bottom views always confuse me.

Anyway, to complete the board I have to

  1. mount the MiCS2710 sensor
  2. mount the Bluetooth module


The next step is to test the power supply section...

Bluetooth protocol

Everytime I search something in the opensource community, a quote from Isaac Newton comes into my mind


"We are dwarfs on the shoulders of giants"


It's unbelievable the health of information is available for you to give form to all your ideas!!


I was looking for an Android application that I could use as a starting point. The main requirements were very simple

  • Connect via Bluetooth to the AirMobile sensor
  • Cache data local visualization
  • Push data to the AirVantage cloud through MQTT

I was very lucky because I found an application that also met my idea about the Bluetooth protocol (see my post here) The application Bluetooth protocol is a very simple one-way (from sensor to application) procotol and so I decided to adopt it for the AirMobile sensor.

Here is the protocol specifications:


<Measurement value>;<Sensor package name>;<Sensor name>;<Type of measurement>;<Short type of measurement>;<Unit name>;<Unit symbol/abbreviation>;<T1>;<T2>;<T3>;<T4>;<T5>


  • The Sensor package name is the external sensor name (in this case "AirMobile")
  • The Sensor name should be different for each sensor.
  • Type of measurements is a string that identifies what we are measuring
  • Short type of measurement is used (in my case) internally to identify the dataset to update in the AirVantage cloud
  1. T1..T5 are integer thresholds which guide how values should be displayed -
    lower than T1 - extremely low / won't be displayed
  2. between T1 and T2 - low / green
  3. between T2 and T3 - medium / yellow
  4. between T3 and T4 - high / orange
  5. between T4 and T5 - very high / red
  6. higher than T5 - extremely high / won't be displayed


Just to give an example, the AirMobile sensor will send out strings like this


  23.5;AirMobile;TMP36;Temperature;temperature;degrees Celsius;°C;-40;-10;30;40;60
  10;AirMobile;TGS2442;CO ppm;co;ppm;ppm;30;40;100;500;1000
   20;AirMobile;MiCS-2710;N02 ppb;no2;ppb;ppb;200;200;500;1000;2000