The Metro cities all around the world are facing a lot of problem because of the increasing population, which is resulting in an exponential pollution rise, which is a very serious problem and needs immediate attention.
But the problem is that there is no proper monitoring device for these Urban environments, so we are unable to get any reliable data. Even if there are devices to monitor the conditions, they are in limited number due to the current cost - to - reliability and accuracy count.
So, What's the Solution?The UQM - A quality Monitor designed specifically for urban environments. Please note that I have designed this device keeping in mind the Indian metro city conditions, as cities like Delhi are one of the most polluted cities in the world when it comes to Air Pollution.
Lets get started with the project.
Components RequiredThe main Hardware components required for this project are stated and explained in brief below:
1. The NXP Rapid IoT prototyping kit
This is the main component of the sensor node, as this is the device with all the embedded sensors. This will collect the data, show it on its LED Display, and send it to the Raspberry Pi via Bluetooth. It comes with a pre installed demo application which I have explained in the video given below.
2. Raspberry Pi
The Pi will get the data collected by the Kit via Bluetooth and send it to the Adafruit IO feeds using a simple Python code. We need BLE for this project, so I would recommend you to use any device with embedded Bluetooth chip.
The best choice would be the Pi Zero W, but I didn't have one so used the Pi 3B.
3. A Battery Bank - for Powering the device.
This is all, so lets get started with the Project.
Building the Project - HardwareSo, first lets have a look at a simple schematic diagram describing the workflow of this project.
This diagram describes the whole workflow of the project. So, lets start with the Basic Functionality of our device first.
1. Basic FunctionalityNow, the device works in the following manner:
1. The device has a Raspberry Pi and the Rapid IoT prototyping kit as its hardware components. The Rapid IoT acts as a sensor node and sends all the data to the Pi via Bluetooth (Python Code explained later). Each Pi accesses its location via Internet (as I couldn't get the GPS click board in time).
2. Now, the Pi uses this data in the following ways:
- It firstly stores this data locally in the form of csv file for creating a database. It stores sensor values, and the latitude and longitude on their current position.
- Secondly, for web interface, this data is sent to the Adafruit IO platform, for visualization in the form of graphs, meters, etc.
- The data is also sent to a Fire base database, so that this can be used and accessed by the Android app users, so they can view this data even remotely.
3. We can analyse the csv file data using numpy and matplotlib to create heatmaps, and also plot this data on the map (as we have the location data).
So, overall this project has all the features required for a quality monitoring device to operate at its maximum efficiency. So, lets start with the project.
2. NXP Rapid IoT Studio AppNow, to develop new firmware applications for your Rapid IoT prototyping kit, you need to use the rapid IoT studio and the MCU Expresso SDK for more advanced development. As I got the kit with less than 20 days left for project submission deadline, we will stick to the easy to use Rapid IoT studio.
i) Getting Started Rapid IoT Studio
The IoT Studio is easy to use. There are many user references for this purpose:
ii) Building our Application
Now, due to the shortage of time, we will be creating a simple weather station application which would be able to take the following sensor values:
1. Temperature
2. Humidity
3. Ambient Light
4. Pressure
5. Air Quality (CO2 Concentration in ppm)
In addition to that, we will create two new function triggers to get the value of BatteryLevel and the Charging Status of the Rapid IoT device. This Device will also have an Anti-TheftFeature, in which the device will send an alert of it senses any unwanted motion(motion detected using the Accelarometer of the Rapid IoT).
The code for the same is given in the Rapid IoT Reference Manual.
According to the manual in Chapter 4: Battery sensor, we can get the current battery state by using this function.
Function for getting the Battery Sensor State
In the NXP Rapid Studio, click the element function. Then click the code view which we can write some custom functions that fits our needs.
Add this code to get the Charging State of the device.
ATMO_Status_t Charging_State_trigger(ATMO_Value_t *in, ATMO_Value_t *out)
{
uint8_t batteryPercentLevel = 0;
uint8_t batteryChargingState = 0;
BatterySensor_GetState(&batteryPercentLevel, &batteryChargingState);
ATMO_CreateValueUnsignedInt(out, batteryChargingState);
return ATMO_Status_Success;
}
Then also add another function and paste this code to get the Battery Percent level of the device.
ATMO_Status_t Battery_Level_trigger(ATMO_Value_t *in, ATMO_Value_t *out)
{
uint8_t batteryPercentLevel = 0;
uint8_t batteryChargingState = 0;
BatterySensor_GetState(&batteryPercentLevel, &batteryChargingState);
ATMO_CreateValueUnsignedInt(out, batteryPercentLevel);
return ATMO_Status_Success;
}
So, the final Project image of our UQM Device is given below.
This project will have some additional features :
1. If the air quality index is above 175 ppm, the RGB LED of the device will turn red warning the user and below this threshold value, the RGB LED will remain Green, indicating safe air.
2. It have theft protection using motion sensing, and also it is able to share its location to the user.
Now, the next step is to compile and load the firmware into the Rapid IoT device.
iii) Load the Firmware
Before loading your own custom firmware, make sure you saved your project. Then click the compile button which is located in the upper right part of the IDE. If everything is fine, a notification will prompt the the compilation is successful. Click the download button which will then download the firmware of the device (*.bin).
In uploading the firmware to the device, follow the instructions which can be found here on how to upload the firmware to the device. All of the instructions that I said from compilation, downloading the firmware up until uploading it in the device is discussed in that document. (Page 133 - 134)
Detailed instructions on how to upload the firmware to the device can be found in the link above.
An alternative to this is just by pressing the top left and bottom right buttons to enter into flash mode. The video is the same is shown below.
3. Adafruit IO - Web InterfaceNow that we have our data, need a platform to visualize it graphically for better interpretation and understanding. So, for a interactive web interface, we will be using Adafruit IO Platform. So, we will be following the below steps to do that:
i) Create an Adafruit IO Account
Go to https://io.adafruit.com/ and create an account.
Why Adafruit IO?
It is a very easy to use platform with python as there is minimal settings, you just need to give your userid and key to connect to your feeds, nothing else!
Just like any free platforms, there are also some limitations in using this platform.
Adafruit IO Free Plan
In the free plan, we are limited to 30 data points per minute, 30 data storage, 10 feeds and 5 dashboards per account.
Terminologies:
- Feeds - Feeds contain the sensor data that we are sending from the device. For more info ( https://learn.adafruit.com/adafruit-io-basics-feeds)
- Dashboard - Dashboards allow you to visualize data and control Adafruit IO connected projects. For more info (https://learn.adafruit.com/adafruit-io-basics-dashboards)
ii) Obtain the AIO Key
Now that your account is created, you have to click on the view AIO Key option on the left menu, to get your username and key, which will be used to connect your python client with the Adafruit IO.
Now, you first have to install the Adafruit IO library for python on your Pi. For that, simply use the following command:
sudo pip install Adafruit_IO
Once done, import it in your python code as :
from Adafruit_IO import Client,Feed
Now, once you have it imported, you can initialize the connection using these commands:
ADAFRUIT_IO_USERNAME = "Dhairya_1998"
ADAFRUIT_IO_KEY = "Your Key"
aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) #Starting the Adafruit Client
After this is done, we now have to create feeds for our project on the Adafruit IO website.
iii) Create Feeds on Adafruit IO
We will be creating 5 feeds which correspond to:
- Ambient Light
- CO2 Level
- Humidity
- Pressure
- Temperature
Just like what I have stated earlier that in free plan, we can only create 10 Feeds (Maximum). So if you are planning to modify this and send some other data, you should take this into consideration.
NOTE: After Creating all feeds, please do take note of the Key column in the feeds table as we will be needing this in getting the value of that specific feed later.
Now, after created, we have to define the keys of each feed on the python program which is shown by the code snippet given below.
#Defining the feed keys
light_feed = aio.feeds('light-feed')
temp_feed = aio.feeds('temp-feed')
humidity_feed = aio.feeds('humidity-feed')
air_feed = aio.feeds('air-feed')
pressure_feed = aio.feeds('pressure-feed')
Another significant feature of adafruit.io is that you can download a feed data in CSV Format. Just go to the Feeds => Click the specific feed you want to download and down below there is a button to download all the data (Reminder: Storage is only for 30 Days for Free Plan)
Now, to push the obtained data to the feeds, we use the following code:
#Sending this data to the Adafruit io feeds for furthur analysis
aio.send_data(light_feed.key, light_value1)
aio.send_data(temp_feed.key, temp_value1)
aio.send_data(humidity_feed.key, humidity_value1)
aio.send_data(air_feed.key, air_value1)
aio.send_data(pressure_feed.key, pressure_value1)
Download data of a specific Feed just by clicking on the download button.
iii) Creating a Dashboard for All of Our Feeds
Create a dashboard that will be the home for all of your feeds. Click Action > Create a New Dashboard and fill up the necessary data like the name of your dashboard.
Next, click the dashboard that you have created.
This is what an empty dashboard looks like
Now, let's create some blocks in the dashboard. Blocks are widgets that we can add base on the value from a feed. Click the plus icon in the upper right.
Blocks available in Adafruit
A detailed explanation on what is the function of each specific blocks can be found in the documentation of adafruit here.
This is what our final dashboard looks like after adding gauges and line graphs for data visualization.
I have also sent the battery level and the charging state of the device, so we can even add that to the dashboard, which I haven't done for now, but its just as easy as adding 2 new elements to the Dashboard.
Now, our Web Visualization part is over.
Local StorageAs we saw above, we can download the data in csv format on the Adafruit IO platform, but we have certain drawbacks when free plan is considered which are :
1. We can only download the last 30 day data.
2. We get a csv file for each feed, so we have to merge those into a single file manually.
So, to overcome these drawbacks, I have added a small code snippet in which the obtained data in stored in a local csv file itself, so that it can be used later for analyzing the conditions of that particular locality.
csvData = [['Sensor','Value','Latitude','Longitude'],['Temperature',temp_value1,lat,lon],['Humidity',humidity_value1,lat,lon],['AirQuality',air_value1,lat,lon],['AmbientLight',light_value1,lat,lon],['Pressure',pressure_value1,lat,lon]] #data to be stored
with open('data.csv','w') as csvFile:
writer = csv.writer(csvFile)
writer.writerows(csvData)
print "Data stored in csv file successfully"
csvFile.close()
This is a simple code snippet used to write csv files with the data, csvData in the above case.
This local data can be useful for training machine learning models that predict the weather and air quality of a particular area or locality.
Remote Access via Android AppThe Rapid IoT data can be visualized via BLE using the Rapid IoT app, as shown below.
But what if we want to get real time data remotely, without being anywhere near the device, which would be the practical case in the real world.
Of course, we can use the Adafruit IO dashboard for this, but for an end user, who would be a normal person busy with his day to day life, how would he get time to go search for the dashboard, sign in and then see the data. It is just not a fruitful way, and moreover with the increasing number of users, we can't use the same account.
So, I had a solution for this problem too. I pushed the sensor data to a Firebase database using the "put" method for overwriting the data.
After that, the android app will simply fetch this data and display, which enables us to monitor various elements in real time. This section is divided into 3 parts:
Part 1. Fire Base Setup
Part 2. Fire Base integration with python code
Part 3. Android App integration and Data fetching from Firebase real time Database.
Our Final App will be a single activity app. Its image is shown below:
Step 1. Fire Base Setup
We need to first create a new firebase project. To do so, you need a google account, using which you sign in to through following url:
You will see the sign in option as shown in the figure below, from which you sign into your google account and then go to the Console using the Go to Console option shown in the image below.
The Console looks something like this:
Create a new project now:
Once done, you will be redirected to project homepage.
Now, go to Develop > Database and create a real-time Database.
Add the fields and shown in the above picture for this project, or you can add your own fields too if you have some knowledge or have previously worked with firebase.
Now, to link an Android application to the Firebase Database, just follow this easy tutorial shown in the video below:
This completes our Fire Base Setup.
Step 2. Firebase integration with Python Code
First, to use FireBase with Python, you need to download the python-firebase library. To do that, simply execute the line shown below in the Pi terminal:
sudo pip install python-firebase
This will install the library. Now, the import command for the code is:
from firebase import firebase
After this is done, you have create a Firebase application for your code using the following command:
firebase = firebase.FirebaseApplication("Your Firebase URL")
Now, you can copy your Firebase URL from the database page of your project. The image showing the URL is shown below.
Now, change the database rules for read and write to true, so that you can write into the database using the python code.
Now, it is really simple to send your data to firebase real time database from your python code. Just use the following code snippet, in which I sent 5 sensor data values to the Database.
I used 'Put' method to send the data, so it will be replaced every time a new data is sent, which will be reflected by a color(yellow) change in the firebase database.
#Send the data to firebase for real time monitoring remotely
firebase.put('urban-quality-monitor','Temperature',temp_value1)
firebase.put('urban-quality-monitor','Humidity',humidity_value1)
firebase.put('urban-quality-monitor','Ambient Light',light_value1)
firebase.put('urban-quality-monitor','Air Quality',air_value1)
firebase.put('urban-quality-monitor','Pressure',pressure_value1)
So, this concludes the firebase python integration.
Step 3. Fire Base integration to Android App
Now that we have the sensor data in our Database, we can fetch this data from our Android App and display it. If you have followed the instructions from the above video to create an android app integration, you will just have to follow these steps:
1. Create some Data Text Views which will be set to the read values and give some text views that will give the description of the data being displayed. Give appropriate id's to the Data text views so that we can find and set them via Java code. My Activity_main.xml file looks something like this.
2. Now that we have the text views, lets move to the MainActivity.java code. Firstly, import the google firebase database files we are going to use for the project.
import com.google.firebase.database.DataSnapshot;import com.google.firebase.database.DatabaseError;import com.google.firebase.database.DatabaseReference;import com.google.firebase.database.FirebaseDatabase;import com.google.firebase.database.ValueEventListener;
Now, for this to work, you need to add a dependency in the app gradle file.
implementation 'com.google.firebase:firebase-database:16.0.6'
Now, after this is done, we create an Instance of the database and get a reference of the parent using the following command. We also define the text view variables.
TextView temp, humidity, air, light, pressure;
final DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Name of the Table");
Now, we find the values of the text view by their ids using the following code snippet.
protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); temp = (TextView) findViewById(R.id.temp); humidity = findViewById(R.id.humid); air = findViewById(R.id.air); light = findViewById(R.id.light); pressure = findViewById(R.id.pressure);}
After this, we create and onStart function to fetch or read the data from the above referred table, 'urban-quality-monitor' in my case.
The function will have an addValueListenner() function of Firebase, which will read and set the value of the text views. The code snippet for the same is given below.
protected void onStart(){ super.onStart(); reference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { temp.setText(dataSnapshot.child("Temperature").getValue(Float.class).toString()); humidity.setText(dataSnapshot.child("Humidity").getValue(Float.class).toString()); air.setText(dataSnapshot.child("Air Quality").getValue().toString()); light.setText(dataSnapshot.child("Ambient Light").getValue().toString()); pressure.setText(dataSnapshot.child("Pressure").getValue(Integer.class).toString()); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } });}
So, this is all that is required for the android app. Our app is finally ready and can be now tested.
Video DemoNow, the video Demo of the whole project is given below.
Sorry for the fact that I didn't have any casing for my project showcase. I actually got my Rapid IoT kit just a few days back, so couldn't focus much on the Hardware casing in such a Short span of time.
So, This was all about my Project.
Vote of ThanksI would like to thank NXP for giving me the opportunity to build such a project. It won't have been possible without your Hardware and the constant technical support from the authorities.
I would also like to thank Hackster for providing such a platform for innovators, where they get to share and showcase their knowledge and learn something beyond the books. :)
Please respect the project if you like it and follow me, so you don't miss our more of such practical and innovative projects.
Comments