Skip navigation

There are a lot of resources available online to setup the Beagle Bone Black and connect it with AirVantage.  This post will be a quick start guide to get your BBB talk to AirVantage in under an hour (assuming all things going well).


A Bit of Intro

Beagle Bone Black is yet another powerful development Single Board Computer running on TI's AM335x processor with an ARM Cortex-A8 at its core clocked at 1GHz.  One of the main features of the BBB is its embedded MMC that is preloaded with a Debian (Linux) Image, which takes the hassle out of setting up an SD-card and flashing an operating system.  BBB has taken a plug-n-play approach.  More info can be found in their main website.    Enough with all this introduction and let's get the BBB ready. 

Ingredients (still feeling festive)

To start off, we will need

1    BeagleBoneBlack

1    Ethernet Cable

1    USB mini cable or 5V power supply

IP Scanner (i.e. Advance IP Scanner)

Telnet/SSH Client (i.e. PuTTY, SmarTTY, OSX Terminal)

Web Browser (i.e. Internet Explorer, Chrome, Firefox, Safari, etc.)





  1. Connect the BBB to your home network by plugging the ethernet cable to your router.
  2. Power the BBB by plugging the USB mini cable to a USB power supply (I'm powering mine from the USB port of my router).
  3. If you haven't installed the software tools, now is the best time to do so while BBB is booting up (takes about 10secs for the boot process to complete).
  4. Run Advance IP Scanner, to retrieve the IP address of the BBB.  Sort by Manufacturer and take note of the device from Texas Instruments.  This will be the IP Address of the BeagleBoneBlack. 


   5. Next we will update the system.  Using an SSH client, connect to the BeagleBoneBlack, username is root with an empty password.  I usually setup a password as some SSH clients do not connect with remote devices with an empty password.  To change/setup the password, type the command passwd.  To update the system, type the following commands:

                    apt-get update

                    apt-get upgrade

   6.  On a web browser, enter the IP address to retrieve the board's serial number to be used later on.


   7.  Now, we are ready to setup a connection to Sierra Wireless' AirVantage.  Login or register a trial account to AirVantage if you haven't done so.  Follow this guide to setup an AirVantage application.  Half-way through the page, there is a specific guide for the BeagleBoneBlack.  Stop at that point and proceed to the next step before following AirVantage's BBB guide.

   8.  Back to the web browser, connect to the Cloud9 IDE at port 3000, i.e.


   Cloud9 IDE is yet another great feature, you can delve into development immediately without installing a separate IDE.


   9. In the Workspace (right pane), create a new folder for development.  In the bash pane (lower section), change the directory to the newly created folder and install the MQTT library.

install mqtt.PNG

   10.  After that's installed, you can proceed with the Beagle Bone specific guide.


This is the basic setup to get you up and running the BBB with AirVantage.  As an additional reference, you can look at Node.js v0.10.35 Manual & Documentation.  If you are going to use the CC3200 with the BBB, have a look at the net module.


'Til next post, HAPPY NEW YEAR everyone!!!


AirMobile - 15 - RAM Execution

Posted by amgalbu Top Member Dec 30, 2014

RAM Execution

While building the AirMobile application, a noticed some warnings from the ULP Advisor tool. In particular, the warning was about floating point operations, which are said to be processor intensive and consume many instruction cycles, which wastes time and energy. The 16-bit MSP430 microcontroller device is best designed for simple controlling logic, as opposed to complex arithmetic computations.

Floating point operations on an MSP430 CPU requires the compiler to generate a significant number of instructions. This requires additional code instruction execution to perform the operation and consequently results in additional power and energy consumption.

The suggestion is to re-architecture your program to avoid or minimize the number of math functions. Alternatively, move the processing-intensive function to RAM as code execution from RAM consumes much less power than Flash.

I choose the second alternative: move the processing intensive function to RAM

This is not difficult to accomplish

First of all, I need to Create a load = FLASH, run = RAM memory section in the device linker command file. Reserve a memory region in FLASH to store the functions and a memory region in RAM for copy/execution.


RAM: origin = 0x2400, length = 0x2000
 INFOA: origin = 0x1980, length = 0x0080
 INFOB: origin = 0x1900, length = 0x0080
 INFOC: origin = 0x1880, length = 0x0080
 INFOD: origin = 0x1800, length = 0x0080
 FLASH: origin = 0x4400, length = 0xBB80
 FLASH2: origin = 0x10000,length = 0x14400


After reserving 0x200 bytes for RAM_EXECUTE and 0x200 bytes for FLASH_EXECUTE. Notice the new starting addresses (origins) & lengths.

RAM_EXECUTE: origin = 0x2400, length = 0x0200
 RAM: origin = 0x2600, length = 0x1C00
 INFOA: origin = 0x1980, length = 0x0080
 INFOB: origin = 0x1900, length = 0x0080
 INFOC: origin = 0x1880, length = 0x0080
 INFOD: origin = 0x1800, length = 0x0080
 FLASH_EXECUTE:origin = 0x4400, length = 0x0x200
 FLASH: origin = 0x4600, length = 0xB980
 FLASH2: origin = 0x10000,length = 0x14400

Create a section to load from FLASH_EXECUTE & run from RAM_EXECUTE:


/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY                              */

    .bss       : {} > RAM                /* GLOBAL & STATIC VARS              */
    .sysmem    : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
    .stack     : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */

    .run_from_ram: load = FLASH_EXECUTE, run = RAM_EXECUTE

    .text      : {}>> FLASH | FLASH2     /* CODE                              */
    .text:_isr : {} > FLASH              /* ISR CODE SPACE                    */

Then all the functions that uses floating point math can be decorated with the following pragma

#pragma CODE_SECTION(SENSORS_Map,".run_from_ram")


Because I use division and multiplication, these functions are pulled in from the real-time library. These processor intensive functions should also be relocated to RAM to optimize application for power.

You can find out whether your application uses many of these functions by looking at the output map file and searching for rts430*.lib. For example

rts430xl.lib : mult16_f5hw.obj (.text)
 rts430xl.lib : div16u.obj (.text)


Add the following lines to the linker command file to redirect these objects into the FLASH_EXECUTE//RAM_EXECUTE area

.text:rts430.lib_div : { rts*.lib<div16u.obj>(.text) } .run_from_ram 
 .text:rts430.lib_mult : { rts*.lib<mult16_f5hw.obj>(.text) } .run_from_ram 

Note that relocating the functions to RAM requires the use of a customized command linker file. This method is undetected by the ULP Advisor tool and the remark will still be issued. Once you can confirm the RAM execution in your code, you can suppress the remark by disabling the option for this rule in the Project's ULP Advisor setting.

Bluetooth module

The AirMobile sensor will communicate with the smartphone using a Bluetooth module. The obvious choice for an application that harvest energy from wasted heat should be to use a module that supports Bluetooth LE technology. However, because of the some difficulties in hardware design and because my smartphone is a bit old and does not support Bluetooth 4.0, I decided to use a common Roving RN42 module, which is easy to interface to an MCU thanks its UART interface


In order to optimize power consumption, I made some changes to the power management parameters

There are 5 methods to reduce power consumption:


MethodsBluetooth statesAdvantagesDisadvantages
Optimize Inquiry (discovery) and Page (connection) windowIdle (Not Connected)or ActiveConnectionThe current can be reduced from morethan 20 mA to less than 5 mA (combiningthis method with Sniff mode uses lessthan 3 mA).Causes additional latencywhen pairing or connecting.
Sniff ModeTransmitActive ConnectionThis mode can be combined with theOptimize Inquiry (Discovery) and Page(Connection) Window or Enable DeepSleep methods for lower power consumption.
Enable Deep Sleep Idle (Not Connected)With this method, current is reduced to
  1. about 300 μA.
This method can causelatency issues and may dropthe first byte if the devicewakes on RX data. It alsocauses a loss of performance/power when thedevice wakes frequently.
Disable Output DriversIdle (Not Connected)or ActiveConnectionThis method is simple to use. However, itdepends on the load: if the device is notconnected there are no power savings.This method is required for Roving Networksevaluation boards to measurepower accurately.External components drivenby GPIO pins may not work
  1. properly.
Lower TransmitPowerIdle (Not Connected)or ActiveConnectionThis method lowers power consumptionduring Txmt and active mode by reducingradio output power.The device has a shortereffective range.


Before selecting the proper approach for power saving, I had to define a bit more in details the protocol between the AirMobile sensor and the smartphone app.

I finally decided for a very simple protocol where (when connected) the AirMobile sensor sends out the value it got from the sensor. No buffering is going to be implemented if the app is not listening, because the AirMobile sensor has no way to provide neither a timestamp nor a location information. A value without such information is of no significance as it cannot be located anywhere in time and space and it will be simply be discarded

With this in mind, it's clear that

  1. the connection and pairing time is not very relevant
  2. the AirMobile sensor does not have to be actively listening for commands from AirMobile app and so it can be put to sleep when it has nothing to transmit

From this analysis, I chose to use the following methods


Optimize Inquiry (discovery) and Page (connection) window

In slave mode, there are two timers that can be used to lower radio power radio while idle. When not connected, the Bluetooth radio is active when listening for other devices. Other devices can discover (inquire) or connect (page) to the device. The amount of time the radio listens is called the window, and the interval at which the process repeats is called the interval.

For Roving Networks devices, the inquiry and page window is fixed at is 0x1000  (2.56 seconds). The default window is 0x0100 (160 ms) or a 6.25% duty cycle. By lowering the window values, you can save power at the expense of possibly missing an inquiry or page request. Because the host usually retries many times automatically, the only downside is a delay in discovery or connection time.

You adjust the inquiry scan window using the SI command. The minimum window for inquiry or page is 0x0012 (11.25 ms), which corresponds to about a 0.5% duty cycle.

You adjust the page scan window using the SJ command. The minimum window for inquiry or page is 0x0012 (11.25 ms), which corresponds to about a 0.5% duty cycle.

Thus, you can reduce the average power from more than 20 mA to less than 5 mA in standard mode and less than 3 mA in Sniff mode.

It is also possible (and desirable for security reasons) to completely disable inquiry. Once a host has found and installed a device, inquiry is not required, only page is used to make a connection. To disable inquiry while still allowing connections, set the inquiry timer to 0 with the SI,0000 command.

To obtain an extreme power saving, I decided to completely disable the inquiry. Also, I decreased the page window to the minimum allowed (11.25 ms)


Sniff mode

Sniff mode, a Bluetooth power conservation method, only pertains to an active connection. In Roving Networks devices, Sniff mode is disabled by default and the radio is active continuously when connected (about 25 to 30 mA). In Sniff mode, the radio wakes up at specific intervals and sleeps in very low power mode (around 2 mA) the rest of the time. With Sniff mode, the power savings can be quite dramatic. To enable Sniff mode, use the SW,<hex value> command. For example to set a 20 ms sniff mode timer, the command to enter is


(0x20 is 32 decimal, and 32 decimal * .625 = 20 ms)

When a connection is made, both master and slave must support Sniff mode and agree to the Sniff window, otherwise, the radio remains in full active mode.

Because AirMobile sensor never acts as a master, this setting cannot be used.


Enable deep-sleep

  1. You can use deep sleep mode to obtain extremely low power operation. In this mode, the device shuts down completely and only draws about 300 μA of current. To enable deep sleep, set the high-order bit of the Sniff word to 0x8000. This bit is NOT used to determine the sleep interval, it is only used as a flag to enable deep sleep. For example:

SW,8320 // ½ second sleep (0x0320), with deep sleep enabled

In normal low-power sleep (not deep sleep) the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops running some tasks. For example, the LEDs only update about once per second. There are 3 ways to wake the radio from sleep mode:

  • Send a character to the UART.
  • Transition the RX pin. The worst-case wake time is 5 ms. Therefore, the radio generally loses the first character sent. A better way to wake the radio is to toggle the CTS line from low to high, wait 5 ms, and then send data.
  • The radio can wake automatically every <hex value> slot times (1 slot time is 625 μs) as defined previously. The radio wakes and listens to see if the other side of the connection has anything to send. This wake time is typically about 5 ms (8 slots) even if no data is to be transferred.

Once the radio is awake, it stays active for exactly 1 second of inactivity, and then sleeps again.

Although enabling deep sleep mode could look a great way to reduce power consumption, I actually experienced a lot of issue due to packet drops and bytes losses. So I finally made up my mind not to use this feature


Disabling output drivers

Because I'm not going to use any GPIO, I used the S%,1000 command to set all GPIO pins (0 to 11) to inputs and thus disabling all output drivers


Lower transmit power

I decided not to change the transmit power because the environment where the sensor will be installed is harsh (lot of metal all around the Bluetooth module) so I think it's better to use the maximum transmitting power


Low-power connect mode

The low-power connect mode command disables the Bluetooth radio and LED timers while not connected, where <value> is a 4-digit number made up of two 1-byte intervals. The first interval is the off period and the second the on period. Both are in hex seconds (not decimal). The maximum value for either interval is 20 seconds. The default is 0000, which indicates always actively waiting for a connection. When this option is set, the module cycles between active (discoverable and connectable) and low-power deep sleep. This setting can save considerable power when the module is waiting for a long time without a connection. The trade off is additional latency when connecting or pairing.

After some tests, I found out a good trade off in keeping the radio switched off for 3 seconds and active for 1 second. This makes discovery operations enough responsive from the smartphone app's point of view


Initialization sequence

After some experiments, I found this initialization sequence works well as long as the AirMobile sensor is concerned

$$$          // enter command mode

S,0        // select SPP profile

S%1000        // set all GPIOs as input

SI,0000      // disable enquiry

SJ,0012      // set page window to 11.25 ms

S|,0301      // when not connected, stays off for 3 seconds and on for 1 second

---          // enter command mode


Power consumption

I measured the power consumption of the Bluetooth module with the default settings and with the new settings. I averaged current consumptions over a 10 seconds period. Here are the results



Original settings

Optimized settings


17 mA

2 mA


25 mA

20 mA


The most of the savings are unfortunately when the Bluetooth module is in not connected, due to the fact that it stays on only 25% of the time. I say "unfortunately" because if the AirMobile sensor is on, it means that the car is running and thus the driver's smartphone is nearby and possibly connected.

To obtain greater savings, I should enable the deep sleep mode, but this would require a more complex handling of the data flow sent to the Bluetooth module. I will get back to this if I will have some time before the challenge ends

Merry Christmas everyone!  We're all busy during this festive weeks and it could never be better as I've received my proto boards on Christmas eve.




This is all for now, and will be posting more updates as the boards get populated and tested.


Again Merry Christmas everyone, and happy holidays!


Waiting for parts and working with the Launchpad CC3200. No major progress. Merry Christmas (see Figure 1). I modified the year in the picture.


Figure 1: Closed for Christmas (Source: Holiday Closure | Fowler Museum at UCLA)

Sending sensor readings to airvantage :


For this i connected airvantage to the beaglebone black and after its connected go to

This is the cloud9 workspace.

Now in the cloud9 workspace go to terminal and in the default cloud9 location run the following :

npm install mqtt

This installs the necessary mqtt module for nodejs in cloud9 directory.

Next I created a sample file using the following code to send data to airvantage :



var mqtt = require('mqtt');
var port = 1883;
var server = "";
var serialnumber = "3713BBBK7777";                   //serialnumber of your beaglebone
var password = "1234"; //password used in credentials 
var mqtt_options = {username: serialnumber, password: password};
var client = mqtt.createClient(port, server, mqtt_options);
console.log("Client started");
//Send values
console.log("Sending value");

//Publish a message on the right topic
var room_1= {};
var timestamp = new Date().getTime();
room_1[timestamp] = { "room1.temperature": 42.2, "room1.threshold": 30, "room1.humidity": 42.2, "room1.dust": 42.2, "": 42.2, "room1.co2": 42.2,}; 
client.publish(serialnumber + '/messages/json', JSON.stringify(room_1));


Save this file and run the file in cloud9 workspace.



Thats it . Next go to your airvantage account and go inventory >  systems > your device > timeline tosee if the readings are being uploaded. On the timeline you can see all the readings that are uploaded.

Setting up Airvantage



In this post i am going to connect beaglebone  black to airvantage. For this connect beaglebone to the pc and update it. Then following the steps below i was able to connect it to airvantage and update readings and see them.



Hardware :

Step 1. Plug the BeagleBone Black to USB and install USB drivers by reading this getting started.

Step 2. Set up Internet on your device with an ethernet cable.

Step 3. Go to the Cloud9 IDE by openning the following url in a browser: Where `` is the default IP of the BeagleBone.

Step 4. Create a new file in the workspace.

step 5. Open a browser to this url: Click on the run button. Take note of the serial number and the name.

step 6. Open notepad and make a .app file to be used on airvantage with the following code:

<?xml version="1.0" encoding="ISO-8859-1"?>
<app:application xmlns:app=""
      <protocol comm-id="SERIAL" type="MQTT" />
      <encoding type="MQTT">
        <asset default-label="Room1" id="room1">
          <variable default-label="Temperature" path="temperature" type="double"/>
          <variable default-label="Humidity" path="humidity" type="double"/>
          <variable default-label="Carbon dioxide" path="co2" type="int"/>
          <variable default-label="Dust" path="dust" type="int"/>
          <variable default-label="Carbon Monoxide" path="co" type="int"/>
        <asset default-label="Room2" id="room2">
          <variable default-label="Temperature" path="temperature" type="double"/>
          <variable default-label="Humidity" path="humidity" type="double"/>
          <variable default-label="Carbon dioxide" path="co2" type="int"/>
          <variable default-label="Dust" path="dust" type="int"/>
          <variable default-label="Carbon Monoxide" path="co" type="int"/>
         <asset default-label="Kitchen" id="kitchen">
          <variable default-label="Temperature" path="temperature" type="double"/>
          <variable default-label="Humidity" path="humidity" type="double"/>
          <variable default-label="Carbon dioxide" path="co2" type="int"/>
          <variable default-label="Dust" path="dust" type="int"/>
          <variable default-label="Carbon Monoxide" path="co" type="int"/>



Next save it with .app extension like

Zip the file in an archive.

step 7. Go to Inventory > Systems.

Click on the "Create" action.

In the "Create System" dialog:

"Name" step: Specify an optional name for your system.

"Gateway" step: Click "Create gateway" and enter the identifier of the device in the "Serial Number" field.

"Subscription" step: You won't create nor use any.

"Applications" step: Click on "Release a new application" and upload the application package archive created in the previous step.

"Credentials" step: Enter the password used to authenticate the device.

Click on "Create".

In the grid, select the newly created system and click on the "Activate" action.

Thats all for setup.

The beaglebone is now ready to go.

Previous posts:

In the Air Design Challenge - Pollen & Allergen Sensing

In the Air Design Challenge - Pollen & Allergen Sensing – Post 1 (Pollen Sensor)

In the Air Design Challenge - Pollen & Allergen Sensing – Post 2

In the Air Design Challenge - Pollen & Allergen Sensing – Post 3 (AirVantage Intro)

In the Air Design Challenge - Pollen & Allergen Sensing – Post 4 (Preparing the InTheAir Power Board)


This time I will provide just a small update on the solar power PCB.

I will send it out for fabrication to WE Direkt in a couple of days. Based on the quote on Wuerth site, PCB should arrive in 9-10 days after I order them.


In the meantime, I made some design change. Since there are preset versions of TPS61200 I decided to use them for both 3.3V and 5V supply.

Please keep in mind that I'm not a professional so there may be some fundamental design faults. Comments and directions from professionals are more than welcome.

Here's my PCB design for the solar power board:

Screen Shot 2014-12-21 at 11.50.08 PM.png


Eagle files can be found in the attached .zip archive but I also created a BitBucket repository:

Please note that I didn't set resistor values for BQ25504 voltage dividers (ROV, RUV and ROK) since these values depend on battery type and desired limits.


I will soon provide the link to cross-platform InTheAir client application source code - it's still not good enough to be published.




So many sensors, so little time!

Have been studying sensor datasheets all this time to make up my mind on what sensors to use. Found it very hard come up with a meaningful, doable and useful selection. I was tempted to go for a full blown list of these popular, low-cost and popular air sensors:

You can find them on ebay for a few $ each, and it seems easy to get the readings:

However I had some concerns about the quality of their measurements. Datasheets are not very detailed, and I have no easy way of calibrating / confirming these readings.

I think one needs a second (quality) sensor as a reference and go through something like this:

Since I want to have both internal and external sensors for comparing air quality, I decided on a middle-approach. Low cost sensor outside, quality sensor inside, which is also used for calibrating/verification purposes. I’ve spent quite some time on the farnell website, and found an interesting CO2 NDIR Infrared sensor at the reasonable price of £33:


(last item, it seems its a few years old)

In terms of characteristics it looks very promising and easy to use, for newbies like myself:


Patented absorption infrared/gas sensing engine provides high accuracy in a

compact, low-cost package

• Patented ABC Logic™ self-calibration system eliminates the need for manual calibration in most applications

• Gas permeable, water-resistant diffusion filter prevents particulate and water contamination of the sensor

• Lifetime calibration guarantee

Measurement Range 0-2000 ppm factory calibrated

Duct Air Velocity 0 to 1500 ft/min (0-450 meter/min)

Temp Dependence 0.2% of full scale per ºC

*Accuracy ±40 ppm +3% of reading @ 22ºC (72ºF) when compared with a factory certified reference

Non-linearity <1% of full scale @ 22ºC (72ºF)

Power Supply Requirements 18 to 30 VAC RMS, 50/60 Hz or 18 to 42 VDC, polarity protected. Power Consumption Typical values (1.65 watts peak, 0.65 watts avg. @ 42 VDC)

Output Analog 0 to 10 VDC (100 ohm output impedance)

I know the input voltage is not ideal for TTL/CMOS stuff but I will try to "boost" things. (Any advice is more than welcome)

Btw there are newer / improved sensors from the same family but kind of expensive for my budget as I went for the SMD rework station.

My first thought with the T8031 was, "I will reverse engineer their circuit, and modify it, to power it after the voltage regulation with something closer to 5volts".

Great idea :-) if only everything was not covered in black varnish :-P

