2015년 8월 10일 월요일

[7th Week] Stream Applications for Sensor Data

Last week, I made a code that reads data from 2 Arduino synchronously, and send them to other device with bluetooth.
I modified the code that could read asynchronous data with making separate condition for each sensor. Next step could be making streams with sensor data. Python package PStreams would help this work. It was provided from my mentor.

Here's python code running on Raspberry Pi.

#Sample Code For Reading Data From Arduino, Sending via Bluetooth
#Get several string lines from sensors every 1 sampling
if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )

import sys
import serial # From Arduino
from Stream import Stream # From PStreams
# asynch_element_func operates asynchronously
# on messages that appear in any of its input
# streams in the order in which they arrive.
from Asynch import asynch_element_func
from example_window_single_in_single_out_stateful import subtract_mean
from example_window_single_in_single_out_stateful import exceeds_k_sigma
from PrintingFunctions import print_stream, print_list_of_streams

# Two Arduinos connected to Raspberry Pi
# Arduino 0 has temperature and humidity
port0 = "/dev/ttyACM0" #DHT11(temperature,humidity)
# Arduini 1 has acceleration, gyro, and temperature
port1 = "/dev/ttyACM1" #MPU6050(acc(x,y,z),gyro(x,y,z),temperature)
portout = "/dev/ttyAMA0" #For Bluetooth Output

serialFromArduino0 = serial.Serial(port0, 115200)
serialFromArduino0.flushInput() #DHT11

serialFromArduino1 = serial.Serial(port1, 115200)
serialFromArduino1.flushInput() #MPU6050

serialToMATLAB = serial.Serial(portout, 9600)
serialToMATLAB.flushInput()
serialToMATLAB.flushOutput() #Bluetooth


def getSensorData0(temp1, temp2): #DHT11
    print('*DHT11*')
    input1 = serialFromArduino0.readline()
    input2 = serialFromArduino0.readline()
    r_tem = input1.split()
    r_hum = input2.split()

    if(input1.find('temperature') != -1 and input2.find('humidity') != -1
       and len(r_tem) == 2 and len(r_hum) == 2):

        tem = r_tem[1]
        hum = r_hum[1]
        return(tem, hum)

    else:
        return(temp1, temp2)

def getSensorData1(temp1, temp2, temp3, temp4, temp5, temp6, temp7): #MPU6050
    r_accel = serialFromArduino1.readline()
    r_temp = serialFromArduino1.readline()
    r_gyro = serialFromArduino1.readline()
    accel = r_accel.split()
    temp = r_temp.split()
    gyro = r_gyro.split()

    if(r_accel.find('accel') != -1 and r_temp.find('temperature') != -1 and r_gyro.find('gyro') != -1 and len(accel) == 5 and len(temp) == 4 and len(gyro) ==5 ):

        acc_x, acc_y, acc_z = accel[2:5]
        temp = temp[1]
        gyro_x, gyro_y, gyro_z = gyro[2:5]

        return(acc_x,acc_y,acc_z,temp,gyro_x,gyro_y,gyro_z)

    else:
        return(temp1,temp2,temp3,temp4,temp5,temp6,temp7)

    
def condition(state):
    """ Condition on temperature and humidity
    """
    temperature, humidity = state
    return ((temperature > 24 and humidity > 45) or
            (temperature > 25 and humidity > 40))


def update_state_and_output_condition(
        value, stream_number, state):
    """ Function that updates the state when a new
    value appears on the stream specified by
    stream_number. The function then returns the
    condition on the new state.

    """
    # update the state
    state[stream_number] = value
    return (condition(state), state)


