Stuff related to Arduino

Airsense, when things go wrong

I have had the opportunity to run another data collection for characterising the Airsense air quality sensor. The data collection started at the end of June 2018. I co-located my sensors with the official City Council’s one in High Street, Oxford. The site sits just in front of the All Souls college. After a couple of weeks the college decided to start renovating its facade. Shortly the whole thing was covered in scaffolds and a sort of protective plastic.

I managed to sneak in with the City Council office to check the situation, and this is what we found. There was scaffolding on top of the cage, which prevented it from being removed, so my sensor was stuck there until the end of the works!


The works ended in December 2018! And this is how I found it:


The amount of dust and dirt was such that I doubt the data would have been reliable at all.

During this whole time, the device was supposed to be running and storing its data on the SD card. I went to read the data from the SD card, and, instead of more than 5 months wort of data, I only found about 30 days. Given that my device timestamps with a relative clock (Arduino millis() function), I couldn’t even relate it with the reference data.

In other words, the whole thing was a waste of time!

Lesson learned for the next time: do not rely on the SD card alone, better send it to a server immediately. This would have two advantages: 1) the server could precisely timestamp the samples and 2) I could monitor if the sensor is sending stuff and intervene in the case of failure.


Airsense: second validation

In my last post, I showed a DIY air quality sensor built with Arduino and how I tried to calibrate / validate it.

I am still working on it. In fact, it is not clear at all if, once I’ve calibrated the sensor, the measurements would be still valid and for how long.

So, thanks again to the support of the Oxford City Council, I have run another calibration / validation round.


I have decided to focus this calibration on nitrogen dioxide only, because it’s probably the most complicated pollutant to measure reliably. So I have removed the sound sensor, the MQ2 sensor and the particulate sensor.

As noted in the previous post, the data spitted out by the electrochemical sensors: SPEC and Alphasense were quite noisy, likely due to the low resolution of the Arduino ADC. So this time I have decided to use a 24-bit analogue-to-digital converter. I used a cheap Chinese board based on the ADS1256 chip. Unfortunately there are no Arduino libraries around to control the chip, but I managed to put together some lines of code to control it by using some examples I’ve found online and by reading the datasheet.

As for temperature and humidity I have decided to switch to the GROVE temperature, humidity and pressure sensor (based on the BME280 chip). The addition of pressure may be beneficial to modeling the sensors’ response?

As for the metaloxide sensor, I have left the Mics 2714 sensor as it was, but I have also added the GROVE multi gas sensor. This is based on the Mics-6814, which is a model that came after the Mics 27154 and that contains three sensors into the same package for measuring NO2, CO and NH3. The GROVE board has a microcontroller on it that samples the data and sends it via I2C, which allows us to save some pins. Importantly, the GROVE board is easy to connect, and does not require any soldering.


Data collection

The settings were the same as last time. My device was left side-to-side with the official City Council’s monitor inlet.

I left the device sampling and writing on a SD card every minute, while the official monitor also provided data every minute. The data collection started on the 12th of January 2018 and ended on the 17th.

Unfortunately, the GROVE multi gas sensor failed for some reason, even though it was working perfectly in the tests at home, and did not provide any data at all. In any case I still had the Mics 2714 as a backup.


If we look at the correlation among signals:

Signal NO2 NOx NO
Mics 0.29 0.41 0.40
SPEC 0.33 0.29 0.23
Alpha1 0.06 0.06 0.22
Alpha2 0.34 0.32 0.26
Alpha (1-2) 0.04 0.07 0.08
Temp 0.03  0.07  0.08
Hum -0.18 -0.07 -0.00
Pressure 0.13 -0.18 -0.17

Compared to the previous calibration round, we can clearly see that the SPEC and Alphasense sensors have an increased correlation. This must be the effect of using the 24-bit ADC.

The raw data is visible here (click to open the interactive chart):


As done last time, I have removed noise by averaging over 30 minutes and then used the data for linear regression.

Using the former linear regression

The question is: if I use the coefficients computed using the data acquired the year before, will the estimations be as good as before?