I should have guess that, by looking at the number of repetitions of the word "patent" in the datasheet :-)


Anyway, lets continue with the CO2 sensing by the book. I also found someone who has the T8031 running in parallel with MG-135 and looks ugly (probably for the MG-135),

I don't know if it’s in the same location, I will do my own tests, and in the worst case I will just keep the telaire sensor only.

I will also add Internal/external temperature and humidity but the TI SMD are soooo small. so will  start with some cheapy DHT11 & LM35 for breadboard prototyping and will go back to the SMD once I have my PCB.

Furthermore I will use the dust sensor for outdoor for outdoor measurements:

GP2Y1010AU0F - SHARP - DUST SENSOR | Farnell element14 UK

Found a nice example here: Monitoring your Air Quality

For external use, I do not like the idea of flooding the sensor when it rains, so I also got a basic rain/drop sensor (grill and LM358) in order to shut down the ventilation that will push air in the dust sensor when raining. I need to carefully think about the case. (if only I was roadtesting a 3D printer :-P )

I will also try to do a wind-meter based on a old brushless pc-fan, taking advantage the ball-bearings and the 3-wire speed sensor setup.

Hope to gain some ground during the holidays, as I did not have much free time to work on this project during the last two weeks.

Previous posts for this project:





I didn't have time to work on my project this week, but here's a small update.

