We typically spend around 90% of our time indoors. Good ventilation is essential to maintain good health. This project should increase the awareness of how important it is to periodically open the windows and let fresh air in.
The project name "UBAIRTICLE" is a word contraction of "Ubidots - Air - Particle", which brings all pieces together.
Connect "the things" togetherThe microcontroller collects data from the sensors and publishes them to the Particle Cloud. From there it is forwarded to Ubidots in order to persist and visualize them on a dashboard.
SGP30 Gas Sensor
The SGP30 is responsible to measure the air quality. It provides eCO2 (equivalent calculated carbon-dioxide) concentration within a range of 0 to 60, 000 parts per million (ppm), and TVOC (Total Volatile Organic Compound) concentration within a range of 0 to 60, 000 parts per billion (ppb). The typical accuracy of the signals is 15% within measured values.
The following features have been implemented in order to increase the sensor output signal precision:
- on-chip humidity compensation
- storage of baseline values in regular intervals and restore at power-up
SHT31-D Temperature & Humidity Sensor
The SHT31-D is responsible to measure air temperature and humidity. The typical accuracy is ±2% for relative humidity and ±0.3°C for temperature.
Particle Photon
The Photon is a tiny Wi-Fi development kit for creating connected projects and products for the Internet of Things. It's easy to use, it's powerful, and it's connected to the cloud.
The complete source code is hosted on GitHub. The "main loop" of the firmware has the following responsibilities:
- read current temperature & humidity values from SHT31-D
- trigger the SGP30 humidity compensation (to increase precision of air quality signals)
- read air quality values (eCO2 and TVOC) from SGP30
- read and store the SGP30 baseline (so that it can be restored at power-up)
- publish data to the Particle cloud
// loop() runs over and over again
void loop() {
MeasurementData sample;
// SHT31-D
readTemperatureHumidity(sample);
// SGP30
setHumidityCompensation(sample);
readAirQuality(sample);
readBaseline(sample);
refreshBaseline(sample);
// Pubish to Particle Cloud
publishMeasurementData(sample);
// Wait until next sample
delay(10000);
}
Particle CloudThe Particle cloud receives the published data, but does not persist them. So all events that you see in the console are gone once you close the session.
In order to store the data, we will create a "Webhook Integration" that forwards the data to Ubidots.
Follow the official tutorial to create your Ubidots Webhook. After that, modify the form to map the Particle variable names to Ubidots variable names:
Once the data is in Ubidots, you can start to create the dashboard.
Custom HTML Widget
The standard widgets allow you to show the data as numbers, gauges and charts. For the VOC level I have created my own custom widget:
Widget-HTML contains a background image and a text:
Widget-CSS defines the style:
Widget-JS contains the logic:
var $bg = $('#image_background');
var $text = $('#value_text');
var lastValue = null;
function changeFields(value) {
var levelText = '..';
var background = {
excellent: 'https://i.imgur.com/DII5UKR.png',
good: 'https://i.imgur.com/ih3Ks8d.png',
moderate: 'https://i.imgur.com/ggP3vPl.png',
poor: 'https://i.imgur.com/vedTFcq.png',
unhealthy: 'https://i.imgur.com/FJ2mMdH.png'
}
if (value <= 65) {
levelText = 'excellent';
$bg.css('color', 'white');
} else if (value > 65 && value <= 220) {
levelText = 'good';
$bg.css('color', 'white');
} else if (value > 220 && value <= 660) {
levelText = 'moderate';
$bg.css('color', 'white');
} else if (value > 660 && value <= 2200) {
levelText = 'poor';
$bg.css('color', 'white');
} else if (value > 2200) {
levelText = 'unhealthy';
$bg.css('color', 'white');
}
$text.text(levelText);
$bg.css('background', 'url(' + background[levelText] + ') 0 / contain no-repeat');
}
function getLastValue(variableId, token) {
var url = 'https://things.ubidots.com/api/v1.6/variables/' + variableId + '/values';
$.get(url, { token: token, page_size: 1 }, function (res) {
if (lastValue === null ||res.results[0].value !== lastValue.value) {
lastValue = res.results[0].value;
changeFields(lastValue);
}
});
}
setInterval(function () {
getLastValue('YOUR_VARIABLE_ID', 'YOUR_SECRET_API_TOKEN');
}, 1000);
HousingThe most fun part of the project was to build the case. Since I don't have a 3D printer at home, I used some classic LEGO technics bricks.
The sensors are thermally decoupled from Particle Photon, which is powered through a USB power supply.
Comments