Because of the fact I have changed some sensors, I have re-trained the linear regression with the data of the first round, but using only those signals that are in common with this second round: temperature, humidity and Mics 2714.

Then I used those coefficients to estimate the NO2 levels using the second round data. The accuracy of the estimates were not as impressive: if with the round 1 data we obtained 3.62 ppb average error, and 0.75 correlation, with round 2 data we have 7.90 ppb average error and 0.56 correlation.

The signal looks like this:


The reasons I can think of can be two: either the sensors drift, or I hadn’t collected enough data in round 1 to be able to “generalise” the model. Or a combination of both.

What if we perform another regression?

Now, if we use the data collected from round 2 to train the linear regression model, how does it perform?

Let’s use all the available signals:



Now, this looks like a good estimation !

The correlation between estimated and actual samples is 0.93 and the average absolute error is 1.70 ppb. Impressive!

Do we need all those input signals?
By playing around with signals I have observed that:

  • The air pressure signal doesn’t add anything significant
  • We can use either SPEC of Alphasense, the accuracy will be similar, but we shouldn’t remove both of them



To sum-up:

  • The sensor can be built using almost all GROVE-compatible sensors (although I haven’t managed to actually use the multi gas one, I think it would perform similarly to the Mics 2714).
  • If we use a decent ADC converter, the SPEC sensor can be actually pretty useful.
  • The Alphasense sensor provides much better data with a more powerful ADC too.

As future work, I’d like to run a long-lasting data collection round, to see how and if the sensors drift over time.

From the device design perspective, I may try to send the data over network instead of relying on the SD card. This way I can monitor the device and, if something goes wrong, I can try to intervene.

AirSense: a DIY, cheap, air quality sensor

This post summarises the results of an experience that has been going on for more than a couple of years now.

When I moved to Oxford, the committee of the residential area I live in sent an email expressing some concerns about the consequences of a local developments on air quality. As a good neighbour, and maker, I proposed them to build an air quality sensor to monitor the situation.

I was aware of several initiatives of DIY air quality sensors, like the famous Air quality egg, so I thought that I could try to emulate one of them.

I didn’t know at that time where I was getting myself into. It turns out that building a device is quite simple, but validating it is completely another story.

Let’s try to explain it in a simple way.


Mine is surely not the first attempt to build a DIY air quality sensor. There are some good guides online, I have particularly appreciated these sources:

In order to understand the legislative framework in Europe, I suggest to have a look at this very nice HandBook about EU air quality legislation.

Finally, the local authorities of Oxfordshire publish a very handy chart with historic measurements of air quality: see the Oxfordshire air quality reference website.


Air quality is an umbrella word that identifies a whole bunch of pollutants. To be in line with the EU legislation, I have decided to measure the following quantities:

  • Temperature and humidity
  • Noise level
  • Concentration of particulates
  • Concentration of nitrogen dioxide

the sensor should be able to save data on a SD card, it should be operated on batteries or line power and should be placed outdoor.


to simplify its development, I have decided to use Seedstudio’s GROVE system, which allows plugging sensors to an Arduino board without any soldering. these are the components I have used:

The total price was about 115€.

If you want to replicate this experiment, check the current offer of Grove-compatible sensors on Seedstudio, because the offer for air quality is growing constantly!

While all Grove-compatible devices didn’t need soldering, the MICS 2714 board was a bit trickier. The component is sold for very little, but it’s hard to solder by an amateur. So I have bought a board with pins that makes the job easier (but costs 5 times the original price).

Be aware that Mics has released some new components that measure other gases too like the Mics 4514 or the Mics 6814 and there are reference boards or products for Arduino too.

Advanced materials (and why they are needed)

Making the long story short: this experiment has allowed me to involve other parties including the Oxford City Council, the Network for clean air UK and some people from Ricardo, the official provider of air quality monitoring for Oxford.

Thanks to their help and sponsorship, I was able to also integrate two more advanced sensors:

Both are chemical sensors for nitrogen dioxide with electronic analog front-ends (the circuitry needed to interface them with a micro-controller). These are more expensive devices (200 to 300 € when including the interfacing electronics), but are based on a much more solid technology than the Mics 2714. The Mics sensor is a metal-oxide sensor. It is simpler to produce but it is less accurate and, most problematically, it is more sensitive to interference (e.g. humidity) and tends to drift over time. The other 2 sensors are chemical sensors and should be more accurate and more stable over time.