Energia 14 finally came out, and with it, support for the MSP430FR5969 (with EnergyTrace) which was part of the challenge's kit. Time to test it!

Energia 14

As you might remember, I was struggling to get the MSP430FR5969 to work with Energia, and ended up resorting to Code Composer Studio.

After talking to some people of Texas Instruments at electronica, I understood the new version of Energia would support that board.

Version 14 was recently released (9th December), you can find it here.


I installed it, and gave it a try.


Trying to put a sketch directly on the MSP430FR5969 failed. A popup appeared stating the firmware needed to be upgraded first, so I did.

Screen Shot 2014-12-21 at 13.48.09.pngScreen Shot 2014-12-21 at 13.49.20.png


After the firmware upgrade, I was able to upload a sketch to the board! Finally!

Screen Shot 2014-12-21 at 13.50.07.png

With these issues out of the way, I can finally start using this Launchpad.


The coming two weeks might be quiet from my side with the upcoming holidays and all .... you know how that goes. I'll post if I manage to produce meaningful content.


Happy holidays everyone!


AirMobile - Xmas gift

Posted by amgalbu Top Member Dec 20, 2014

Finally I got the PCB from WE direct!! And it included a complimentary cake!




AirWise #6 - Ordering components

Posted by clk Dec 18, 2014

Sorry for the delay in updates. Been sick with the flu and only just on the mend. A week behind schedule here so I'll be playing catch up. Here are the parts that I will be ordering today through Newark:


Designator Newark Order CodeManufacturer P/NManufacturerDescriptionQuantity Price
197K0582GP2Y1010AU0FSharpDust Sensor314.86
286W6331TPS61200Texas InstrumentsBoost DC-DC CONVERTER32.72
335R26092058943-5TE ConnectivityCable assembly31.43
438X4646BOOSTXL-IOBKOUTTexas InstrumentsIO Break-Out Board319.98
511N9283LM7321MA/NOPBTexas InstrumentsIC, OP-AMP, 20MHZ, 18V/ us52.65
675T8009PMBT3946YPNNXPTRANSISTOR, NPN/PNP, 40V, 200MA100.266

Previous Posts:

In The Air: Epidose 1: Introduction

In The Air: Episode 2 - Preparing for Surface Mount Work

In The Air: Episode 3 - Surface Mount Beginnings

In The Air: Episode 4 - Inductors

In The Air: Episode 5 - PCB Design

In The Air: Episode 6 - Getting Ready For PCBs



Guess what came in the mail? Two things. First, my boards have arrived, and I've taken a picture to show you (Figure 1). It doesn't matter how many boards I've designed, when they arrive it's always like Christmas.



Figure 1: The Particle Counting PCB.


Secondly, the samples and the Newark order have not arrived yet. It's a pretty busy time of year, so they may not show up for a little while. I'm still working through Shabaz's (@shabaz) tutorials on the CC3200 (part1, part2). When I installed all the software and I plugged in my CC3200 Launch Pad the USB connection did not enumerate as a virtual com port, as it does in the tutorial. I think it may be due to a newer version of the software I installed. Anyway, if you experience this as well, you need to right click the CC3200LP items under the Universal Serial Bus Controllers in Device Manager and select properties. In these properties you need to set the device to use VCP. I'm at work right now, and I don't have the Launch Pad here, so I can't get a screen shot until later. This was pretty straight forward, and I found it by messing around with the settings.

(Best view 1920 x 1200)

This chapter only discuss about PCB design and PCB prototype. Sorry guys have a bad cough and fever this weeks.

Get an 4 days MC.


Look like I need to have 2 design PCB for this project for now. Fan have a big internal cutout that may disturb the routing.

This issue can easily fix if I just use one sensor for each hardware. For now still plan for two.

Attached picture show the fan and dust sensor design PCB.

Screen Shot 2014-12-15 at 1.30.43 pm.png

PCB Prototype:

For PCB prototype, I have make an example PCB to make sure the fan and dust sensor design is correct.

I maybe will just use the prototype PCB for fan and dust sensor PCB and same go to power bank PCB because there is not much design involve

Just create some video clip to share with other on how the PCB prototype making.

Attached picture show the prototype PCB preparation


Attached picture show the prototype PCB cutting process


Attached picture show the prototype PCB end process


Attached picture show the finishing prototype PCB


Power bank:

Getting some power bank for this project. The power bank is use to power up the BBB or CC3200 and other component in the device.

Today joint the Christmas sale to get the power bank


Screen shot 2014-12-16 at PM 12.05.05.png

In the Q for few minute thinking that not going to make it

Screen shot 2014-12-16 at PM 12.13.32.png

But today quite lucky, fast enough to order 2pc xiaomi power bank for this project

Screen shot 2014-12-16 at PM 02.42.37.png



Just share some informative video about Nissan leaf battery.




Dust, Temperature and Humidity Monitor Chapter 6



Coming soon

Previous posts

AirMobile - 11 - MQTT Java Client

AirMobile - 12 - AirVantage REST API


AirVantage OpenHAB binding

After creating an helper class for accessing the data stored in AirVantage, I am now ready to implement an OpenHAB binding. With such a binding, I will be able to show AirMobile data using typical OpenHAB widgets.

Configuration entries

First of all, I need to define the entries in the default.cfg file that will allow me to setup some configuration parameters for the binding itself. I currently found the following entries





