While working very concentrated on projects (like this one) it happens quite often to me that I forget about my environment. Suddenly sitting in the dark or not recognizing that fresh air is needed is not uncommon. Previously, I purchased a well known branded fancy Smart Sensing Weather Station, and I really loved how packed it was with sensors. I loved how much data they provided. But tinkering with it, I realized, I didn’t have local access to my personal data on a bloody device that is literally sitting next to me. The device only works with an internet connection, and all of my data is stored on their servers.
Having a sensor/device connected to the internet does not make it smart!
As a tinkerer I thought I can do that as well and maybe even better, get the same sensor data, add notifications and statistics to it all, but with the slight difference that my data and logic will be stored and processed locally.
So here’s what I did: I took my Raspberry Pi and attached sensors to it for temperature, humidity, air quality, ambient light and a barometric pressure. I decided to use nymea, my favorite IoT middle-ware, and wrote plug-ins for the sensors. Nymea provides a bunch of stuff out of the box, such as logging, statistics, notifications and rules, so that would easily allow me to add some actual smart behavior in my environment.
ComponentsI used several I²C sensors, which I got from Amazon. I was looking for a I²C air quality sensors, but I wasn’t able to find any for a reasonable price, so I hooked a cheap analog air quality sensor to an Analog to Digital Converter (ADC for short). I used a Raspberry Pi 3B+, but a similar hardware platform, that supports the I²C interface would do just fine.
- The temperature and humidity sensor: I found the
SHT30
sensor would be most suitable for my use case. It was cheap, and took care for the physical influence between humidity and temperature. Reading the values using the data sheet was straight forward. - The pressure sensor: very popular pressure sensor is the
BMP180
. Using this sensor, I could also get the temperature and humidity, since those values are needed for a correct measurement. The sensor was calibrated in the factory, and the calibration data was stored in the chip, which I found very neat. The data sheet provided me with all the necessary steps on how to get the pressure. You could also calculate the altitude if you want to, but I didn’t really need that for my use case - The light intensity sensor: There are a lot of sensors out there for this purpose. I was looking specifically for one, that is suited for measuring the visible light, since I wanted to use this sensor for my living room. I chose the
TSL2561
, which gives me the full spectrum of light intensity measurement, and additionally, gave me the infrared light intensity spectrum separately. That was really handy, because it allowed me to subtract the infrared spectrum measurement, from the full spectrum, and that results in a light measurement suitable for humans. - The air quality sensor. Finding a suitable air quality sensor without spending a bunch of money proved to be a bit challenging. I ended up with an analog MQ-135 air quality sensor. It measures different gases in the air like NH3, NOx, alcohol, benzene, smoke and CO2. Digging on more information for this sensor has shown that it’s not the easiest thing to single out a certain gas from the sensor. The calibration had to be done for each individual sensor (finding R0) and the sensor needed a “burn in” phase of at least 24 hours before giving any useful data. A detailed description and an in-depth research on the sensor can be found here. The code of the mathematical model behind it can be found here. I implemented the model and the result was more informative than accurate in my case, but more on that later.
Since I²C is a parallel bus and each I²C device has a different default register address, there was no need to change the address and all devices can be connected directly. The air quality sensor has an analog output, therefore an ADC was needed. For this I used the ADS1115
ADC, also connected to the I²C bus allowing me to read the analog value as digital representation. There are still three free inputs, I'll probably extend the station with additional sensors in the future. I placed the temperature sensor as far away from the air quality sensor as possible, since the air quality sensor contains a heating element which gets hot.
Once connected, I checked with i2c-detect
if all devices show up correctly according to the appropriate datasheets on the Raspberry Pi.
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- --
40: -- -- -- -- 44 -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
0x39
The light sensor TSL25610x44
The temperature/humidity sensor SHT300x48
The ADC ADS1115 (where the MQ-135 is connected to AI0)0x77
The pressure sensor BMP180
As a base operating system for my Raspberry Pi I used the latest Raspbian. After flashing the image to the micro SD card using etcher I went directly to the wiring and development.
First I installed nymea (my favorite open source IoT platform) from the official repository.
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key A1A19ED6
sudo apt update
sudo apt install nymea nymea-plugins nymea-cli libnymea1-dev git libi2c-dev
The plug-in for the sensor station is not suitable for the main repository, since this is a DIY project, but you can get the source code from my github account and build it for your system:
# Clone the source code on the Raspberry Pi
git clone https://github.com/t-mon/nymea-sensorstation-plugin.git
cd nymea-sensorstation-plugin
# Build the plugin against the current libraries
mkdir build
cd build
qmake ../
make -j$(nproc)
# Finally install the plugin and restart nymea
sudo make install
sudo systemctrl restart nymead
In my setup I have the Philips Hue lights, the Kodi media center, an LG Smart Tv, the weather information from where I live and some other devices and services integrated. I also enabled the remote connection in order to have the push notification service on my phone (the data will remain locally, I only use the cloud connection to connect remotely and to receive push notifications). These are the devices I want to control, based on the data I get from my new sensor station.
And now it also contains my new sensor station!
Once the plugin development was done, I installed the plugin on my system and added the sensor station as a "thing" by using nymea:app as system client.
While developing the I²C sensor reading mechanism (starting a thread constantly to read the data in the loop) I realized that each sensor generates a lot of data, and has also some noise in the signal. To prevent a huge amount of data being dumped on the log database, rule engine and overall system performance I had to do some filtering. At the point of writing this article, the reading interval of the system is 5 minutes. This seems to be a good interval for reading slow changing sensors like temperature, humidity, and pressure. When it comes to quick changing sensor data, such as light intensity or air quality sensors, the system reacts slowly. For example: I switch on my lights, and in the worst case scenario, the system will recognize the light increase 5 minutes later. Not great. The current light measurement works perfect for the slow daylight changes, but it’s not the best in handling rapid changes. The problem is the huge noise in the data, which makes a classic low-/high-pass filtering or PID regulators useless, since you have to filter so strong, that you loose the quick responding effect.
Maybe a reader of this article has a solution for this problem? Is there a filter model/method for having smooth nice data changes on noisy signals, but quick response time on strong changes like switching on the light?Interpretation of the data
I placed the sensor station next to my couch in the living room (since that is the point of interest where I want the most comfort) and I let the system collect data for a few days in order to see how the sensor data performs in my environment
In the app overview I see the current values of my station.
In the morning, when I start my day, I open my blinds and windows since my flat is isolated very well. The data from my new sensor station represents my “getting up” routine nicely, as you can see in the following diagrams (screenshots straight from the app). I opened my window at 8:30 in the morning for 20 minutes.
- The temperature dropped about 3°C after opening the window. The heating then regulated the temperature back to the desired 22.5°C.
- The humidity dropped significantly after opening the window.
- The pressure is dropping slowly today, It's a sunny winter day.
- The light intensity shows a big peak in the morning. This was direct sunlight trough the window to the sensor, then the sun raised higher. At approximately 10:30 I opened the second blind where you can see the step. The normal brightness in the room around noon is at ~1100 lux. Then the value slowly goes down until sunset.
- The air quality measurement dropped after opening a window significantly. The lower the value the better the air. If I keep the window open for like 2 hours, the value is around 300 ppm. After closing the window again the value slowly goes up.
In the afternoon when it was getting darker outside I checked the sensor data again with following results (I have not opened a window, was alone here and my wife came home at ~16:30 from work).
- The temperature raised a little bit during the day (it was sunny). And dropped in the late afternoon (the heating turned on again).
- The humidity went up during the day and has a peak at ~18:45, where I actually started to cook.
- The pressure changes are very small. Not sure yet what to do with these data.
- The light intensity went down together with the sun. Sunset on this today was at 17:53. But in my living room it was already dark at ~17:00, where the value had ~80 lux. That's the point where I would switch on the lights. Here we can also see when I switched on the lights in the kitchen for cooking, between 18:45 and 19:20.
- The air quality measurement raised during the day, and there is a bigger peak at ~16:30 when my wife came home since 2 people are breathing in the room. Another peak when I started to cook.
After getting a good feeling about the sensor values it was time to define some rules and actions depending on those data. For my "problem" I defined two rules.
The first rule which I called Air quality notification
should inform me if the air quality is bad, so I can open a window and my mind remains fresh and awake. According to the data gathered during the day I realized, that a ppm value above 2000 ppm is where I can sense that fresh air is needed (coming back into the room after a walk). If this value would represent only CO2, I would probably be dead with 2000 ppm, but the sensor is detecting multiple gases, so there's a lot of space for interpretation. For a precise measurement I definitely would choose another sensor, but for my needs, it does the job.
The rule sends a notification to my phone and to my media center, once the value goes above 2000 ppm.
The second rule which I called Light sensor rule
should switch on my couch background lights, but only if the TV is currently on. I could do this in 2 ways, either check if Kodi is currently playing (I watch TV using Kodi PVR plugin for Mythtv) or using the Smart TV plugin by detecting if the TV is reachable. Both cases would do the job for me. I could also use the presence sensor plugin, which checks the presence of a network device in the LAN. If my phone or the phone of my wife is in the network, switch on the light, if the light intensity goes below 80 lux.
It works! After using the indoor sensor station for more than 2 weeks now I am aware that I'm opening the window more often, and I was never suddenly sitting in the dark since I use it. To me, it was surprising which daily actions of mine I recognized in the sensor data. Since the data is stored locally and mine, I have no bad feelings regarding the data gathered. The functionality (besides the phone notification) does not depend on my internet connectivity.
What's next?There are several things I want to do with my new sensor station. A few ideas:
- Building a RF outdoor station, sending data to the system using 6LoWPAN or Zigbee.
- Adding more sensors for getting better information of my surroundings. There are still three analog inputs available and a lot of registers on the I²C bus. More data, more information, more autonomous behavior.
- Having a smooth brightness increase while it's getting darker would also be very nice. This feature is still missing in nymea, but hopefully this feature will be implemented soon.
- Make a better sensor filtering of the light intensity and air quality for detecting peaks like: blowing smoke into the sensor or switching on the light for having a quick reacting behavior. Maybe somebody can help me out there? :)
- Detecting repeating patterns in my data using FFT like the window opening event, cooking, having guests, drinking alcohol.
Comments