So I have decided to combine all these modules together in one device and plugged all of them to an Arduino.

Building the device

Building the device was very simple. All sensors are plug-and-play except the Mics 2714 that required a bit of soldering. I used the reference design provided with the datasheet and this is how it appears:


Mics 2714 interfacing board

This was connected to ground, 5V and one of the analog pins of Arduino.

The SD card reader wasn’t Grove-compatible either, but examples of how to connect it are easy to find.

At the end this is how the device looks like if we don’t include the “advanced” sensors.


Sensors connected to the Grove shield

To this, I added an LED that to give some feedback if everything is working OK and a little computer fan, to suck air in from outside and to keep temperature under control.

The advanced sensors were also easy to install. They are both powered with the 5V output of Arduino and their measurement pins (1 for the SPEC sensor and 2 for the Alphasense sensor) where connected to 3 analog pins of the Arduino.

For what regards the casing, I used a plastic food box. The box is sealed and doesn’t allow rain to come in (good for placing it outdoor). I made two openings on the box so that air could be exchanged with the outside and to avoid overheating. In order to lay all the components I took a piece of cardboard and made holes in it, then I tied the components to the cardboard using some metal wire. The Arduino board was placed inside a plastic cup so that if the box gets some water in it, the electronics is protected anyway.

The sketch used on the Arduino was also really straight-forward. After start-up, the used ADC pins are sampled, the dust ratio is computed for 30 seconds (see reference code), the temperature and humidity are taken from the DHT sensor (see reference code) and all the values are logged in a file on the SD card together with the timestamp (see millis). Then the board waits for other 30 seconds, so that, in total, a sample of each quantity is taken every minute.

Characterisation and calibration

Now we need to convert the raw data, as measured by the ADC of the Arduino, into actual quantities (concentrations, decibels etc.), and this is where the things get very complicated.

All manufacturers of the sensors provide a datasheet with some graphs you can use to do this conversion, but unfortunately, these are not always to be trusted 100% because of differences in the produced components or because of drifts. For this reason I have decided to perform a characterisation campaign myself.

Sound characterisation

The idea here is to convert the raw samples read by the microphone into decibels. As a reference, I have bought an inexpensive, second-hand decibel monitor (about 15 € on eBay). Then, at home, I connected my laptop to my stereo and put on some white noise generator as this one. On Arduino, I measure the maximum and minimum values of the input from the microphone (the amplitude) for a period of few seconds.

The procedure is simple: I start the noise on the laptop, I start the Arduino sketch and I print the amplitude on the screen while I note down the reference decibel on the external device. I repeat this operation several times at different volumes and I note down the numbers on Excel.

Here’s the result:


Relationship between the amplitude (difference between maximum and minimum) and the reference sound intensity.

You can see that there is clearly a relationship between the amplitude and the decibels and, not surprisingly, it’s logaritmic.

NO2 characterisation: 1st attempt

The idea here is to locate my sensor next to a reference one (so that they “sniff” the same air) and to compare what is measured against the reference. To have enough points, I decided to take a measurement of at least 24 hours and in a place with enough traffic so that the range of concentrations is as wide as possible.

The first characterisation campaign was launched in September 2015. I contacted the Oxford City Council Air Quality officer, who, very kindly, let me locate my sensor on top of the official one in a busy street in the centre of the city. My sensor was few centimetres apart from the inlet of the official monitor, so it should have measured the same air!


Airsense placed next to the official City Council’s monitor inlet.

The problem I encountered was energy supply. My device was by far not optimised and there was no plug on top of the cabinet containing the official monitor. I tried different combinations of battery supplies (even with 10 9V batteries in parallel!) and, eventually, I found a cheap 5000 mAh battery bank that would let run my device for 35 hours.


Useless set of 10 9V batteries in parallel.

I left my sensor gathering data for about a day and then I downloaded the official monitor’s data from the official website. The monitor provides hourly averages, so I had, in total, about 24 samples only. Here is how the Mics 2714 data looks like compared with the NO2 reference:


NO2 official measurements (1 hour average) versus raw data of the Mics 2714 sensor (1 hour averages)

There’s no clear trend or relationship between the signals. Definitely, the number of samples is too small and we need to do something more clever.

NO2 characterisation: 2nd attempt

A year passed, and I managed to liaise with both a new City Council officer and a person who could help me getting raw data from the official monitors. Together we set-up a new data collection campaign. This time the monitor would provide minute-by-minute samples and we found a way to bring an electricity cable from inside the cabinet to the top (so no power limitations any more!). Then we left the devices collecting data for about a week.

This is how raw data appear (warning: big and messy graph! select the plots on the right of the chart).

The reference signals are NO, NO2 and NOX. All the others are raw data as measured by the Arduino ADC (except temperature, humidity and dust).

Worth mentioning, is that signals are not aligned in time (some start or end earlier and there is no sample-by-sample alignment) and they are quite noisy too. So we need to a) align them and b) try to reduce the noise a bit.

We can also already notice that some signals present some similar trends (the Mics signal notably) and other seem to be completely unrelated (the SPEC signal for example). So I have computed the correlation among all these inputs and outputs. These are the results:

Signal NO2 NOx NO
Mics 0.44 0.46 0.43
SPEC -0.01 -0.00 -0.01
Alpha1 0.15 0.15 0.11
Alpha2 -0.02 0.01 0.09
Alpha (1-2) 0.17 0.19 0.19
MQ2 0.09 0.09 0.08
Dust 0.05 0.04 0.04
Temp -0.03 -0.03 -0.02
Hum -0.00 0.04 0.06

You can see that the Mics signal is the only one that has a decent correlation.

Note: it is important to note down the exact time when the experiment starts as measured by both your device and the official monitor, otherwise then it’s impossible to align them!

In order to do sample-by-sample comparisons, I have created a little program in JavaScript (running on nodeJS) that aligns the samples and interpolates them when the timestamps do not match. In total, I had 8154 aligned samples per signal.

Then I have:
  1. Taken the 30 minutes averages of the signal to remove (some) noise. This brings down the number of samples to 273 per signal.
  2. Regressed different combinations of signals with different combinations of their powers (up to the 3rd) against the reference NO2 (I used this simple regression library).
  3. Compared the regressed signal with reference (all of it, thus no training-test distinction, with obvious possibility of overfitting). As metrics I have computed the average, median and maximum absolute error and the correlation between the regressed signal and the reference
These are the main findings:
  • The cheap metal-oxide Mics 2714 sensor, after regression, obtains an average absolute error of 3.82 ppb and correlates with the reference signal 0.7.
  • If we add temperature and humidity to the model, the error remains about the same (3.62 ppb), but the correlation goes up to 0.75 (maybe because effects from humidity are partially compensated?).
  • The Alphasense signal, taken at pin 1 alone, has an average error of 4.62 ppb and correlates 0.55 with the reference.
  • If we add humidity and temperature to the Alphasense signal, error becomes 3.81 ppb and correlation 0.69.
  • If we regress Mics, Alphasense, humidity and temperature all together we get a very interesting 2.76 ppb error and 0.87 (!!!) correlation.
The rest of the sensors (dust, SPEC, MQ2) didn’t add anything interesting.
This is how the best regressed signal (Alphasense + Mics + humidity + temperature up to the 3d power) looks like against the reference. Not too bad, but we are of course risking over-fitting here.

Best regressed signal vs reference (click to see interactive graph)

I have also tried with other de-noising methods, like a moving average, or averages over shorter and longer periods of time. The results change slightly, but not substantially.


In conclusion:
  • Building a DIY air quality sensor is relatively easy and inexpensive, but needs to be calibrated or it will provide measurements that are not meaningful.
  • The cheap, metal-oxide Mics 2714 sensor seems to be promising, but it is affected by interference (likely humidity or maybe other gases too).
  • The Alphasense device performed worse than expected, but combined with the metal-oxide sensor creates a very good estimator.
  • The SPEC sensor, as used here, provides only noise.

Future work

