Introduction: Detecting Natural Events With Qualcomm Dragonboard 410c
By Dominik Reller and William Mingardi
Description
We want to be able to detect natural events before and during it. For that we are using four sensor, a cloud and twitter to allow us to detect them. The sensors used are able to detect light, temperature, tremors and a button click. We also use twitter to monitor if any user is reporting a flood or tremors in the city. Any significant event triggers a notification by email.
Components:
- Dragonboard 410c
- Linker Base Mezzanine
- Sensors
- Light Sensor
- Linker Temperature
- Linker Tilt
- Touch Sensor
How it Works
There are some events that may trigger a notification depending on the platform and priority. These are defined by ourselves and might be changed depending on your needs.
For this project we have the following events that will trigger a notification:
- Twitter
- If someone tweets about a flood happening with the hashtag #sorocaba
- If more than 5 tweets are detected about a tremor
- Sensors
- If a tremor bigger than 100 happens
- If there is a decrease in luminosity and increase in temperature 5 times in a row.
- If the button is pushed
Step 1: Getting Started With the Cloud
Create a Bluemix account: https://console.bluemix.net/registration
Step 2: Setting Up Your Bluemix Account
Create a Watson IoT Platform Starter: https://console.bluemix.net/docs/starters/IoT/iot500.html#iot500
Step 3: Setting Up Your Internet of Things Plataforms
Register a Device: https://developer.ibm.com/recipes/tutorials/how-to...
Create an API Key and keep the authentication token for later
Step 4: Setting Up Your Node Red Starter Part 1
Menu -> Import -> Clipboard and paste the code below. It should look like the image above.
[ { "id": "c29fd6da.4ed9a", "type": "tab", "label": "Flow 1", "disabled": false, "info": "" }, { "id": "723d72a4.69c3f4", "type": "twitter-credentials", "z": "", "screen_name": "@2017_iot" }, { "id": "4bfabbbf.97ded4", "type": "ibmiot", "z": "", "name": "", "keepalive": "60", "serverName": "jxvoc1.messaging.internetofthings.ibmcloud.com", "cleansession": true, "appId": "", "shared": false }, { "id": "e9b3bb9.fdb6048", "type": "twitter in", "z": "c29fd6da.4ed9a", "twitter": "723d72a4.69c3f4", "tags": "#sorocaba enchente, #Sorocaba enchente, #sorocaba enchentes, #Sorocaba enchentes", "user": "false", "name": "Procura Enchentes", "topic": "tweets", "inputs": 1, "x": 110, "y": 120, "wires": [ [ "55806c88.0da75c" ] ] }, { "id": "ed854fc1.470218", "type": "e-mail", "z": "c29fd6da.4ed9a", "server": "smtp.gmail.com", "port": "465", "secure": true, "name": "", "dname": "envia notificação", "x": 1290, "y": 380, "wires": [] }, { "id": "55806c88.0da75c", "type": "function", "z": "c29fd6da.4ed9a", "name": "Envia notificação de enchente", "func": "msg.topic = \"Aviso de enchente em Sorocaba\";\nmsg.payload = \"Verificamos por um tweet que está ocorrendo enchentes em Sorocaba\\n De acordo com o Tweet:\\n\" + \"\\\"\" + msg.payload; + \"\\\"\"\n//msg.payload = \"Verificamos por um tweet que está ocorrendo enchentes em Sorocaba\"\nreturn msg;", "outputs": 1, "noerr": 0, "x": 1010, "y": 120, "wires": [ [ "ed854fc1.470218" ] ] }, { "id": "84beafeb.36d57", "type": "ibmiot in", "z": "c29fd6da.4ed9a", "authentication": "apiKey", "apiKey": "4bfabbbf.97ded4", "inputType": "evt", "deviceId": "", "applicationId": "", "deviceType": "", "eventType": "+", "commandType": "", "format": "json", "name": "IBM IoT", "service": "registered", "allDevices": true, "allApplications": "", "allDeviceTypes": true, "allEvents": true, "allCommands": "", "allFormats": "", "qos": 0, "x": 70, "y": 400, "wires": [ [ "4288622e.32e65c" ] ] }, { "id": "4288622e.32e65c", "type": "function", "z": "c29fd6da.4ed9a", "name": "Filter type of status", "func": "// If tilt is undefined than the status recieved is for another type\nif (typeof msg.payload.d.tilt != 'undefined') {\n msg.type = \"tilt\"\n} else if (typeof msg.payload.d.temperature != 'undefined') {\n msg.type = \"temperature\"\n} else if (typeof msg.payload.d.luminosity != 'undefined') {\n msg.type = \"luminosity\"\n} else if (typeof msg.payload.d.button != 'undefined') {\n msg.type = \"button\"\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "x": 280, "y": 400, "wires": [ [ "8631b9f5.53bd98" ] ] }, { "id": "8631b9f5.53bd98", "type": "switch", "z": "c29fd6da.4ed9a", "name": "Switch status", "property": "type", "propertyType": "msg", "rules": [ { "t": "eq", "v": "tilt", "vt": "str" }, { "t": "eq", "v": "temperature", "vt": "str" }, { "t": "eq", "v": "luminosity", "vt": "str" }, { "t": "eq", "v": "button", "vt": "str" } ], "checkall": "false", "outputs": 4, "x": 500, "y": 400, "wires": [ [ "96808843.c314d8" ], [ "d011bd30.2654b8" ], [ "9eca69f6.61f4c" ], [ "da29021f.c72c18" ] ] }, { "id": "6a7587bc.9a7c08", "type": "function", "z": "c29fd6da.4ed9a", "name": "Envia notificação", "func": "msg.topic = \"Aviso de terremoto em Sorocaba\";\nmsg.payload = \"Temos indícios de terremotos em Sorocaba! Detectado: \" + msg.payload.d.tilt + \" tremores/s\";\nreturn msg;", "outputs": 1, "noerr": 0, "x": 1030, "y": 380, "wires": [ [ "ed854fc1.470218" ] ] }, { "id": "96808843.c314d8", "type": "switch", "z": "c29fd6da.4ed9a", "name": "Envia notificacao se tremores > 100", "property": "payload.d.tilt", "propertyType": "msg", "rules": [ { "t": "gt", "v": "100", "vt": "num" } ], "checkall": "true", "outputs": 1, "x": 760, "y": 380, "wires": [ [ "6a7587bc.9a7c08" ] ] }, { "id": "9eca69f6.61f4c", "type": "function", "z": "c29fd6da.4ed9a", "name": "Verifica iluminosidade", "func": "var ilum = context.get('ilum')||0;\nvar ilumCount = context.get('ilumCount')||0;\n\nif(ilum > msg.payload.d.luminosity) {\n ilumCount++;\n if (ilumCount >= 4) {\n global.set(\"avisoIlum\", true);\n ilumCount = 0;\n }\n context.set('ilumCount',ilumCount);\n context.set('ilum',msg.payload.d.luminosity);\n} else {\n ilumCount = 0;\n context.set('ilumCount',ilumCount);\n context.set('ilum',msg.payload.d.luminosity);\n global.set(\"avisoIlum\",false);\n \n}\nreturn msg;", "outputs": 1, "noerr": 0, "x": 720, "y": 460, "wires": [ [ "5213b33f.648074" ] ] }, { "id": "d011bd30.2654b8", "type": "function", "z": "c29fd6da.4ed9a", "name": "Verifica temperatura", "func": "var temp = context.get('temp')||0;\nvar tempCount = context.get('tempCount')||0;\n\nif(temp < msg.payload.d.temperature) {\n tempCount++;\n if (tempCount >= 5) {\n global.set(\"avisoTemp\", true);\n tempCount = 0;\n }\n context.set('tempCount',tempCount);\n context.set('temp', msg.payload.d.temperature);\n} else {\n tempCount = 0;\n context.set('tempCount',tempCount);\n context.set('temp', msg.payload.d.temperature);\n global.set(\"avisoTemp\",false);\n}\nreturn msg;", "outputs": 1, "noerr": 0, "x": 720, "y": 420, "wires": [ [ "5213b33f.648074" ] ] }, { "id": "5213b33f.648074", "type": "function", "z": "c29fd6da.4ed9a", "name": "Envia notificação", "func": "var avTemp = global.get(\"avisoTemp\"); \nvar avIlum = global.get(\"avisoIlum\");\n\nif (avTemp === true && avIlum === true){\n global.set(\"avisoTemp\",false);\n global.set(\"avisoIlum\",false);\n msg.topic = \"Aviso de tempestade em Sorocaba\";\n msg.payload = \"Temos indícios que possa ocorrer uma tempestade em Sorocaba nas próximas horas!\";\n return msg;\n}", "outputs": 1, "noerr": 0, "x": 1030, "y": 440, "wires": [ [ "ed854fc1.470218" ] ] }, { "id": "961c6f34.f6448", "type": "twitter in", "z": "c29fd6da.4ed9a", "twitter": "723d72a4.69c3f4", "tags": "#sorocaba terremoto, #Sorocaba terremoto, #sorocaba terremotos, #Sorocaba terremotos", "user": "false", "name": "Procura terremotos", "topic": "tweets", "inputs": 1, "x": 110, "y": 260, "wires": [ [ "994ec250.c47348" ] ] }, { "id": "994ec250.c47348", "type": "function", "z": "c29fd6da.4ed9a", "name": "conta twitter", "func": "var count = context.get('count')||0;\ncount += 1;\nif (count >= 5){\n count = 0;\n context.set('count',count);\n return true;\n}\ncontext.set('count',count);\nreturn false;", "outputs": 1, "noerr": 0, "x": 550, "y": 260, "wires": [ [ "2040656d.2d36b2" ] ] }, { "id": "9f70322.e842ad", "type": "function", "z": "c29fd6da.4ed9a", "name": "Envia notificação terremotos", "func": "msg.topic = \"Aviso de enchente em Sorocaba\";\nmsg.payload = \"Verificamos por um tweet que está ocorrendo terremoto em Sorocaba\\n De acordo com os tweets dos usuários\";\nreturn msg;", "outputs": 1, "noerr": 0, "x": 1020, "y": 260, "wires": [ [ "ed854fc1.470218" ] ] }, { "id": "2040656d.2d36b2", "type": "switch", "z": "c29fd6da.4ed9a", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "true" } ], "checkall": "true", "outputs": 1, "x": 790, "y": 260, "wires": [ [ "9f70322.e842ad" ] ] }, { "id": "da29021f.c72c18", "type": "function", "z": "c29fd6da.4ed9a", "name": "Envia notificação", "func": "msg.topic = \"Aviso do botão de pânico\";\nmsg.payload = \"O botão de pânico foi precionado!\\n\";\nreturn msg;", "outputs": 1, "noerr": 0, "x": 710, "y": 520, "wires": [ [ "68be3f36.d9a0b8" ] ] }, { "id": "68be3f36.d9a0b8", "type": "delay", "z": "c29fd6da.4ed9a", "name": "", "pauseType": "rate", "timeout": "15", "timeoutUnits": "seconds", "rate": "1", "nbRateUnits": "30", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": true, "x": 1020, "y": 520, "wires": [ [ "ed854fc1.470218" ] ] } ]
Step 5: Setting Up Your Node Red Starter Part 2
Due to privacy reasons we had to remove some information that were contained on some nodes.
It will be necessary to configure and set up your API Key on the "ibmiot node".
Set a twitter account on "twitter-credentials" and set a email account on the "e-mail node".
Step 6: Getting Started With Dragonboard 410c
Follow this setup guide: https://pythonhosted.org/libsoc_zero/setup.html
Run the following code:
pip3 install spidev pip3 install libsoc pip3 install paho-mqtt
Step 7: Connecting the Sensors
For this instructions the sensors have to bee connected on specific pins.
- Linker Temperature -> ADC2
- Light Sensor -> ADC1
- Linker Tilt -> D1
- Touch Sensor -> D2
Step 8: Creating Send.py
Create a file called: send.py and paste the following code in it:
import paho.mqtt.client as mqtt import ibmiotf.application import json #Set the variables for connecting to the iot service topic = "iot-2/evt/status/fmt/json" username = "use-token-auth" # Only change these informations below password = "" #auth-token organization = "" #org_id deviceType = "" deviceId = "" #Creating the client connection #Set clientID and broker clientID = "d:" + organization + ":" + deviceType + ":" + deviceId broker = organization + ".messaging.internetofthings.ibmcloud.com" mqttc = mqtt.Client(clientID) mqttc.loop_start() #Set authentication values, if connecting to registered service if username is not "": mqttc.username_pw_set(username, password=password) mqttc.connect(host=broker, port=1883, keepalive=60) def send_message(msg_type, msg): msg = json.JSONEncoder().encode({"d":{msg_type:msg}}) print("Debug:", msg) mqttc.publish(topic, payload=msg, qos=1, retain=False)
Step 9: Configuring Send.py
Configure send.py configuration by adding your Watson IoT credentials
password = Authentication token
organization = Organization name
deviceType = Device type
deviceId = Device ID
Step 10: Creating Sensors.py
Create a file called: sensors.py and paste the following code in it:
# -*- coding: utf-8 -*- import threading from spidev import SpiDev from time import sleep from libsoc import gpio from libsoc_zero.GPIO import Tilt, Input import send import sys spi = SpiDev() spi.open(0,0) spi.max_speed_hz=10000 spi.mode = 0b00 spi.bits_per_word = 8 tilt = Tilt('GPIO-A') botao = Input('GPIO-C') def detectaTilt(): count = 0 sleep_count = 0 while True: try: tilt.wait_for_tilt(1) except: sleep_count += 1 else: count += 1 sleep_count += 1 if sleep_count > 999: break print("count:", count) send.send_message("tilt", count) def detectaBotao(): if botao.is_pressed(): send.send_message("button", 1) def detectaTemperatura(gpio_cs): gpio_cs.set_high() sleep(0.00002) gpio_cs.set_low() rx = spi.xfer([0x01, 0xA0, 0x00]) #ADC2 gpio_cs.set_high() adc_value = (rx[1] << 8) & 0b1100000000 adc_value = adc_value | (rx[2] & 0xff) #Realiza a conversao para celsius adc_value = (adc_value * 5.0/1023-0.5) * 100 print("Temperatura: %.1f C" % adc_value) send.send_message("temperature", adc_value) def detectaLuminosidade(gpio_cs): gpio_cs.set_high() sleep(0.00002) gpio_cs.set_low() rx = spi.xfer([0x01, 0x80, 0x00]) #ADC1 gpio_cs.set_high() adc_value = (rx[1] << 8) & 0b1100000000 adc_value = adc_value | (rx[2] & 0xff) print("Luminosidade: %d" % adc_value) send.send_message("luminosity", adc_value) if __name__=='__main__': threading.Thread(target=detectaTilt).start() gpio_cs = gpio.GPIO(18, gpio.DIRECTION_OUTPUT) with gpio.request_gpios([gpio_cs]): while True: detectaTemperatura(gpio_cs) detectaLuminosidade(gpio_cs) detectaBotao() detectaTilt() # Demora 1 seg para executar sleep(1)
Step 11: Run Sensors.py
That's it! Just run sensors.py with the following command and you're done.
sudo python3 sensors.py