AirPi is an plug-and-sense, low cost weather station. It works as a shield for the Raspberry Pi, gathering data about temperature, humidity, air pressure, carbon monoxide, nitrogen dioxide, light levels, noise levels and even more. In this article we'll connect the AirPi Kit to the Ubidots cloud, creating a connected WiFi weather station.
1. Materials
Raspberry Pi Model B
USB WiFi Dongle
Airpikit v1.4
The kit includes the following:
MCP3008 (adc converter)
LDR (Light dependent resistor GL5528)
DHT AM23602 (Humidity and temperature)
MICS-4514 (NO2 and CO concentrations)
MIC electret (noise mesuarement)
BMP085 (pression, temperature)
2. Welding
If you have your Airpi already assembled you can skip this step. If you don't, we recommend this guide.
3. Coding your Raspberry Pi
Before we can start coding we'll need to fullfill some requirements:
You should've already configured your Raspberry Pi with Internet. If not, follow this guide, or check this blog post about setting up WiFi.
You'll need a Ubidots account. If you don't have one, create an account here and take note of your Api Key found in "My Profile --> API Key".
When ready, login through a terminal into your Raspberry Pi and set up the SPI module to communicate with the ADC:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
Add a "#" character before the line spi-bcm2708, then press CTRL-X, type Y and Enter. This enables SPI from the boot.
Install the python library called Ubidots, to do so you need to install first a package manager called pip:
sudo apt-get install python-setuptools
sudo easy_install pip
sudo pip install ubidots
Install the library called "py-spidev" in order to read data from SPI devices attached to the Raspberry Pi. To do this you'll have to install first "python-dev":
sudo apt-get install python-dev
mkdir py-spidev
cd py-spidev
wget https://raw.github.com/doceme/py-spidev/master/setup.py
wget https://raw.github.com/doceme/py-spidev/master/spidev_module.c
sudo python setup.py install
Awesome, SPI is ready, now we need to setup the Adafruit DHT library:
git clone https://github.com/adafruit/Adafruit_Python_DHT.git
sudo python Adafruit_Python_DHT/setup.py install
Now we need to restart the device:
sudo reboot
You can test if the library is working properly by typing:
cd Adafruit_Python_DHT/examples
sudo python AdafruitDHT.py 2302 4
We are ready to go. Now you can paste the following code into a new file called airpi.py (dont forget to put your own API Key):
sudo nano airpi.py
#!/usr/bin/env pythonimport time # Library for delaysimport RPi.GPIO as GPIO # Library for using the GPIO portsfrom math import log1p,exp,log10 # Library for math functions. No need for it if you'll get the raw data from the sensorsfrom ubidots import ApiClient # Ubidots Libraryimport Adafruit_DHT # Library from Adafruit to simplify the use of DHT sensor.# Set up the SPI interface pins. Through SPI we can connect to the ADC MCP3008SPICLK = 18SPIMISO = 24SPIMOSI = 23SPICS = 25GPIO.setmode(GPIO.BCM) # Set up BCM as numbering system for inputsGPIO.setup(SPIMOSI, GPIO.OUT) # Configure the SPI I/OGPIO.setup(SPIMISO, GPIO.IN)GPIO.setup(SPICLK, GPIO.OUT)GPIO.setup(SPICS, GPIO.OUT)# Setup VariablesdS = None # Ubidots Data source. We'll call Airpisensor = Adafruit_DHT.AM2302 # Especify the DHT sensor we will use # You can change this line for other DHT sensors like this: Adafruit_DHT.DHT11 or Adafruit_DHT.DHT22light = 0 # Save value of the LDRnoise = 0 # Save value of the Mic inno2 = 0 # Save value for Nitrogen dioxide levelco = 0 # Save value for Carbon monoxide levelhum = 0 # Save value for Humiditytemperature = 0 # Save value for Temperaturevin = 3.3 # Voltage reference for the ADC # Function to verify if the variable exists or not in your Ubidots accountdef getVarbyNames(varName,dS): for var in dS.get_variables(): if var.name == varName: return var return None# Function from Adafruit to read analog valuesdef readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) GPIO.output(clockpin, False) # start clock low GPIO.output(cspin, False) # bring CS low commandout = adcnum commandout |= 0x18 # start bit + single-ended bit commandout <<= 3 # we only need to send 5 bits here for i in range(5): if (commandout & 0x80): GPIO.output(mosipin, True) else: GPIO.output(mosipin, False) commandout <<= 1 GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout = 0 # read in one empty bit, one null bit and 10 ADC bits for i in range(12): GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout >>= 1 # first bit is 'null' so drop it return adcout# Code to connect a Ubidotstry: api = ApiClient("75617caf2933588b7fd0da531155d16035138535") # Connect to Ubidots. Don't forget to put your own apikey for curDs in api.get_datasources(): # Check if there's any Data Source with the name AirPi if curDs.name == "AirPi": dS = curDs break if dS is None: dS = api.create_datasource({"name":"AirPi"}) # If doesn't exist it'll create a Data Source with the name Airpi lightValue = getVarbyNames("Light_level",dS) if lightValue is None: lightValue = dS.create_variable({"name": "Light_level","unit": "lux"}) # Create a new Variable for light nitrogen = getVarbyNames("Nitrogen_dioxide_concentration",dS) if nitrogen is None: nitrogen = dS.create_variable({"name": "Nitrogen_dioxide_concentration", "unit": "ppm"}) # Create a new Variable for NO2 level mic = getVarbyNames("Noise_level", dS) if mic is None: mic = dS.create_variable({"name": "Noise_level","unit": "mV"}) # Create a new Variable for noise level carbon = getVarbyNames("Carbon_monoxide_concentration",dS) if carbon is None: carbon = dS.create_variable({"name": "Carbon_monoxide_concentration","unit": "ppm"}) # Create a new Variable for CO level temp = getVarbyNames("Temperature",dS) if temp is None: temp = dS.create_variable({"name": "Temperature", "unit": "C"}) #Create a new Variable for temperature humidity = getVarbyNames("Humidity",dS) if humidity is None: humidity = dS.create_variable({"name": "Humidity","unit": "%"}) # Create a new Variable for humidityexcept: print("Can't connect to Ubidots")while True: # Code to get light levels data light = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) # Read the analog pin where the LDR is connected light = float(light)/1023*vin # Voltage value from ADC light = 10000/((vin/light)-1) # Ohm value of the LDR, 10k is used as Pull up Resistor light = exp((log1p(light/1000)-4.125)/-0.6704) # Linear aproximation from http://pi.gate.ac.uk/posts/2014/02/25/airpisensors/ to get Lux value # Code to get audio levels from 20 hz frequency signalMax = 0 signalMin = 1024 startMillis = int(round(time.time()*1000)) # Time in milliseconds while (int(round(time.time()*1000))-startMillis<50): # Collect data for 20hz frequency, 20hz=1/50ms noise = readadc(4, SPICLK, SPIMOSI, SPIMISO, SPICS) # Read the analog input where the mic is connected if (noise < 1024): if(noise > signalMax): signalMax = noise elif(noise < signalMin): signalMin = noise peakToPeak = signalMax - signalMin print peakToPeak # Peak to Peak value db = float((peakToPeak*vin*1000)/1023) #Measure in mV time.sleep(0.1) # Code to read NO2 and CO concentrations no2 = readadc(2, SPICLK, SPIMOSI, SPIMISO, SPICS) # Read the analog input for the nitrogen value no2 = float(no2)/1023*vin # Voltage value from the ADC no2 = ((10000*vin)/no2)-10000 # Ohm value of the no2 resistor, 10k is used as pull down resistor no2 = float(no2/700) #Reference value time.sleep(0.1) co = readadc(3, SPICLK, SPIMOSI, SPIMISO, SPICS) # Read the analog input for the carbon value co = float(co)/1023*vin # Voltage value from the ADC co = ((360000*vin)/co)-360000 # Ohm Value of the co resistor, 360k is used as pull down resistor co = float(co/30000) #Reference value # Code to use the DHT sensor hum, temperature = Adafruit_DHT.read_retry(sensor, 4) if hum is not None and temperature is not None: print 'Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, hum) else: print 'Failed to get DHT sensor reading. Try again!' # Print sensor values to the console print "light[lux]:", light print "no2[ohm]:", no2 print "co[ohm]:", co print "noise[mv]", db # Post values to Ubidots lightValue.save_value({'value':light}) nitrogen.save_value({'value':no2}) mic.save_value({'value':db}) carbon.save_value({'value':co}) temp.save_value({'value':temperature}) humidity.save_value({'value':hum})GPIO.cleanup() # Reset the status of the GPIO pins
view rawAirpi.py hosted with ❤ by GitHub
Finally, run the code:
sudo python airpi.py
This script creates a data source called "AirPi" inside your Ubidots account, as well as individual variables for each sensor. Then it will continuously post the envirnomental data to Ubidots.
Now visit your Ubidots account and you will find the live data from the AirPi!
Once your data is in Ubidots, you can create a real-time dashboard, SMS/Email alerts (i.e "Shoot me an Email when the CO concentration is too high!") or read the data through our API in order to build more advanced applications.
Here's another cool project to create a real-time map without writing any web code:
Do you have sensor applications in mind? click below to get started.
Originally published on Ubidots Blog on July 16, 2014.