I would need to perform another data collection campaign. The aim would be to confirm these findings and to check that the Mics sensor doesn’t drift over time.
Also, I want to use a 24 bits ADC with the Alphasense and the SPEC sensor next time. Especially with the Alphasense, you see that the range of values is small and it’s possible that some information is lost in the quantisation noise.
I also want to try this adapted MICS sensor sold by Seedstudio. It is based on the MiCS-6814, and, by looking at the datasheet, it seems that it embeds the same NO2 sensor used in the 2714, plus it adds 2 others. It would be cheaper than my approach and would be super simple to install.
Ah, and I would still have to validate the dust sensor too.
Future-future work:
Probably more advanced machine learning techniques would lead to even better results. There might be information hidden in non linear transformations, or derivatives of these signals, who knows?
But the more ML approach we take the more we would need to corroborate the results.
I will keep you updated with more experiments and results on this blog !

Intrusino, a new friend in pIoT-land

It’s been a while since I haven’t published anything about pIoT.

This is because I have beenquite busy with many things, and one of these it’s this shiny new pIoT node, I’ve called it intrusino.

It’s placed over the back door and its role is to detect when people open the door and pass by.

Its main sensors are two: a simple magnetic contact sensor and an extremely small, low power, low cost movement sensor (PIR).

Both sensors are attached to an interrupt. The node works this way: it stays in low power mode (except from the PIR, which is always on) and is woken up by either the PIR or the door sensor. If the status of the PIR or the door is different from the previous one, a message is sent. Also, each hour, the node sends its state anyway.

I have observed that the PIR sensor is not completely stable, which means that, if one passes next to it, it will produce a short burst of 1 and 0 zeros. In order to avoid sending too many packages, I have programmed the node to only send PIR updates if an update hasn’t been sent for more than 2 minutes.

In addition, I have also plugged the usual light sensor.

Here is how a single message looks like on the server:


The “movement” field is an average of the PIR detections over the last hour. The higher the number, the more movement was detected. “DoorOpen” means that the door was opened when this packet was sent.

If we look at some graphs over a day:

We can see clearly the light over the day and also the little tail around 8 PM that is the light coming from the kitchen. In terms of movement, you can see when people was moving around the backdoor, typically in the morning to go to work, or in the afternoon to go to do some shopping. That suspicious activity around 4 AM must be the cats!

The server can also be programmed with a rule to light up an LED in the bedroom whenever the door is opened. This can be used to tell people when someone is coming in, or as an intrusion detection at night!

Here’ s how the rule looks like:



I am powering this node with 3 AA batteries. This was necessary because 2 batteries were not enough to power the PIR sensor, but, be careful, the PIR needs 3.3V maximum, therefore a voltage regulator is necessary. Alcaline batteries last about 1 month. In the future I will likely try to install a small solar panel on it, given that the sensor is exposed to natural light all the day.

A year of pIoT, lessons learnt

About a year ago I posted about an Internet of Things platform I was developing for my home: pIoT.

The platform includes a simple hardware design based on the ATMega328 micro-controller (the same as Arduino UNO), an Arduino compatible firmware, and a server, actually two servers, one made in Java and another made in nodeJS.

In April 2015 the development of the platform was more or less completed, and I started deploying nodes around the house where I am living. Plus, I dedicated a small computer to the server and a node as a gateway between the server and the rest of the network.

So the situation, at the moment, is like this:


it’s composed of a Raspberry PI and a node attached to it with a USB to TTL module.


The software running in the server is the version based on nodeJS (see some screenshots below). As CSS framework I have used Bootstrap, so that the web page is also easily visible on mobile phones.
The server has several functionalities:

– it gives a summary of the status of the sensors and some measurements (dashboard)
– it allows connecting to the serial port and give basic input/output
– it parses the messages coming from the pIoT node (which are in JSON)
– it sends messages to the pIoT network, for example to control some actuator
– it stores all received data into a no-SQL database (nedb) and allows visualising data and plotting simple graphs
– it allows setting up rules so that when some data arrives, an action can be performed

This slideshow requires JavaScript.

