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
    1. Light Sensor
    2. Linker Temperature
    3. Linker Tilt
    4. 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

Step 12: References