The URL of the AirVantage server (either or


Refresh time (in milliseconds). This is the delay between two requests. Default value is 5 seconds


Application client Id as can be seen in AirVantage portal


Application client secret as can be seen in AirVantage portal


Airvantage username


AirVantage password


Optional access token for debug. If present, this value will be added to the requests, thus skipping the authentication process


Here is an excerpt of my default.cfg with the AirVantage binding enabled


############################### AirVantage Binding #####################################
# Interval in milliseconds to poll for data (optional, defaults to 5mins).

# access/secret keys for each user.

Binding specification

After that, I need to plan which settings needs to be included in a typical binding configuration. The following entries seems to be the most useful




The sensor reading to retrieve. Valid values are

  • temperature
  • humidity
  • co
  • no2
  • dust


The name of the system (according to AirVantage terminology) to query


Latitude of the location where the value has been read


Longitude of the location where the value has been read


lat and lon are required because data sent by the AirMobile sensor are location-dependent. It's not very useful to know the CO level 10 miles away from my house! The binding takes lat and lon and tries to find the reading taken as close as possible

Here is an example of binding configuration

Number Temperature "Temperature [%d]" <Temperature>


In a challenge I participated in the past, I set up a development environment for OpenHAB. So I used this a starting point.

To create the skeleton for the binding, I followed this tutorial.

Once the skeleton has been created, I added the methods to read data out from the AirVantage cloud

The configuration options are handled by the AirVantageBinding class, that simply stores configuration settings and provides the corresponding getters

The binding configuration options, are handled by the AirVantageBindingConfig class, that parses the configuration string

Most of the work  is performed by the execute() method in the AirVantageBinding class. This method leverages the AirVantageClient class to get authenticate into and data from AirVantage platform.

Once data has been retrieved and a location is provided in the binding configuration (see previous section), the sample taken at the closest location is sent on the OpenHAB event bus by invoking the method

If no location is provided in the binding configuration, the most recent value is returned



In the video attached to this post, the AirVantage binding in action can be seen


Over the past few days, I have been contemplating about the hardware for this particular project and ended up with a PCB design as rendered below.




Initial Thoughts


How I came into this design was a result of a thought process that attempted to answer the following questions:

1.  How many different sensor nodes are there in the system

2.  What are the similarities/differences between each node

3.  How can each node feature requirements be normalised so as to deliver a minimum viable design

4.  What could be done in the design to have a cost effective PCB run

5.  What design considerations can be put in the board design for ease of debugging and profiling

6.  Which components to be used? Considering project requirement vs design challenge recommendation as well as component availability vs component cost.


Based from the above guideline, I looked back at my proposed system and reviewed the different sensor nodes and found that there are indeed similarities and that these can be grouped together.  As an example, both the indoor and outdoor sensors are particularly identical, except for their power supply.  Aside from the outdoor sensor being powered through solar energy, it has an additional current sensor which the indoor version does not have, instead the indoor sensor has a buzzer. You can refresh yourself by revisiting this post.


The Smart Plug and Smart Switches are basically 'electronically' identical and the variation will be on the mechanical (enclosure) design.  Comparing the smart plug, smart switch, indoor sensor, and outdoor sensor, again there are similarities among them.  They all use the Texas Instruments' CC3200 module, and that is another common aspect being brought into consideration.


Among the different sensor nodes, the emission sensor is quite unique among them.  It uses the MSP430FR5969 MCU instead of the CC3200, at the same time uses Bluetooth Smart instead of WiFi.  So at this stage, I thought of designing two PCB boards.


CC3200-based Sensor Node


And so I started creating a schematic for a CC32000-based sensor node... and upon completing the schematics which was largely based on the Launchpad XL design, I then started to shop for electronic components... and... found that the price for CC3200 MCU's at element14 costs NZ$33.43 while the LaunchpadXL costs $NZ44.96.  So I started pondering on the thought that if I would continue to roll my own board, the BOM cost would be more than the price of a Launchpad PLUS the million risks in getting it right especially around the antenna section of the design.  Thus, it was logical to purchase a couple more or so Launchpads and instead take the booster pack approach.


Booster Pack Design


I kept the schematics and moved on to design a booster pack instead that would fit both (CC3200 and MSP430FR45969) Launchpads.  Everything is going quite on track until I realised that there aren't enough available IO's on the MSP430FR5969-EXP board.  Another revision of the design was inevitable, and this time, I have to incorporate an MSP430FR5969 chipset into the booster pack design.  And that's how the board came about.


Board Sections


Below are renders of the Top (image on the left) and Bottom (image on the right) assembly.  I did not bother on the missing 3D models, the render should be enough to explain the different sections and main components of the board.



The top section is where the power supply(s) are laid.  See below.


Battery is placed in the bottom assembly.


The idea here is to only populate the section relevant to the sensor node.  Thus saving a bit on PCB manufacturing costs.

U3 in the center of the lower part of the board is the MSP430FR5969, which will be populated for the emission sensor node. 

MOD1 is placeholder for the Bluetooth Smart (nRF8001) module.


This is all for this week's post.  I will provide more information about the board when they arrive.

Hello to everyone!!


So, my update last week didn't get posted due to a drastic change in our project. With the focus on clean air, water and soil sensing, I was creating sensor boards for.. well sensors. This was starting to work well until my daughter (Chrystal/Project Partner) asked how does the sensor tell if the water is ok to drink? I explained that we test for PPM, PH and other sensor tests we add. Chrystal, being a perfectionist and aspiring biologist said that my tests wouldn't give accurate enough results. She asked how I figure that it could, with so little information from a sensor? (I started to see a lecture coming). She added, if we are to make a field tester that can be used and trusted we have to do it right. So in my great wisdom I told her to tell me how to do this right. (I say my great wisdom because she was right and I let her tell me.. And I listened!! I'm very glad I did.)


Same but different:


Our change is now more biology directed. We are still using the sensors but adding in more biology for better results. This won't add too much more space to our project (Well, it will add 50% more) but the accuracy will be worth it. We are making a digital microscope and (Believe it or not) a small 4 vial centrifuge (Yes, centrifuge). As Chrystal pointed out to me, this is the most accurate way to find bacteria in the water or soil. The findings in the sample after the centrifuge can be checked against a database for safety. This redirection for accuracy is more important to our project as we require more information then what a sensor could give.


Our centrifuge is being made from a cordless rotary tool with a plastic molded vial holder attached. This is the only inexpensive and high speed way I could come up with as we require at least 18,000 rpm to reach the required G-force for separation of particles. (Pictures to come)


Our digital microscope is made from lenses and a web cam. We require 150-400x to see the small bacteria, viruses are a different story which we won't get near, as that is far beyond our knowledge. We may look into this later if time allows, I would rather leave that for more experienced virologists.


That is our update for now, Chrystal will be writing the next report later this week,


Dale and Chrystal Winhold

AirVantage REST API


In the previous post, I created a Java MQTT client to push data into the AirVantage cloud platform.

Next step is to read it out and make it available to OpenHAB. In this post I will talk about the AirVantage REST API, whereas in the next post I will provide details about my implementation of an OpenHAB  binding to get data from AirVantage



The first step in getting data is to authenticate yourself. AirVantage supports three kinds of authentication

For development, the easiest approach is to use the access token that can be read on the AirVantage portal.


AirVantage AccessToken.png


For a real-world application, probably the most user-friendly approach is to define a username and a password in a configuration file. This is the approach I will use later to create OpenHAB binding. The URL to authenticate using a username-password pair, is as follow

"https://" + server + "/api/oauth/token?grant_type=password&username=" +    username + "&password=" + password +

      "&client_id=" + clientId + "&client_secret=" + clientSecret +



server can be either or

username and password are the credentials you typically use to login into the AirVantage portal

clientId and clientSecret identify the device that is requesting data and can be generated on the AirVantage.

The response includes the access token for use with following requests


  "access_token": "fe47d528-7414-4962-a7e6-ee6b82491f7a",

  "refresh_token": "9b465388-c9e2-45d3-98d0-1a44a503ec40",

  "expires_in": 86400,



This URL returns an access token that needs to be appended to every URL. Note that access token has an expiration time. This means that care must be taken to refresh the access token periodically


Last value

To show the current (or better, the last) sensor reading in OpenHAB, the last known value has to be read, This can be accomplished by invoking the following URL

"https://" + server + "/api/V1/systems/" systemUid + /"data?access_token="

      + access_token + "&ids=" + data


systemUid is the unique identifier of the system to query. The Uid can be read on the portal


AirVantage SystemUid.png


dataIds is a comma-separated list of data to read. Keeping in mind the AirMobile application, an example of dataIds is

dataIds=airmobile_temperature.value, airmobile_temperature.latitude, airmobile_temperature.longitude

The document that is returned has the following format


   "airmobile_temperature.value": [{

"value": 30.1,

      "timestamp": 1331906459440


   " airmobile_temperature.latitude ": [{

"value": 45.913405,

"timestamp": 1331906459440


   " airmobile_temperature.longitude": [{

"value": "10.998",

"timestamp": 1331906459440




Raw values

Raw values are unfiltered values. Values are returned as sent by the field devices. Only values for the last three hours or 10000 values are available as raw data.

To get raw values, the following URL needs to be invoked

"https://" + server + "/api/V1/systems/data/raw?access_token="

      + access_token + "&targetIds=" + systemUid + "&dataIds=" + data


The response to this request has the following format




      "airmobile_temperature.value": [{

         "value": 30.1,

         "timestamp": 1331906459440


      " airmobile_temperature.latitude ": [{

         "value": 45.913405,

         "timestamp": 1331906459440


      " airmobile_temperature.longitude": [{

         "value": "10.998",

         "timestamp": 1331906459440





Aggregate values

If data over a longer time interval is required, data must be accessed using aggregate functions. Aggregate functions apply a certain function over data in a given time interval (for example one hour) and return that value instead of all the value in that time interval. Available aggregate functions include mean, sum, min, max, standard deviation, number of samples

To get aggregate values, the following URL needs to be invoked

"https://" + server + "/api/V1/systems/data/aggregated?access_token="

      + access_token + "&dataIds=" + data

      + "&targetIds=" + systemUid

      + "&from=" + (System.currentTimeMillis() - 23 * 60 * 60 * 1000)

      + "&to=" + (System.currentTimeMillis() + 1 * 60 * 60 * 1000)


There are other possible parameters that can be added to the URL, like interval. Intervals are specified by a multiplier and a unit of time, i.e. 6hour or 1day. The supported time units are:

  • hour - Hours
  • day - Days
  • month - Months
  • year - Years

The multiplier has to be lower than 50. The default interval is 1 hour

The response to this request is similar to the response shown in previous section


An helper class

All this methods have been encapsulated in a Java class (  that will be very useful in the next post, when I will talk about the OpenHAB binding implementation

This class has a few fetaures that worth to be highlighted


I used GSON library to deserialize responses. Because responses may contain fields whose name has periods in it, a custom deserializer is required. This is for example the implementation of the custom deserializer for raw data response


publicclass AirVantageRawData
   public List<Datapoint> values;
   public List<Datapoint> lats;
   public List<Datapoint> longs;

private class AirVantageRawDataDeserializer implements
  JsonDeserializer<AirVantageRawData> {

   public AirVantageRawData deserialize(JsonElement json, Type type,                          JsonDeserializationContext context) throws JsonParseException
      JsonObject jobject = (JsonObject) json;

      AirVantageRawData data = new AirVantageRawData();

      Type collectionType = new TypeToken<List<Datapoint>>() 

      JsonArray array =
      data.values = context.deserialize(array, collectionType);

      array = jobject.get("airmobile_temperature.latitude").getAsJsonArray();
      data.lats = context.deserialize(array, collectionType);

      array = jobject.get("airmobile_temperature.longitude").getAsJsonArray();
      data.longs = context.deserialize(array, collectionType);
      return data;


The usage of the deserializer is as follow


   Gson gson = new GsonBuilder()
 new AirVantageRawDataDeserializer())
   AirVantageRawData rawData = gson.fromJson(isr, collectionType);

Data fusion

Unfortunately it is not possible to read out a complete asset. Instead, it is only possible to read a specific data value in an asset.

For this reason, I created a function to merge the three array of data values (value, latitude and longitude) into a single class, because having a single class is definitely more handy. This is the code to merge data value arrays


publicclass GeoDatapoint {
      public long timestamp;
      public double latitude;
      public double longitude;
      public double value;

List<GeoDatapoint> points = new ArrayList<GeoDatapoint>();
for (int i=0; i<rawData.values.size(); i++)
   Datapoint lat = rawData.lats.get(i);
   Datapoint lon = rawData.longs.get(i);
   Datapoint val = rawData.values.get(i);

   GeoDatapoint dp = new GeoDatapoint();
   dp.latitude = lat.value;
   dp.longitude = lon.value;
   dp.value = val.value;


Apologies folks for the long gap between posts!


Things have been moving forward, although not as fast as I would like, and not ion all the areas I would like them to.


Things Achieved


  • Assembled a frame for the project - Ikea Gorm frame, fluorescent tube lighting - the lighting is GE's F40T12 Plant and Aquarium bulbs in a cheap fixture.
  • Started seedlings (require only moisture until after germination).
  • Assembled components and workbench - power supply, soldering station.


  • House renovations - I am coming to an end of my kitchen renovation project, which has unfortunately consumed almost all of my "spare" time.
  • I am still short a few components that are on back order - but this is not yet a blocker, as I have yet to utilize the things I have on hand.
  • Work schedule - I have been "under the gun" at work on an embedded project (our next generation Ground Penetrating Radar) which frankly has been taking most of my mind share lately.


Enough of the excuses already, here are some pictures.


Next Steps

  • Install OS on Beaglebone Black. Add ROS packages, configure and test.
  • Setup development environments for the CC3200 and MSP430.
  • Integrate the microcontrollers with the Beaglebone Black using ROS.
  • I have a circuit design for the pH meter (although this is not a high priority item, I happened to receive this sensor already, so I will incorporate it). Next is to build and test the circuit.
  • I have a moisture and temperature sensor (TH75 based) - connect and test.

Previous posts for this project:





For this week's post, I experimented with the Sharp GP2Y1010AU0FSharp GP2Y1010AU0F dust sensor which I plan to use in my project.

Sensor info

The Sharp GP2Y1010AU0F dust sensor uses an IR LED and detector to provide information on the dust concentration in the air.

The output of the sensor is analog and provides a voltage which can be used to correlate the dust concentration. (See paragraph "Measurements" in this post)


In the pictures above, you can see a disassembled sensor with both the LED and detector crossing paths at the ventilation hole.

The sensor is also low power, with a typical supply current of 11mA and maximum supply current of 20 mA (at 5V).



An example circuit is provided in the datasheet. It provides the function of every pin and indicates the need of an RC circuit on the LED input.

Screen Shot 2014-12-11 at 20.38.13.pngScreen Shot 2014-12-11 at 20.41.41.png

I didn't have the exact same values available, so I used the closest I could find.

To be able to test the sensor, I soldered breadboard friendly headers on the sensor cable.

sensor-pin-order.pngphoto 2.JPG

The test setup:

photo 4.JPG

The white cone contains a fan used to create an airflow to the sensor. I plan on 3D printing a more compact version so that it will fit inside the build.

In the circuit above, the fan is always on. This will not be the case in the final solution: the fan should be turned on before sampling, and turned off after it.

Through testing, I will need to find the best timing between turning the fan on and sampling, as initially, turning the fan on might give different results (dust on fan blowing through sensor).


Based on the datasheet information on sampling timing, I made a quick Arduino sketch i order to test the sensor and the circuit.

Screen Shot 2014-12-11 at 20.11.39.pngScreen Shot 2014-12-11 at 20.35.28.png

The resulting sketch is as follows:

int sensorPin = A0;
int sensorValue = 0;

int ledPin = 2;

int delaySampling = 280; // wait 280 us before sampling after turning on LED
int delayLed = 40; // wait 40 us after sampling before turning off LED
int delayCycle = 10000 - delaySampling - delayLed; // 10ms cycle

void setup() {

  pinMode(sensorPin, INPUT);
  pinMode(ledPin, OUTPUT);

  digitalWrite(ledPin, HIGH); // turn LED off

void loop() {
  digitalWrite(ledPin, LOW); // turn LED on
  delayMicroseconds(delaySampling); // wait before sampling

  sensorValue = analogRead(sensorPin); // sample
  delayMicroseconds(delayLed); // wait before turning LED off

  digitalWrite(ledPin, HIGH); // turn LED off
  delayMicroseconds(delayCycle); // wait for end of cycle

  Serial.print("Sensor Value: ");

  float voltage = sensorValue * (5.0 / 1023.0);

  Serial.print("Voltage Value: ");



I performed two measurements for initial testing.

The first test, was to use the sensor as is, measuring the dust concentration in the room.

The second, was to trigger an extreme condition using a smoking matchstick.

Screen Shot 2014-12-11 at 22.07.00.png


The change in value is clearly indicating the smoke was detected. Looking further in the datasheet, following graph is provided.

Screen Shot 2014-12-11 at 22.14.26.png

The maximum value in the graph matches the result when using the smoking matchstick, meaning a density larger than 0.6mg/m3.

As for the dust, it would seem there is an approximate concentration of 0.05mg/m3 in the room I was testing.


I'll be testing the sensor further and porting the Arduino code to the Launchpad (which should be straightforward with Energia ?!).

I'm curious to see the results when measuring in different rooms (who has the dirtiest room).

MQTT Java Client

MQTT is a light-weight protocol initially developed by IBM for transferring telemetry data. It' based on the publisher-subscriber paradigm: a device can publish data into the system and many receivers can subscribe to get data changes notifications.

Data is published under a unique path named "topic". Subscribers can subscribe to a single topic or to a certain set of topics that match the provided pattern. If the latter is the case, pattern may contain wildcards "." and "#")

Talking specifically about AirVantage, data is published under the topic "messages/json". The data being published is a JSON object whose structure is defined by the application model (see this link for more details)

AirMobile application

For the AirMobile sensor, I defined the following application. The rationale behind this is to have simple streams of sensor data that can be manipulated as a stand-alone entity or mashed-up with other streams. All the streams have a common base structure that includes the following fields

  • Latitude
  • Longitude
  • Sensor value

This should make it easier to accommodate data from other sensors. For example if AirMobile is going to be enhanced by adding a new VOC sensor, the only action required is to append a new stream to the application document. Here is the current AirMobile application

<?xml version="1.0" encoding="ISO-8859-1"?>
<app:application xmlns:app=""
      <protocol comm-id="SERIAL" type="MQTT" />

      <encoding type="MQTT">
        <asset default-label="AirMobile Sensor (T)" id="airmobile_temperature">
          <variable default-label="Latitude" path="latitude" type="double"/>
          <variable default-label="Longitude" path="longitude" type="double"/>
          <variable default-label="Value" path="value" type="double"/>
        <asset default-label="AirMobile Sensor (RH)" id="airmobile.humidity">
          <variable default-label="Latitude" path="latitude" type="double"/>
          <variable default-label="Longitude" path="longitude" type="double"/>
          <variable default-label="Value" path="value" type="double"/>
        <asset default-label="AirMobile Sensor (CO)" id="">
          <variable default-label="Latitude" path="latitude" type="double"/>
          <variable default-label="Longitude" path="longitude" type="double"/>
          <variable default-label="Value" path="value" type="double"/>
        <asset default-label="AirMobile Sensor (NO2)" id="airmobile.no2">
          <variable default-label="Latitude" path="latitude" type="double"/>
          <variable default-label="Longitude" path="longitude" type="double"/>
          <variable default-label="Value" path="value" type="double"/>
        <asset default-label="AirMobile Sensor (Dust)" id="airmobile.dust">
          <variable default-label="Latitude" path="latitude" type="double"/>
          <variable default-label="Longitude" path="longitude" type="double"/>
          <variable default-label="Value" path="value" type="double"/>

Payload creation

According to the AirMobile application, the payload is expected to be as follow

  "airmobile_temperature.latitude": 45.123,
  "airmobile_temperature.longitude": 9.111,
  " airmobile_temperature.value": 25.1


The Java code to generate this object is quite straightforward

private String convertToJson(String prefix, SensorData data) 
        long timestamp = System.currentTimeMillis();

        Map<String, List<DataValue>> values = new HashMap<String, List<DataValue>>();

        if (data.getValue() != null)
            values.put(String.format("airmobile_%s.value", prefix), Collections.singletonList(new DataValue(timestamp, data.getValue())));

        if (data.getLatitude() != null) {
 values.put(String.format("airmobile_%s.latitude", prefix), Collections.singletonList(new DataValue(timestamp, data.getLatitude())));

        if (data.getLongitude() != null) {
 values.put(String.format("airmobile_%s.longitude", prefix), Collections.singletonList(new DataValue(timestamp, data.getLongitude())));

        return gson.toJson(Collections.singletonList(values));


The parameter prefix identifies the reading being published. Possible values are

  • temperature
  • humidity
  • no
  • co2
  • dust


The Java MQTT client can be implemented by leveraging the Paho MQTT library. The steps to implement the client are

1. Create a MqttClient object

this.client = new MqttClient("tcp://" + serverHost + ":1883", MqttClient.generateClientId(), new MemoryPersistence());

  this.opt = new MqttConnectOptions();

serverHost is the AirVantage server URL ( or dependending if you want to use datacenter in North America or in Europe)

clientId and password are the credentials you provided when you created the system on the AIrVantage portal (more details in this tutorial)

2. Connect


3. Push data

  String message = this.convertToJson(data);

  MqttMessage msg = new MqttMessage(message.getBytes("UTF-8"));

  this.client.publish(opt.getUserName() + "/messages/json", msg);

Testing the MQTT client

To test the MQTT client, I created a minimal Android app. You can see the app in action in the video attached to this post

Previous Posts

I read this part a little late, but there was a document shared in the content section that said something about compulsory part. So I set out to make a custom power circuit for this project. The concept is simple. I needed a power system that could work without 'user interference'. This means I need rechargeable batteries and a way to manage them. The TI Fuel Booster Pack is one way of doing this but the parts provided do not include them and what would be the fun of a copy paste. So I set out to create a new PCB...


This post is sort of a standalone segment on designing a power sub system.


The basic design

The TI Fuel booster pack can be used as a reference and the block diagram is given below.




Now we do not want a USB in but a solar panel instead. Also I really have no need to gauge the battery either so thats out too. Instead I will use the BQ25504 to charge the Li-ion battery. In this case, we can also use a super cap like 1farad or so because the Wolverine LP really can work on that. Unfortunately, the sensors use up a lot more power so I left that part for an expansion for later. Next the buck and boost converter and for that we are using the TPS51200 and TPS62740. These generate the 5V and 3V for various parts. Each of these has an enable pin so I can shut them down too. This is our basic requirement and its quite simple. So lets start making the ckt. Eagle!!!!!


The Schematic

There are a couple of ways you can get a reference design but the application circuits in the datasheet are usually good enough. These are shown below.


Thats the BQ25504. Pretty simple...


and the TPS61200


and the TPS62740


I can use these as is but I chose to dig a little deeper. I went on to find application notes for these and the circuits were more or less the same. So I can start making the circuit in eagle? Not so fast... Eagle has a lot of parts but you will need to make these yourself. I did and there are good tutorials on how to make parts in eagle from adafruit and sparkfun. The process is a little tedious but very satisfying.


The schematic I made looks like this...


The schematic is self explanatory except for a few things. I added a connector for a sensor module which operates at 5V. Another module is used to interface a different sensor module. I probably should have added a voltage divider to the ADC but I simply missed that actually. That can be rectified but cutting the track and adding it between the connector. There is also a connector to connect it to the LaunchPad but its not a booster pack and I will explain why later.


The best laid layout

The next part is to layout the board. Everyone has a system for doing this and I have mine. When I start making the schematic, I finish a part such as the BQ25504 and its parts and jump into the layout. I don't completely layout the board but just arrange the parts together as an estimate and then place it somewhere else. The reason is that it simplifies layouts later and I used to work with Cadence OrCAD which had the facility to group components together. On the layout, keep pressing N to get the next part in the selected group for placement and thats something very nice. In eagle I just club things together since the number of parts on the PCB are usually smaller.


Before your start layout, see the datasheet for layout considerations like...


All said and done, you can even find sample layouts like the one for the HDC1000


Neat! So my final layout looks like...


Each module was laid out separately and put into place. The thoughprocess is to use the least space but make the layout work. I used the seeed studios fabhouse so they ask for PCB sizes as a multiple of 5cm so I chose the least i.e. 5cm x 5cm. I make the outline 49mm x 49mm and then placed everything in it. The standard booster pack is much larger hence that was out of the question. Another aspect is that I know I will need to make changes later so I want to reduce the cost of prototype as much as possible. And lastly I want this thing to be reusable hence the enable pins, inputs and outputs all have a connector. So I can choose to use each part alone if I want. I ordered 10 of these so they should be useful for later projects as well.


I did NOT tent vias where vias are covered by the solder mask because I usually use these as test points to save unnecessary vias. The rev number is compulsory and I prefer rounded edges. Mounting holes I again avoid for small boards and instead I add single pin connectors(1 pin burg strips) at the corners or use a hot glue gun to make standoffs.


One more trick is to upload these to to see the result. I cannot use OSHPark because the shipping plus making is too much.


Thats about it. Once I get these manufactured, I will do a separate post for the pcb and parts.


Hope this helps.




Previous Posts

It looks as if I have been maintaining blog silence for this challenge but actually I have been plagued by personal issues. In addition to that, despite the simple appearance of this project, the research that has gone into making this project is really huge. As  consequence I have a dozen half finished blog posts that are going to come in as work on each module finishes.

This post is a dedicated progress report for work done.


The design simplified

The objective is to measure air quality indoor and outdoor. This means two modules and each module to work on battery.

Each of the two modules will have TI and Wurth parts. The table below shows the activities and their progress.


Outdoor Module


Indoor Module




There is a lot to be done but the PCB part is done and I am finishing up the parts for purchases before the holidays.

More on this later...

Previous Posts:

In The Air: Epidose 1: Introduction

In The Air: Episode 2 - Preparing for Surface Mount Work

In The Air: Episode 3 - Surface Mount Beginnings

In The Air: Episode 4 - Inductors

In The Air: Episode 5 - PCB Design



This week involved procuring parts. I contacted Wurth for the following parts:



The first two kits are for the 0805 and 1206 capacitors I used on my board. The third item is a 2 position terminal block for a power supply input. Items 4 and 5 are male and female headers for the TI Booster Pack Interface. I used all Texas Instruments ICs on my board, so I contacted Christian (@doctorcdf) and he was able to procure samples from TI for me. For everything else, I used my budget from Newark. So, while I wait for everything to be delivered I began working with the CC3200 Launch Pad. I'm following the tutorials (first, second) created by @shabaz for the CC3200.


This leaves me with not much to talk about for this week's blog post. How about some more about PCB design, and then a little about reading? Figure 1 shows a zoomed portion of my Booster Pack design. U8, down at the bottom left, is a TINY humidity and temperature sensor. I was surprised that no one who read my last post challenged me on the layout decision for that chip.



Figure 1: Zoomed picture of my Booster Pack design.


When placing the sensor directly on my main PCB like this, it should be thermally isolated from the rest of the board. Figure 2 shows how TI suggests doing this in the HDC1000 datasheet. The white portions are slots drilled in the PCB, and this reduces the thermal mass. What's that all about? Well, for our purposes, a low thermal mass allows the sensor to respond quickly to temperature fluctuations. What I'm really getting at here, is that I didn't include any slots in my PCB design.



Figure 2: Isolating the HDC1000 and reducing its thermal mass.


Why, oh why would I have done this? I've got three reasons:

  1. I don't want to measure the ambient air temperature. I want to know the board temperature. The microcontroller might have a temperature sensor built-in, but that's on the launchpad not the Booster Pack.
  2. Slotted holes are always a pain when getting your PCB fabricated. I'm not sure why this is an issue, but every time I've gotten quotes for PCBs the manufacturers were more concerned with how many slotted holes the board contained and not the overall hole count.
  3. I don't even have a good reason to have this chip included, I just thought it would be fun to put it on the board.


I suppose this brings me to the section where I talk about reading. The more I mentor students, the more I reflect on my own education and experience. Inevitably, when I first started with a student we would have a conversation something like this:


     Student: Hey Mike, I can't seem to get XYZ working.

     Mike: What does the datasheet say about it?

     Student: Ahhh, I dunno.


I think this is a symptom of a larger problem: students can "read" without understanding. I'm guilty of it myself. I can easily recall reading technical documents and stopping only to think, "I haven't understood anything I've read for the last page and a half". Not only did I not understand it, I don't even remember what I read! It's like my "reading" was on autopilot. When I was a teenager, my father always told me RTFQ², which stood for Read the (expletive deleted) question squared, or in this case twice. Although I prefer a cleaner version, I think the principle remains true; reading and understanding is important. I have two techniques I use to help me understand what I am reading. The first is to periodically stop and ponder what I have read. It's amazing how effective this technique can be. The second is to read with a pen and paper handy to make notes about what I've read. I only discovered how helpful this was when I started preparing lectures as a graduate student.


Hope your projects are going well! Til next time.

The image below shows my sensor node enclosure. The enclosure is an air-tight box where all electronics ( MSP430FR5969, batteries, C110L tranceiver) will be fixed inside. A total of four PVC elbows with 12 inches pipes are mounted on two longer sides of the air-tight box for sensor probes that will be submerged in the water. Additionally, upward pipe on one of the shorter side is also mounted for the Air temperature and Carbon dioxide sensors. A 5W soloar panel is placed in an inclined position on top of the box. I am still working on the removable holder for the solar panel that can adjusted 45 degrees on the pivot point. This enclosure will be embedded on a bamboo tray before deploying in sea water.




Additional photos of the sensor node enclosure.

20141210_062042.jpg  20141210_061915.jpg  20141210_061958.jpg

Click this link Ryan Labutap to view my previous post on this project.

Previous posts:

In the Air Design Challenge - Pollen & Allergen Sensing

In the Air Design Challenge - Pollen & Allergen Sensing – Post 1 (Pollen Sensor)

In the Air Design Challenge - Pollen & Allergen Sensing – Post 2

In the Air Design Challenge - Pollen & Allergen Sensing – Post 3 (AirVantage Intro)


Preparing the InTheAir Power Board


I’m having trouble with TI LaunchPads delivery but I have to make some advance here even without having them with me in order to complete the project on time.

First, I would like to say thanks to Christian Defeo for being very helpful and patient when it comes to shipping the material and resolving customs issues. Also, I would like to say thanks to .lukasz. who was kind enough to share his work on the solar Li-Ion battery charger based on TI’s BQ25504.


I chose to make a power supply board in form of a LP BoosterPack.

TI’s BoosterPack template was used to develop my own board that fits to Launchpads. This template can be obtained from the following page: Build Your Own BoosterPack for TI LaunchPad

For the actual PCB design I use Eagle PCB Design software provided by CadSoft - CadSoft EAGLE PCB Design Software - Circuit Board Design Software.


This PCB design will be my second real attempt in making a circuit design so I will have to be very careful. In my first attempt, I created a VFD clock based on MSP430G2553 and after my boards arrived back from manufacturer I realized that I made a couple of design errors. Luckily, those were small errors that I managed to resolve using a sharp knife and a small peace of wire


InTheAir Power Board will host:

  • Battery charger powered by a solar cell
  • 3.3V power supply
  • 5V power supply


Lukasz’s battery charger circuit is used as the basis for my booster pack. I removed the connectors used for resistor connections.

At the moment, my board hosts the charger based on BQ25504 from Texas Instruments. After I made the following picture I realised that Lukasz's connectors are not 2.54mm pitch so I will change them for 2.54 pitched ones (kindly provided by Würth Electronics: Serie 2109 - 2.54mm Horiz. Entry WR-TBL - Product Catalog Electromechanical Components).


Here’s the current state of my Booster Pack:



EDIT: After I changed the connectors there's much more space left for other components:

Screen Shot 2014-12-07 at 10.46.12 PM.png

I followed some michaelwylie's advices on using vias to avoid making unwanted antennas.


For 3.3V supply, I will use TPS61291 Boost Converter.

For 5V supply, TPS61200 Boost Converter will be used.

Both components have very detailed data-sheets with example usage circuits. It will be fun to fit them on my board.


Eagle files will be uploaded as soon as I complete the design.

I’m sure more experienced guys will have some comments when I complete. I will wait a couple of days before I send it out for manufacture.


As for the soldering, I have a lot of experience there so I expect that will not be too much of a problem.



Previous post: In-the-Air-Challenge: Air Quality Sensor Box

Next post: In-the-Air-Challenge: A sheet of laser light for 2D visualization of dust flow


Roadtesters for In-the-Air-Challenge received fom Element14 a free Beaglebone Black (BBB) microcomputer with Angstrom Linux on internal 4 GB flash. It has one USB port, where one could connect a HDD and make low power consumtion server for IoT data storing.


Dust particles in air scatter light when illuminated by a powerful LED or laser, floodlights or flashlight.  I have done dust counting in webcam images on a Windows PC using LabVIEW. I wanted to give a try and use  BBB for that purpose.  Particle identification and counting on BBB I planned to do using OpenCV. While OpenCV is ready to use in Processing on a Windows PC, it appeared that one needs to compile OpenCV for BBB and it could take hours and result with some error code meaning that your day has been wasted. Another approach could be used to send pictures from a BBB to a Windows server that is doing image processing and particle counting.


Home-built airborne particle counter using image processing


From your childhood probably you remember seeing dust flying around in a room in sunny days. Nowadays one can see dust flying in a dark room using a mobile phone LED. Physicists distinquish several types of scattering. Sky is blue because of Rayleigh scattering from air molecules that are smaller than the wavelength of light. Blue light is scattered more than red. Mie scattering is from particles comparable to the wavelenght of light. Unlike Rayleigh scattering Mie scattering is not strongly wavelength dependent. Geometrical scattering occures from larger particles.


About a year ago we vave installed a HEPA cleanroom box in a university optics lab and wanted to know if it really helps to filter air. Commercial cleanroom airborne particle detectors use a laser, cost thousands and can get polluted if used in dusty rooms.


I had a 1W output 445 nm blue laser diode lying around and togather with my student gave a try. LED would be better to use thinking about eye safety. Light output from a 10W LED measured with a laser power meter was 0.25W. So 10W is the electrical power, not the optical. In the case of laser diodes 1W is optical power and consumed power is just 2W. Laser diodes are more efficient than LEDs and can be focussed much tighter visualizing smaller dust.



We directed laser light into a darkened chamber and recorded scattered light from dust with a webcam. Using image processing tools allows to count the number of particles in air and determine their size from the scattering intensity. The light beam has to be terminated on a bent dark surface without causing too much scattering from surface. We used LabView 2012 for image processing. LabView .vi file is attached to this post. Camera lens was defocussed, to make circle detection easier.



We can clearly see increase of particle count after dry sweeping the room. 50 particles/cm3 is actually 50 million/m3. Quite a lot!

Inside a cleanroom flowbox after a HEPA filter air is clean. Recently Electrolux has started to use HEPA13 class filters stopping 99.95% of particles in vacuum cleaners keeping air fresh after cleaning.

There are also mechanical wirpool filters, electrostatic filters and active coal filters. Latest can remove cigarette smoke odor. Odor molecules are smaller than dust but larger than air molecules.


dust signals.png




We got some limitations. Camera frame rate of 15 fps was not enough and when some air flow was present particles smeared out from circles into lines. Smearing into lines was more pronounced when using a macro lens because  particles quicker crossed the small field of view. But macro lens was esential to be able to see small size particles. I would say that human eye is still superiour to a webcam.



First steps with BeagleBone Black


The BeagleBone Black is relatively well described in Internet, so I only will write down some short notes:

Plugged into a USB appears as a SD disk. Installed drivers from the SD disk.

In Windows7 Device manager "cdc serial unknown" device still appears but it seems not to be  a problem.


Surprise: Could open in a webbrowser site  Cool! BBB acts like a USB network card.


Next will continue with terminal connection from Putty ssh  Default login: root  pass: <none>

Most things are like on regular Linux PCs.

Header 1Header 2

df -h

Size  Used Avail Use% Mounted on

rootfs  3.4G  1.5G  1.8G  45% /


shows ram usage

ps -ef

shows processes, among other also apache2 webserver running

ls /dev

shows watchdog present


shows processes running

uname -a

Linux beaglebone 3.8.13-bone47 #1 SMP Fri Apr 11 01:36:09 UTC 2014 armv7l GNU/Linux
dmesgshows boot log
passwdsets password
ifconfigshows that there is an active network connection over usb
nano /etc/network/interfaces
ping google.comedit network settings
ntpdate -b -s -u pool.ntp.orgtime server



USB Wi-Fi donge to BBB Angstrom (no success)


Cable ethernet started to work after uncommenting lines in /etc/network/interfaces.


Wi-Fi setup described here:

Connected external 5V power. Plugged in a USB Wi-Fi donge.



Bus 001 Device 005 ID 7392:7811 Edimax Technology Co Ltd EW-7811Un 802.11n Wireless Adapter[Realtek RTL8188CUS



[ 1065.852675] rtl8192cu 1-1:1.0: usb_probe_interface

[ 1065.978194] rtlwifi: wireless switch is on


iwlist scanning

shows Wi-Fi networks around


nano /etc/network/interfaces


auto wlan0

  iface wlan0 inet dhcp

  wpa-ssid "essid"

  wpa-psk  "password"


/etc/init.d/networking restart





ifconfig wlan0 up

iwlist wlan0 scan

iwconfig wlan0 essid Wifi2Home key s:ABCDE12345

dhclient wlan0



PING ( 56(84) bytes of data.

64 bytes from ( icmp_req=1 ttl=44 time=75.5 ms


I managed to connect only to password protected networks. Not to the open networks.



OpenCV image processing with BBB Angstrom (no success)


apt-get update

apt-get install OpenCV

E: Unable to locate package OpenCV


It appears that thing is not so easy.

One needs to download OpenCV source code and to compile it takes 10 hours. It is a crazy long time. After waiting some hours got got make: *** [all] Error 2

Was no more space left on 4 GB. It is much easier in Processing on a PC. So I probably will not use OpenCV and make my own C or Python code to find dust spots in a picture.




Tried Debian. Flashed Debian transfer image from a 2GB card to emmc.

During transfer external 5V power is needed.

Same Wi-Fi problems. Could not get it working. Probably I have an unsupported adapter.



Webcam and Ramdisk


Plugged in a USB webcam Logitech C270.

It appeared in ls/dev as video0


Next installed fswebcam programm to take photos

apt-get install fswebcam 

cd /tmp  # this is RAM 

fswebcam --device /dev/video0 `date +%y%m%d-%H%M%S`.jpg 

A .jpg file should should appear.



Next would like to store photos in a www directory to be able to see them over webbrowser. Usually Linux PCs store webpages here:

cd /var/www

But it is empty directory. Let's make a test html file.


nano index.html


chmod 777 index.html


Apache2 at port 80 is displaying Beaglebone page. So we need to look in settings how to display our page..

Apache2 settings are here.

cd /etc/apache2

I did not change them as read there that port 8080 is an alternative page.


Our test webpage should be displayed at


Lets make a Ramdisk under /var/www for storing webcam picture so that flash does not get weared out.

And add a line in fstab that Ramdisk gets mounted on the boot.


mkdir /var/www/tmp 

nano /etc/fstab 

tmpfs /var/www/tmp tmpfs size=10M,mode=0755 0 0



df -h    # shows that we have now a 10 MB ramdisk at /var/www/tmp


Filesystem  Size  Used Avail Use% Mounted on

rootfs      3.4G  1.7G  1.6G  51% /

tmpfs        10M    0  10M  0% /var/www/tmp


Now let's take a test photo.

cd /var/www/tmp/

fswebcam --device /dev/video0 -r 800x600 current.jpg

A picture appeared in


dust beagle.png

The problem is that fswebcam programm compresses image to jpg. And quality goes down. Dust is much less visible than in uncompressed image.

It is possible to upload the photo file to a server where a mobilewebcam.php script  saves it:

     curl -F userfile=@/tmp/current.jpg




Tried to use another webcam programm.


apt-get install uvccapture

uvccapture -v -t1 -B148 -S128 -C32 -G4  -q90 -o/var/www/tmp/test.jpg

uvccapture -v -m -t1 -B96 -S32 -C32 -G16  -x640 -y480 -o/var/www/tmp/test.jpg


Using videodevice: /dev/video0  
Saving images to: /var/www/tmp/test.jpg

Image size: 320x240

Taking snapshot every 1 seconds

Taking images using mmap  

Setting camera brightness to 148

Setting camera contrast to 32

Setting camera saturation to 128

Setting camera gain to 4

Saving image to: /var/www/tmp/test.jpg


width=640 height=480 interval=4 output=/home/httpd/webcam.jpg capture=/usr/local/bin/

uvccapture -v -m -t1 -B96 -S32 -C32 -G16  -x640 -y480 -o/var/www/tmp/test.jpg


Picture was saved OK, but despite trying I could not get  highter jpg resolution than 320x240. Seems that there is a bug and uvccapture on BBB is presently pretty unusable.






  • Nowadays it is possible to make a low-cost dust detector using a Beagle Bone Black board and a webcam togather with a diode laser.
  • Camera is similar to a human eye. With an eye clearly see dust flashes. Image processing allows to count dust particles in a photo.
  • Image recognition allows to see large changes in air pollution when  when a room is dry-swept.
  • Bringing eye close to beam reveals much more small dust. Camera needs magnification or macro lens to see small dust.
  • There is a huge number of small particles in air. They are not molecules. Something bigger. For example pollen, aerosols, viruses.
  • Camera needs to look at a small-sized light beam. In a broad beam there are so many particles in a field of view that they overlap and are impossible to count. Some particles 20 per frame ar OK.
  • In a focussed beam light scattering intensity is higher and disturbing background is less.
  • Camera at 15 or 30 fps is quite slow and air velocity should be low. If air flow is fast then the dust tracks smear out and appear as lines. Then image recognition of circles does not work anymore.
  • Solution would be a strobe flashlight or pulsed laser or LED. I tried once and ended up with a burned out laser diode.



After spending a couple of weeks on BBB and  image processing I decided to try out a classical dust counter approach with a laser and a photodiode. Please see the upcoming blogposts.


I got one of these (The LCD!The LCD!) LCDs from the budget and the motive is to use them to display air quality. Low and behold I got them and these things are tiny... I mean more than I thought. BUT they should get the job done. This post is a little one where I try and get it to work and experiment with I2C. Lets go!



The LCD itself

To be honest the features of this LCD are great but the cost is a little higher than I would like. The special thing about these is that they work at 3.3V which means they can be directly connected to my Launchpads. Great! Now how do I get em to work. The datasheet is available as with all element14 parts and you can download it for use. I will take out the parts that we need and discuss.


Shabaz sir used it in his posts about the CC3200 and he did it effortlessly. I had to mess with somethings hence I am posting a bit of my experience.


First things first...

The pin configuration. Before we start with the software lets ready the hardware and for that we need to know about the pin config. Its in the datasheet and the useful parts are:







Brilliant now this means that  I can work with only 4 Pins. I need the VDD, VSS(GND), SDA and SCL. I can tie the reset and everything around. I am not going to make footprints or PCBs for this thing so I will directly solder everything in place. The pins are connected as:

1 - VOUT , 4 - VDD and 8 - RST to the 5V output from the CC3200 Launchpad. Why 5V? Because if you want to run it off the 3.3V then you need to add two caps. I will save those caps and use the 5V available on the LP.

5- VSS to Ground

6 - SDA to the I2C SDA Pin

7- SCL to the I2C SCL Pin



4 pins is all I need. If I need to reset it I can do it in software OR power the thing OFF and ON. Great!

The results of my soldering is shown below. In my deficen I would like to say that I do not have the finer tips for the soldering station so this will have to do.





The bus pirate.

I would like to run the LP directly with the LCD but there is a problem. I don't want to mess with code then find out that my soldering was dry. So I chose to use the Bus Pirate.

For thos who dont know, the bus pirate is a small tool that can be used with most serial bus protocols to debug and analyse them. Here I will be using it for I2C. Hooking it up is easy. The above four pins to the pins on the pirate and done! Well one more thing. The I2C bus needs pull-ups and the voltage of these pull ups matters for the controllers being used. I want the bus to go 3V3 so I can solder some external pullups. The simpler solution is that there is a Pull up connection on the BP which can be enabled or disabled in Software. Any voltage 3V3 or 5V can be selected externally using the provided pin and so I connected the Pullup wire to the 3V3 generated by the BP itself. Neat!






On to the bus!

There are a gazillion tutorials for the I2C bus on the net so I wont bother. The signaling is not important here but what is important is the protocol itself.

In order to talk to a device, the bus is pinged with a start signal.(For signalling details, google it! or PM me.) Next the address of the device to be hailed is sent. The addersses are 7 bit with the last bit signifiying read or write operation. Next data or commands are sent post which the device sends an ACK or acknowledge for each byte successfully received. This makes sure you are talking to something. Lets go by example here.


The first thing here is the address. The buspirate is used via a serial terminal program. After bringing it into I2C mode and enabeling the power and pullups, we try to talk to the LCD. Its address is 0b01111100 where the last bit is 0 for write operations. Hence for a read operation, we would use 0x7d. That simple. A quick look at the datasheet...




Easy right.. OK moving on.


We need to send it something that tells it that I want to send commands to initialize it. These commands also include resetting the LCD and moving the cursor around. So how do we do that?

The next byte we send will be 0x00 if we want to send a single command.

I made the string in notepad and pasted it into the realterm console as:



press enter and...



The ACKs means the LCD is present and responding. Good. Now to print something. Now the Datasheet has a table that you can decode but I have a trick. All the characters are assigned their ascii code and you can go to and get the hex values directly.


Copy and paste the string into the console and...



The Hello pops up on the LCD.




A lot of work just to get a hello but it is worth it in the long run. I hope this helps people thinking about adding an LCD to their project. Graphical LCDs are also possible but this is just smaller and quicker.



This week's update is going to be short but sweet, as I have been working most on the firmware architecture and device driver development.  So far, the code flow as below.





The intention is that the emission sensor board will be powered by the car's battery via 12V plug, ideally this will be wired through the ignition switch, so we can detect that the ignition is turned on or off.  However, for a minimal design, we can determine the engine state through a vibration profile.


After the hardware has been initialised, the main loop for the firmware will sample the accelerometer at TBD rate.  More research needs to be done on identifying the ideal sampling frequency, and vibration profile at different engine states.  The sampled value is then stored to a buffer and filter out the noise.  Again, as with the sampling frequency, the filter type and coefficients are yet to be determined, more of info will be provided in the coming posts about signal processing.  At this stage, data acquisition is the more important part.


From the filtered data we will be able to deduce the engine state, i.e. off, idling, or running and send the updated state to a connected smartphone via Bluetooth LE.  If the engine is running, CO2 emission is sampled and sent to a smartphone for further processing.   CO2 emission, engine state and GPS data (as read from smartphone) will all be used to generate tangible information before being sent to AirVantage.

Translating the flowchart into code, we have the following (excerpt from main.c):

int main(void)
   Acceleration_T raw_accel;
   Acceleration_T filtered_accel;
   EngineState_t engineState = Engine_Off;


   while (1)
      if (Accelerometer_IsSamplingCompleted() == false)

      FilterNoise(raw_accel, &filtered_accel);

      if (EngineStateChanged(filtered_accel, &engineState))

      if (engineState != Engine_Off)
         /* Sample CO2 emission */
         int32_t temperature = 0;
         int32_t humidity = 0;
         HDC1000_Measure(&HDC1000_Instance, &temperature, &humidity);
         MQ135_Read(&MQ135_Instance, temperature, humidity);


Since time is ticking so fast, and I have a good working firmware framework in place, so I think its about time for me to switch my tasks and focus on hardware development.

(Best view 1920 x 1200)


This chapter I will share about PCB design.This PCB design in under progress. I will talk about the design, problem, solution and related issue.

It simply straight forward since we have dedicated hardware and all the related component with no major changing.




I still follow the previous idea to build device in box and PCB in multistage. In PCB design I will start from ground up. But I will not explain in detail about the workflow. Sorry all, just don't have enough time to make a detail report.

Since I not getting the Eagle V7 pro software, I will using existing software for this PCB design.

The plan is to design one PCB for all. This mean one PCB design support for BBB, CC3200 or MSP430FR5969 and other component.


EAGLE CADsoft V7.1

The Eagle V7 is using for the BBB because you can just download the lib from Element 14. For my case I feel that it wasting my time because they have limited space for eagle 7.1 freeware. I cannot place the BBB and other component at the location needed. I don't know what is the size limit for this Eagle V7 freeware but it not support up to 120mm x 120mm PCB.

I also using Würth Elektronik library that also only support Eagle CAD version 7. In the picture show the example the BBB and connector from Würth Elektronik. For those who have interest at Würth Elektronik lib in Eagle V7, can download it at the given link.




Eagle CADsoft V5.7 (look like very outdated he..he..)

This version not support the lib given by element 14 and Würth Elektronik . That why I'm using the eagle latest freeware.

Should just draw them in lib. This way will be faster from solving the issue. For Würth Elektronik, I saw they also provide lib in Eagle V4.

You can try this for the older version Eagle.

Picture show other component part in the PCB layout.



CAM editor

Using to merge multiple PCB design form different Eagle version.

The picture just show the example merge product. This will not be the final or finish product.

I still need to do some measurement and edit some of the file.

For example the TI 430boostsharp96 have a lot small drill hole. Those hole need to be remove.

The given picture just show the example and explain the method use to solve the problem.



More example with color at higher resolution in PDF file. Please refer to the attached file for more detail. If you want to see them .



Mechanical Drawing

Mechanical part will be box that cover and hold up everything. It also will be the first expression to user about product or device. So normally it need to look nice .

It sound easy but when you want to do it nicely and perfectly then it will be different story.


So to make the design then you need to have the part. If you can download the part online then it will make your life easy.

For this case I need to draw them out using the given dimension and measurement dimension. Don't found any information about the 3d drawing for those component.

Tips: If possible please use the latest software to design that can support 3D then you don't need to draw on both PCB and mechanical.




Box design still in progress, I need to finish part drawing then can do assembly process to make sure the box design is correct. This also will help in part assembly, part can be organize nicely and correctly before the box making.

I may try the ECAD for BBB in future. If it work then I have a detail 3D for BBB he..he..

Picture show a box with 120mm x 120mm x 120mm and 10mm thickness.





Part and Component


Picture show example of the part that going to use for this project. Will share the information in future.


Photo 6-12-14 12 49 22 pm.jpg


MSP430 come with 3 different programing platform and this BBB come with 3 different OS platform.


This is the updated link I found. Try to make a step by step OS installation for BBB that support BB view43.


element14: BB View LCD Cape Software Download Centre[1]


element14: Quick Start Guide for BB VIEW


element14: User Manual for BB View - An LCD Expansion Cape for BeagleBone Boards






This is video clip for BMW i3 production. It quite interesting see their setup and process. See how the robot work... nice...


Dust, Temperature and Humidity Monitor Chapter 5


Coming soon

Previous posts for this project:





Last week, I set up openHAB to visualise data on my FuelTank's battery state. But how did I access this data from the CC3200? Let's find out ...


Energia & CC3200 on Mac


But first ... another problem was solved!


At long last, the CC3200 is working with Energia on my Mac, thanks to pmohan for pointing me to the solution. The issue was caused by the latest version of OSX (Yosemite) not allowing to run unsigned drivers ("kext").

Screen Shot 2014-11-19 at 20.50.30.png

Using a manual fix which disables the signature checking in OSX, the driver can be loaded and the CC3200 detected in Energia! Woop!


Trial & error


During my research, I came across some posts and reviews by peteroakes in which he created an Energia sketch to retrieve some statistics from the Fuel Tank BoosterPack via I2C.


I hooked up the Fuel Tank Boosterpack to the CC3200, loaded the sketch in Energia and monitored the serial output. Nothing spectacular happened.

Screen Shot 2014-11-23 at 18.34.01.png


All values were "0". This meant that either the sketch would somehow not be compatible with the CC3200 or that the I2C slave was unreachable.

Searching a bit more, I came across a library (it's at the bottom of that page - or here) doing the same thing, and the result was unfortunately the same. (What was I expecting ??)


Recovering the battery


At some point, I connected the Fuel Tank to the CC3200 and had it run on the battery without charger.

Unfortunately, the battery discharged a bit faster than expected, while I was away at work.


The result ? By the time I got home, the battery would no longer charge via the Fuel Tank when connected to a power source.


Looking through the Fuel Tank's documentation, there is a trick to "kickstart" the charging of the battery in case it was discharged too much.

The procedure is described in paragraph 6 of the user guide and helped me recover the battery, after which it was charging with the Fuel Tank again.


Pinout diagrams


In order to troubleshoot the problem, I searched pinouts of both the CC3200 and the Fuel Tank BoosterPack. I found both on the Energia website.



What I noticed based on these diagrams, is that the Fuel Tank BoosterPack seems to have multiple I2C pins!

Using jumper wires, I tested the different I2C pins of the BoosterPack with the CC3200, until I found a working set.


After that, I connected the BoosterPack to the CC3200 and used the jumper wires on the CC3200 directly. Like so:

Screen Shot 2014-12-05 at 12.56.26.png

(Fritzing part for the CC3200 was found here: New CC3200 Launchpad Fritzing Part)


I removed the jumpers connecting the onboard sensors to the I2C bus and connected jumpers to the I2C pins attached to the underlying BoosterPack.

Because I removed the jumpers of the onboard sensor, I had to ensure the "pull-up" jumper on the BoosterPack was in place. You can verify the pull-ups are ok if the green and orange LEDs of the CC3200 are on.


With this little manipulation, I was finally having proper readings on the Fuel Tank's data with both Peter's code and the library:

Screen Shot 2014-11-23 at 22.33.50.pngScreen Shot 2014-11-23 at 22.42.08.png


Glitches in the readings


I did notice some glitches in the values read when doing the following:

  • connecting/disconnecting a charging source
  • having the CC3200 connected via USB to PC (for Serial output) at the same time




This is my current sketch. It's still very basic and rough, but it does the trick for now.

It will need to be improved to go into deep sleep after sending the values, until the next set of values is to be sent.


#include <WiFi.h>
#include <PubSubClient.h>

// Core library for code-sense
#if defined(WIRING) // Wiring specific
#include "Wiring.h"
#elif defined(MAPLE_IDE) // Maple specific
#include "WProgram.h"
#elif defined(MPIDE) // chipKIT specific
#include "WProgram.h"
#elif defined(DIGISPARK) // Digispark specific
#include "Arduino.h"
#elif defined(ENERGIA) // LaunchPad MSP430, Stellaris and Tiva, Experimeter Board FR5739 specific
#include "Energia.h"
#elif defined(CORE_TEENSY) // Teensy specific
#include "WProgram.h"
#elif defined(ARDUINO) && (ARDUINO >= 100) // Arduino 1.0 and 1.5 specific
#include "Arduino.h"
#elif defined(ARDUINO) && (ARDUINO < 100) // Arduino 23 specific
#include "WProgram.h"
#else // error
#error Platform not defined

// Include application, user and local libraries
#include "Wire.h"
#include "FuelTankLibrary.h"

WiFiClient wclient;
byte ip[]     = { 172, 16, 0, 100 };
PubSubClient client("", 1883, callback, wclient);
FuelTank myFuelTank;

#define       WIFI_SSID         "wifi57"
#define       WIFI_PWD          "**********"

void callback(char* inTopic, byte* payload, unsigned int length) {
// Handle callback here

void setup() {

void loop() {

void publishData() {
  WiFi.begin(WIFI_SSID, WIFI_PWD);
  while(WiFi.localIP() == INADDR_NONE) {
  // Give some time to settle

  char content[10];

  if (client.connect("CC3200-Room-1")) {
      sprintf(content, "%d", myFuelTank.voltage_mV());
      client.publish("cc3200-fvan\/voltage", content);

      sprintf(content, "%d", myFuelTank.timeToEmpty_mn());
      client.publish("cc3200-fvan\/tte", content);

      sprintf(content, "%d", myFuelTank.stateOfCharge_Percent());
      client.publish("cc3200-fvan\/soc", content);




The result of the data being received, as seen from openHAB:

Screen Shot 2014-11-27 at 14.57.12.png

ita.jpgThe In The Air Challenge is running from September 22nd to February 27th.

Previous Activity:

Blog Summary #000 : In The Air Challenge 2014

Blog Summary #001 : In The Air Challenge 2014

Current Activity:

Blog Summary #003 : In The Air Challenge 2014

Blog Summary #004 : In The Air Challenge 2014

Blog Summary #005 : In The Air Challenge 2014

Blog Summary #006 : In The Air Challenge 2014

Blog Summary #007 : In The Air Challenge 2014

Blog Summary #008 : In The Air Challenge 2014 - Final


NameSuper Awesome Blog Time
janisalnisIn-the-Air Challenge:  Texas Instruments MSP 430 FR5969 launchpad
dimonicNo Updates

In The Air [iot_healthy] #Post 5 : Its too Slow progress...


CC3200 Development in Visual Studio

Carbon Footprint Monitoring - Sensor Nodes

Carbon Footprint Monitoring - Emission Sensor


AirMobile - 6 - Temperature sensor

AirMobile - 7 - Humidity sensor

AirMobile - 8 - NO2 Sensor

AirMobile - 9 - CO sensor

AirMobile - 10 - Switching to "Plan B"

tomajaIn the Air Design Challenge - Pollen & Allergen Sensing – Post 3 (AirVantage Intro)

AirWise #4 - Project Milestones

AirWise #5 - Preliminary Schematic


HAB monitoring Post#5 ( BBB to AirVantage using Python with REST API )


No Updates


[Firecracker Analyzer]Brief update


Dust, Temperature and Humidity Monitor Chapter 5


Pollution Effect Minimiser (Post 4)


[AirCare] InTheAir - Week 5: openHAB and MQTT


IOT - In the Air Design Challenge - Portable Field Tester #3

IOT - In the Air Design Challenge - Portable Field Tester #4


In The Air: Episode 5 - PCB Design

Just a quick post with my preliminary schematic.

My plan is to prototype this circuit on a shield first and then to order a custom PCB board. Finalized schematic, BOM and layout to follow.

While creating the board layout, I realized (too late!) that the package I choose for the MSP430 was not available. I selected the MSP430FR5947 MSU because it has the same features of the MSP4305969 mounted on the LaunchPad but in a more handy TSSOP38 package. However this part is hard to find so I have to give up.

On the other hand, the MSP4305969 has a 48RGZ package, which determines a significant rise in costs because I for sure will never be able to place and solder such a small chip without making short-circuits. So I will have to ask some company specialized in surface mounting technique to solder the MSP43 and this definitely will make the budget I planned for this challenge to be over...

So I switched to the Boosterpack approach: I redesigned the board to plugin into the Launchpad. This is the result



I created the Gerber files and sent it to Wurth Elektronik PCB service. Now I'm waiting for the PCB. In the meantime, let's get the components and write down some software...


A Riddle: How many times in three weeks can a 1 year old child catch sick? The correct answer seems to be 3 times ...


Previous Posts

In The Air: Epidose 1: Introduction

In The Air: Episode 2 - Preparing for Surface Mount Work

In The Air: Episode 3 - Surface Mount Beginnings

In The Air: Episode 4 - Inductors



I have finished my Booster Pack design. Figure 1 shows the top and bottom layers. Note, I am an Altium user so the display of the board layers may be unfamiliar to you if you are an Eagle user. If you are familiar with TI's Booster Packs, you'll recognize the characteristic 20 pin headers on opposing sides of the board. In my last post I discussed choosing inductors for filtering/decoupling grounds and power supplies. Accordingly, we will discuss the layout of those inductors and separating grounds for quiet sensor performance in this post.


combo.png Figure 1: Bottom (left) and top (right) layers for my Booster Pack design.


Connecting Grounds

The general approach I have adopted is shown in Figure 3. The signal ground is like an island surrounded by the power ground, and the only way to get to the signal ground is through an inductor. The connector is on the boundary between the two grounds because the sensor requires both power and signal ground. I've created an annotated version of the board layout of Figure 1 and produced it in Figure 4. I have labelled the sensor interface, signal ground, and power ground. The power ground is directly connected to the ground of the C3200 through the Booster Pack header connections, and the signal ground is connected to the power ground through the aforementioned inductor.



Figure 3: Basic idea of the Particle Counter Booster Pack.



Figure 4: Annotated Figure 1 showing the sensor interface, signal ground, and power ground.


In Figure 5 I've zoomed in on the board so the signal ground is more visible, and the ground connecting inductor can be seen in the lower left (L2). You can't see the pads from the component because I used Seeedstudio Fusion for my PCBs, and Seeed Studio's design rules don't use a thermal relief pad connection by default. I'm not sure why, but that's the way it loaded. I didn't personally care for this project because I will be hand building the boards, so I left it alone. If I had loaded the rules before designing the board I may have changed it, but I loaded the design rules after. Disclaimer: especially in mass runs, use thermal reliefs on your ground connections to components as it will prevent tombstoning components during reflow.



Figure 5: Zoomed view of the top layer.


The 3D render of the board is shown in Figure 6. You can clearly see the pads for the inductor L2 in the lower left. I didn't bother using models for any components unless they were supplied by default, because I have no concern for height tolerances with this board. At this point in the design you may be wondering, why did he only use a single inductor, and not tie the grounds together at multiple points? The short answer is you'd be creating a ground loop, which can be a terrible problem to troubleshoot. You can look up the analysis for ground loops on PCBs, but if you only connect the grounds at one point you won't have to worry about it. You may have other issues, but a ground loop will not be one of them.



Figure 6: 3D Render of Particle Counter Booster Pack.


Power Supply Decoupling

In my last blog I spoke of decoupling power supplies as well as grounds. I've reproduced the schematic showing these decouplings in Figure 7.

You can see L2 is connecting the grounds, but what about L1; how is that implemented? In the same way. The inductor pads must straddle the gap between the power and signal ground. If you look back at Figure 5, you can clearly see L1 near the upper left straddling the ground boundary.

Supply Decoupling.png

Figure 7: Decoupling inductors


Still Confused?

How about a video explaining it then!



Final Remarks

I ordered my board. It was only $10 USD from Seeed Studio for 10 pieces. No one else could compete with that price, so I had to choose them. I've got my bill of materials ready to go, I'm just waiting to hear back about the possibility of samples from TI. Every IC on this board is made by TI, which was a bit of a challenge for me. Hopefully everything can arrive in time to put it together and write some software.