The device is located in the conservatory of the house, this choice was due to the fact that it was half way between the router (giving Internet access) and most of the nodes.
I have also setup a dynamic DNS and a static port routing so that the server can be accessible from outside of the local network (no, I won’t give you the address).


there are three nodes at the moment in my house (not considering the one connected to the server).
One node measures light intensity, temperature and soil moisture. It is located in the conservatory and also measures the moisture of the soil of a plant. The intention is to monitor the status of the plant and warn when the level of water is too low. The node is operated by two AA batteries and sends data each hour. In a previous post, I described how to build the moisture sensor.


A second node is located outdoor. It measures light intensity, temperature, humidity, soil moisture and the presence of rain. Its main purpose is to give information about the weather. This node is operated by 3 rechargeable AA batteries (it needs a low-power voltage regulator to not burn the radio module) and a 6V solar panel. It also sends data each hour.


A third node is located indoor, in my bedroom. It measures light, temperature and humidity and has a powerful RGB LED that can be activated remotely (in that sense it’s both a sensor and an actuator). The intention is to monitor the temperature in home and to have a sort of visual output of the system. This node is operated by a USB charger, so it includes a voltage regulator to bring the voltage down to 3.3V. The bedroom is located opposite to the conservatory in the house plant, so data transmission is quite difficult as there are some walls to be traversed. Data are sent each hour, but the node is continuously listening for incoming commands, that’s why the choice of powering it from the line, otherwise batteries would have been consumed very quickly.


Collected data

So far I have received 27359 messages. Most of the messages (12801) are of type “hello” which is sent by all nodes and describes the internal status of the node. These messages include information like the number of packets lost, the operating voltage, the internal temperature as measured in the microcontroller.
Another big chunk (11360 message) is represented by “garden” messages which are sent by the outdoor node and the one in the conservatory. These messages include temperature, light, humidity, rain presence and soil moisture.
The other two categories of messages are “room” (3161 message), that contain information about the light, temperature and humidity of the bedoorm and “color” (only 37) which descirbe the status of the RGB LED.

Consider that the system was not always 100%, 24h/24 ON. It had some down times because I was updating something, or because the power went off or other reasons. But I can probably say that the system was ON at least 80% of the time within this year.

In total, the database occupies about 4 MB, which is prefeclty bearable by the Raspberry. Consider that nedb loads all the data into memory, so, if the DB grows a lot, probably I’ll have to archive some old data.

So now that we know what is the deployment and what data is there more or less, here’s the lessons learned.

Lessons learned:

Crappy batteries are… crap

I have used a wide range of batteries during this year. From expensive Duracell, to very cheap batteries bought in Poundland. Well, the difference is evident.

In the following graph you can see how fast a “good” battery is depleted on a node sending a message each hour.


That’s about 2 months. Now see what happens with cheap batteries:


That’s only about 2 weeks!

In theory, at the rate I am sending data now, if you switch all modules off properly, batteries should last several months if not years. I am not sure why I am consuming power faster than foreseen, I have tried different approaches to improve it, but the situation doesn’t change. Changing batteries every 2 months is not too bad, but it’s not ideal either.

Solar works!

So, here a possible solution to power consumption: adding a solar panel.

And it works!

During winter I had to charge the batteries myself manually about 3 times. Since days have started to last longer (about March) I have never had to recharge the batteries again!


In the graph you can see that the voltage is practically constant at 3.4V except one value, probably an artefact.

Packet loss is inevitable

pIoT configures the NRF24 module to retry transmitting a packet up to 7 times in case of failure. This gives a good amount of assurance that the packet is sent, if the connection is good enough. Even with this setting, packet loss happens.

I have computed the average packet loss for a the three nodes installed at home: for the node located in the conservatory, I get 18% of packets wasted, for the one outdoor: 24% and for the one indoor, almost 51%. That’s quite a big percentage, but it’s also expected. The nRF24 module was not designed for this range. Even though it says that it can reach 100 m, in reality it was thought for very short range communications, like for wireless keyboards or mouse. Still, it’s quite impressive that we can get useful data in an environment such as a house made of bricks.

… and sometimes it works unexpectedly well