def main():
    print('starting...')

    temperature_stream = Stream('temperature')
    humidity_stream = Stream('humidity')
    acc_x_stream = Stream('acceleration_x')
    acc_y_stream = Stream('acceleration_y')
    acc_z_stream = Stream('acceleration_z')

    normed_x_stream = subtract_mean(acc_x_stream, window_size=100)
    normed_y_stream = subtract_mean(acc_y_stream, window_size=100)
    normed_z_stream = subtract_mean(acc_z_stream, window_size=100)

    alerts_x = exceeds_k_sigma(acc_x_stream, window_size=100)
    alerts_y = exceeds_k_sigma(acc_y_stream, window_size=100)
    alerts_z = exceeds_k_sigma(acc_z_stream, window_size=100)

    discomfort_stream = asynch_element_func(
        f=update_state_and_output_condition,
        inputs = [temperature_stream,humidity_stream],
        num_outputs=1,
        state=[0,0])

    normed_x_stream.set_name('accln_x_mean_removed')
    normed_y_stream.set_name('accln_y_mean_removed')
    normed_z_stream.set_name('accln_z_mean_removed')

    alerts_x.set_name('Alert_x')
    alerts_y.set_name('Alert_y')
    alerts_z.set_name('Alert_z')
    
    discomfort_stream.set_name('discomfort_stream')

    print_list_of_streams([
        temperature_stream, humidity_stream,
        acc_x_stream, acc_y_stream, acc_z_stream,
        normed_x_stream, normed_y_stream, normed_z_stream,
        alerts_x, alerts_y, alerts_z,
discomfort_stream])

    d1, d2 = '0','0'
    m1, m2, m3, m4, m5, m6, m7 = '0','0','0','0','0','0','0'

    # The main loop. Reading sensors from two Arduinos.
    while True:
        if serialFromArduino0.inWaiting() > 0  or serialFromArduino1.inWaiting() > 0:
            if serialFromArduino1.inWaiting() > 0:
                if (serialFromArduino1.readline().find('*') != -1):
                    acc_x,acc_y,acc_z,temp,gyro_x,gyro_y,gyro_z = getSensorData1(m1, m2, m3, m4, m5, m6, m7)
                    m1, m2, m3, m4, m5, m6, m7 = acc_x, acc_y, acc_z, temp, gyro_x, gyro_y, gyro_z
                    print 'sensor data 1',acc_x,acc_y,acc_z,temp,gyro_x,gyro_y,gyro_z
                    acc_x_stream.append(int(acc_x))
                    acc_y_stream.append(int(acc_y))
                    acc_z_stream.append(int(acc_z))
                    if alerts_x.stop > 0:
                        alertx = alerts_x.recent[:alerts_x.stop][alerts_x.stop-1]
                        alerty = alerts_y.recent[:alerts_y.stop][alerts_y.stop-1]
                        alertz = alerts_z.recent[:alerts_z.stop][alerts_z.stop-1]
                        serialToMATLAB.write('*\n' + acc_x + '\n' + acc_y + '\n' + acc_z + '\n' + str(alertx) + '\n' + str(alerty) + '\n' + str(alertz) + '\n')
                    else:
                        serialToMATLAB.write('*\n' + acc_x + '\n' + acc_y + '\n' + acc_z + '\n' + '0' + '\n' + '0' + '\n' + '0' + '\n')

            if serialFromArduino0.inWaiting() > 0:
                if serialFromArduino0.readline().find('*') != -1:
                    tem, hum = getSensorData0(d1, d2)
                    d1, d2 = tem, hum
                    print 'sensor data 0', tem, hum
                    temperature_stream.append(float(tem))
                    humidity_stream.append(float(hum))
                    temperature_stream.print_recent()
                    humidity_stream.print_recent()

if __name__ == '__main__':
    main()

This can generate streams for temperature, humidity, and acceleration (x,y,z). Also, I added some additional lines for stable running. Some error occurs when the program can't read the data string from Arduino properly, so some exception is added for that.


Additionally, after generating streams for data, it could generate alerts for unusual conditions.
For example, uncomfortable conditions can be set for temperature and humidity, and alert comes when the current data violates this.
For acceleration, it can gather some data for a while, and calculate some statistical things. When the sigma of current data exceeds the threshold, it generates alerts.
Here's sample of printed data. Upper one is about DHT11, and the other is 2 sample of MPU6050.

Also, we can apply it with bluetooth connection. I captured the acceleration stream and alert stream with MATLAB.
Upper one is Acceleration (x,y,z) and below graphs are alerts. We can see the alert generated when I shake the sensor.


댓글 없음:

댓글 쓰기