AirPi es una estación meteorológica de bajo costo, plug-and-sense. Funciona como un escudo para la Raspberry Pi, recopilando datos sobre temperatura, humedad, presión del aire, monóxido de carbono, dióxido de nitrógeno, niveles de luz, niveles de ruido y más. En este artículo conectaremos el AirPi Kit a la nube de Ubidots, creando una estación meteorológica conectada por WiFi.
1. Materiales
Raspberry Pi Modelo B
Dongle USB WiFi
Airpikit v1.4
El kit incluye lo siguiente:
MCP3008 (convertidor adc)
LDR (resistor dependiente de la luz GL5528)
DHT AM23602 (humedad y temperatura)
MICS-4514 (concentraciones de NO2 y CO)
Micrófono electret (medición de ruido)
BMP085 (presión, temperatura)
2. Soldadura
Si ya tienes tu Airpi ensamblado, puedes omitir este paso. Si no, te recomendamos esta guía.
3. Programando tu Raspberry Pi
Antes de comenzar a programar, necesitaremos cumplir con algunos requisitos:
Ya deberías haber configurado tu Raspberry Pi con Internet. Si no, sigue esta guía, o revisa este artículo del blog sobre cómo configurar WiFi.
Necesitarás una cuenta de Ubidots. Si no tienes una, crea una cuenta aquí y toma nota de tu Api Key que se encuentra en "Mi Perfil --> API Key".
Cuando estés listo, inicia sesión a través de una terminal en tu Raspberry Pi y configura el módulo SPI para comunicarte con el ADC:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
Agrega un carácter "#" antes de la línea spi-bcm2708, luego presiona CTRL-X, escribe Y y Enter. Esto habilita SPI desde el arranque.
Instala la biblioteca de python llamada Ubidots, para ello primero necesitas instalar un gestor de paquetes llamado pip:
sudo apt-get install python-setuptoolssudo easy_install pipsudo pip install ubidots
Instala la biblioteca llamada "py-spidev" para poder leer datos de los dispositivos SPI conectados a la Raspberry Pi. Para hacer esto, primero tendrás que instalar "python-dev":
sudo apt-get install python-devmkdir py-spidevcd py-spidevwget https://raw.github.com/doceme/py-spidev/master/setup.pywget https://raw.github.com/doceme/py-spidev/master/spidev_module.csudo python setup.py install
Genial, SPI está listo, ahora necesitamos configurar la biblioteca DHT de Adafruit:
git clone https://github.com/adafruit/Adafruit_Python_DHT.gitsudo python Adafruit_Python_DHT/setup.py install
Ahora necesitamos reiniciar el dispositivo:
sudo reboot
Puedes probar si la biblioteca está funcionando correctamente escribiendo:
cd Adafruit_Python_DHT/examplessudo python AdafruitDHT.py 2302 4
Estamos listos para comenzar. Ahora puedes pegar el siguiente código en un nuevo archivo llamado airpi.py (no olvides poner tu propia API Key):
sudo nano airpi.py
#!/usr/bin/env pythonimport time # Biblioteca para retrasosimport RPi.GPIO as GPIO # Biblioteca para usar los puertos GPIOfrom math import log1p,exp,log10 # Biblioteca para funciones matemáticas. No es necesario si obtendrás los datos en bruto de los sensoresfrom ubidots import ApiClient # Biblioteca de Ubidotsimport Adafruit_DHT # Biblioteca de Adafruit para simplificar el uso del sensor DHT.# Configura los pines de la interfaz SPI. A través de SPI podemos conectarnos al ADC MCP3008SPICLK = 18SPIMISO = 24SPIMOSI = 23SPICS = 25GPIO.setmode(GPIO.BCM) # Configura BCM como sistema de numeración para entradasGPIO.setup(SPIMOSI, GPIO.OUT) # Configura la I/OGPIO.setup(SPIMISO, GPIO.IN)GPIO.setup(SPICLK, GPIO.OUT)GPIO.setup(SPICS, GPIO.OUT)# Configura VariablesdS = None # Fuente de datos de Ubidots. Llamaremos a Airpisensor = Adafruit_DHT.AM2302 # Especifica el sensor DHT que usaremos # Puedes cambiar esta línea por otros sensores DHT así: Adafruit_DHT.DHT11 o Adafruit_DHT.DHT22light = 0 # Guarda el valor del LDRnoise = 0 # Guarda el valor del Mic inno2 = 0 # Guarda el valor del nivel de dióxido de nitrógenoco = 0 # Guarda el valor del nivel de monóxido de carbonohum = 0 # Guarda el valor de la humedadtemperature = 0 # Guarda el valor de la temperaturavin = 3.3 # Referencia de voltaje para el ADC # Función para verificar si la variable existe o no en tu cuenta de Ubidotsdef getVarbyNames(varName,dS): for var in dS.get_variables(): if var.name == varName: return var return None# Función de Adafruit para leer valores analógicosdef readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) GPIO.output(clockpin, False) # iniciar el reloj bajo GPIO.output(cspin, False) # llevar CS bajo commandout = adcnum commandout |= 0x18 # bit de inicio + bit de entrada única commandout <<= 3 # solo necesitamos enviar 5 bits aquí 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 # leer un bit vacío, un bit nulo y 10 bits ADC 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 # el primer bit es 'nulo' así que lo descartamos return adcout# Código para conectar a Ubidotstry: api = ApiClient("75617caf2933588b7fd0da531155d16035138535") # Conectar a Ubidots. No olvides poner tu propia apikey for curDs in api.get_datasources(): # Verifica si hay alguna fuente de datos con el nombre AirPi if curDs.name == "AirPi": dS = curDs break if dS is None: dS = api.create_datasource({"name":"AirPi"}) # Si no existe, creará una fuente de datos con el nombre Airpi lightValue = getVarbyNames("Light_level",dS) if lightValue is None: lightValue = dS.create_variable({"name": "Light_level","unit": "lux"}) # Crear una nueva variable para la luz nitrogen = getVarbyNames("Nitrogen_dioxide_concentration",dS) if nitrogen is None: nitrogen = dS.create_variable({"name": "Nitrogen_dioxide_concentration", "unit": "ppm"}) # Crear una nueva variable para el nivel de NO2 mic = getVarbyNames("Noise_level", dS) if mic is None: mic = dS.create_variable({"name": "Noise_level","unit": "mV"}) # Crear una nueva variable para el nivel de ruido carbon = getVarbyNames("Carbon_monoxide_concentration",dS) if carbon is None: carbon = dS.create_variable({"name": "Carbon_monoxide_concentration","unit": "ppm"}) # Crear una nueva variable para el nivel de CO temp = getVarbyNames("Temperature",dS) if temp is None: temp = dS.create_variable({"name": "Temperature", "unit": "C"}) #Crear una nueva variable para la temperatura humidity = getVarbyNames("Humidity",dS) if humidity is None: humidity = dS.create_variable({"name": "Humidity","unit": "%"}) # Crear una nueva variable para la humedadexcept: print("No se puede conectar a Ubidots")while True: # Código para obtener datos de niveles de luz light = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) # Leer el pin analógico donde está conectado el LDR light = float(light)/1023*vin # Valor de voltaje del ADC light = 10000/((vin/light)-1) # Valor en ohmios del LDR, se usa 10k como resistor pull up light = exp((log1p(light/1000)-4.125)/-0.6704) # Aproximación lineal de http://pi.gate.ac.uk/posts/2014/02/25/airpisensors/ para obtener el valor en Lux # Código para obtener niveles de audio de frecuencia de 20 hz signalMax = 0 signalMin = 1024 startMillis = int(round(time.time()*1000)) # Tiempo en milisegundos while (int(round(time.time()*1000))-startMillis<50): # Recopila datos para frecuencia de 20hz, 20hz=1/50ms noise = readadc(4, SPICLK, SPIMOSI, SPIMISO, SPICS) # Leer la entrada analógica donde está conectado el micrófono if (noise < 1024): if(noise > signalMax): signalMax = noise elif(noise < signalMin): signalMin = noise peakToPeak = signalMax - signalMin print peakToPeak # Valor Peak to Peak db = float((peakToPeak*vin*1000)/1023) #Medir en mV time.sleep(0.1) # Código para leer concentraciones de NO2 y CO no2 = readadc(2, SPICLK, SPIMOSI, SPIMISO, SPICS) # Leer la entrada analógica para el valor de nitrógeno no2 = float(no2)/1023*vin # Valor de voltaje del ADC no2 = ((10000*vin)/no2)-10000 # Valor en ohmios de la resistencia de no2, se usa 10k como resistor pull down no2 = float(no2/700) #Valor de referencia time.sleep(0.1) co = readadc(3, SPICLK, SPIMOSI, SPIMISO, SPICS) # Leer la entrada analógica para el valor de carbono co = float(co)/1023*vin # Valor de voltaje del ADC co = ((360000*vin)/co)-360000 # Valor en ohmios de la resistencia de co, se usa 360k como resistor pull down co = float(co/30000) #Valor de referencia # Código para usar el sensor DHT hum, temperature = Adafruit_DHT.read_retry(sensor, 4) if hum is not None and temperature is not None: print 'Temp={0:0.1f}*C Humedad={1:0.1f}%'.format(temperature, hum) else: print 'Error al obtener la lectura del sensor DHT. ¡Inténtalo de nuevo!' # Imprimir valores del sensor en la consola print "luz[lux]:", light print "no2[ohm]:", no2 print "co[ohm]:", co print "ruido[mv]", db # Publicar valores en 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() # Restablecer el estado de los pines GPIO
ver rawAirpi.py alojado con ❤ por GitHub
Finalmente, ejecuta el código:
sudo python airpi.py
Este script crea una fuente de datos llamada "AirPi" dentro de tu cuenta de Ubidots, así como variables individuales para cada sensor. Luego publicará continuamente los datos ambientales en Ubidots.
Ahora visita tu cuenta de Ubidots y encontrarás los datos en vivo del AirPi!
Una vez que tus datos estén en Ubidots, puedes crear un panel en tiempo real, alertas por SMS/Email (es decir, "¡Envíame un correo electrónico cuando la concentración de CO sea demasiado alta!") o leer los datos a través de nuestra API para construir aplicaciones más avanzadas.
Aquí hay otro proyecto interesante para crear un mapa en tiempo real sin escribir ningún código web:
¿Tienes aplicaciones de sensores en mente? haz clic a continuación para comenzar.
Publicado originalmente en Ubidots Blog el 16 de julio de 2014.