It is not surprising that the node located in a room opposite to where the receiver is has such a high packet loss. Actually it is quite surprising that it receives data at all.

I have also observed that, when packets are sent by the server though, they are quite likely to be received by the node even though the packet loss on the other direction is pretty high. I don’t know exactly why, but it’s pretty reliable. And that’s also a very good news as, in fact, that node is used to warn the user when some action has to be taken (like pouring water to the plants,).

August is nicer than December

That’s a pretty obvious one, at least here in UK. Let’s see it from the perspective of natural light. The following two pictures show the light as measured by the outdoor node in a day of August 2015 and on in December 2016. You can see clearly that in August light starts at 4:00 and ends around 20:00, while in December it starts at 8:00 and ends at 16:00. Eight hours difference!

This slideshow requires JavaScript.

If we look at the outdoor temperature on two random days of August and December 2015:

This slideshow requires JavaScript.

Temperature in December spans from few degrees over 0 to 10 degrees (Celsius). In August we get temperatures between 10 and 20. It’s interesting to see that the range of variation in a day: in both months it’s about 10 degrees.

…but my room’s temperature is stable

the two charts below show the temperature in my room as measured by the indoor node. One chart is related to a day in August, the other to a day in Feburary.

As you can see, although there’s an obvious difference between the two days, the temperature, is quite stable throughout the day.

This slideshow requires JavaScript.

Micro-controller internal temperature needs calibration

I have used this trick to measure the internal temperature of the ATMega328. I have calibrated the raw values as received by the ADC with a thermometer I had at home and using an air dryer to raise the temperature. There was a very clear correlation between the raw values and the actual temperature and the formula I gathered was:  temperature = (ADCW * 0.9873) – 330.12. This calibration was done on one single MCU.

When using the same formula on other nodes, though, it stopped working. As the charts below show, there is an evident correlation between the temperature as measured internally and as measured with a more precise DHT, but the internal measurement is not correct. This means that, basically, each single microcontroller needs a different calibration.

This slideshow requires JavaScript.

s*#t happens!

Yes, and very often too!

Here’s an example of actual 💩:


Why do these things happen?

I have no idea, but I can only speculate that, although the NRF24L01 has its internal checksum, some data corruption happens anyway. pIoT libraries do not add an extra checksum, so, if you need absolutely clean data, you’d better add it.

Electronics is incredibly resilient

Well, mostly.

Look at this node:

it has been in the wild for 16 months: rain or sun, winter or summer, with high humidity, insects of all sorts trying to build their home inside, and it was all covered by just a plastic box (actually of cotton buds). It’s a bit rusty inside, but still, it was able to survive and send data without (almost) any human intervention.

Soil moisture measurement is not sustainable

The outdoor node measures moisture thanks to two metal nails.That’s not unprecedented, but it’s not very reliable either. The nails tend to get rusty and to corrode over time (see picture).


Nonetheless, as a rough estimation, it’s still good enough. The following charts show soil moisture and rain over the same period of time. There is some sort of correlation between the two, although not very strong.

This slideshow requires JavaScript.



My personal conclusion is that pIoT, as it is now, is a very interesting prototype, but it can’t compete with commercial, ready-made solutions. I wouldn’t rely on my pIoT installation to run critical things like theft alarm, or fire extinguishers, but it’s more than enough for things like gardening, or just for learning some electronics!

There are surely other interesting, and maybe less-obvious, findings that can be derived from the data collected over more than one year. For example, from the indoor node I may get some behavioural information (e.g. sleep patterns). So I may update this post with some other findings if they occur to me later. Meanwhile, if anybody wants to have a peek at my data for doing some research, I’ll be happy to give them !

pIoT a pico/personal Internet of Things DIY platform

This post is a follow up and an evolution of this previous one. I am pretty proud to present here a work that has been going on for more than a year. It all started with some friends at MakeSpaceMadrid. We wanted to create a super-cheap, Arduino-compatible with embedded wireless communication, electronic board. We decided to adopt the very well-known Arduino UNO ATMega 328p as microcontroller and the nRF24L01 wireless chipset as communication module, both sold for about 1€ on the Chinese market. We called our project Sensorino. We did a lot of things, but the project took longer than expected. Its code is still on github and everybody is welcome to contribute. While Sensorino was slowly being developed, I forked it on a personal, simpler project, and called it pIoT.

So what´s pIoT?

It’s a collection of three things: a hardware design for custom boards with a microcontroller and the wireless communication chip, the firmware that runs on the microcontroller and a server that collects data, shows it and executes rules. The project is open source and available on github for anyone to download or contribute.

pIoT board

A pIoT board

At the moment most of the functionalities are there: the board design is extremely simple, it’s just the ATMega328p connected to an nRF24L01+ module, the firmware contains a library for exchanging messages over the nRF24 module, a library for managing energy consumption (that is, putting the microcontroller into sleep modes) and a library for exchanging JSON messages with a host computer, the server software is programmed in java and takes care of parsing packets, visualising data on web using GWT and implementing rules using the mvel expression language. A new version of the server for nodejs is also on its way.


A screenshot of the server interface

The topology of the network is simple, there is one “base” node connected to a host computer through a serial port, the computer running the server code, and a set of “peripheral” nodes, which can be both sensors or actuators, that send/receive data to the base. More complex topologies are possible, but routing is not supported at the moment (for this, I suggest the very interesting RadioHead project). I am writing a tutorial for helping set up the whole thing.

pIoT topology

pIoT topology

I have created a testbed at home, with an old laptop working as server (a Raspberry Pi would also do) and two nodes, one that senses data from a plant (as already published a in previous post) and one that acts as a remote controlled colour LED. It works, and, as far as now, battery consumption is quite good. I have had the plant sensor running on two AA batteries for a couple of months.

pIoT server

The pIoT server

Garden pIoT node

A pIoT node in the garden


There are still things missing of course, but a complete proof of concept is already there and promising. If you are interested in the project and willing to collaborate, I will be very pleased to help!

A simple Arduino garden sensor

This is not the first time Arduino is proposed for gardening, you can see nice examples here and here, or here, and even here. Anyaway, I would like to tell you how I made it even though it’s not that original.

My sensor has three elements: a moisture sensor for the soil, a light sensor and rain sensor.
Let’s see the three parts separately.

Light sensor:

it’s a very standard LDR (photoresistor) example, like this one. You connect an LDR between 5V and an analog pin and the pin to a 47KΩ resistor that goes to ground.


Moisture sensor:

I have used two nails as electrodes, as suggested in many places, like here. You need two long nails and a sponge. You solder the nails to two wires. If you can’t solder the wires, just wind them around the nails and solder just the wire. The you cut the sponge to obtain a rectangle of 5cm long and you put the nails inside, this way the wires won’t go away easily.

Then you connect one of the two wires to the 5V pin, the other to an analog pin and you connect the same pin to ground through a 10KΩ resistor.

The principle is simple, the two nails are put into the soil and act as electrodes. If the soil is completely dry, there will be no current between the electrodes and the value measured at the analog pin will be zero. With a lot of water there will be a relevant current between the nails and the measured value will be higher.

I have done some experiments and my values are like this:

dry soil: 0
some little water: 200-400
some fair water: 500-700
quite a lot of water: 700-750
soaking wet: 800-…


Rain sensor:

I was inspired by these kind of sensors they sell on the Internet. To emulate it, I used a proto perf PCB board the kind with holes connected in lines. I used a thin wire, peeled a piece of it, double the length of the board and “sewed” it around the lines in order to connect lines two by two. Then with another wire you do the same but with the lines that are not connected yet. This way half of the lines (the even) belong to one wire and the other half (the odd) to the other wire. When a drop of water falls between two lines, it generates a little current that can be detected by the Arduino. To wire it to Arduino, you connect one wire to 5V, the other to an analog pin and the same pin to ground with a 10kΩ resistor.

By measuring the values at the analog pin with different amounts of water I get these:

dry: 0
some drop: 300-400
fair a mount of water: 500-600
soaking wet: 800-…


At the end, when you put all together you have something like this:

Regarding the sketch to be used on the Arduino it’s up to you. At the moment I am just measuring the values of the analog pins and doing some experiments (the code is not even worth publishing).