Skip to content

Commit

Permalink
Merge pull request #22 from intelligent-environments-lab/revision
Browse files Browse the repository at this point in the history
software update
  • Loading branch information
HagenFritz authored Apr 2, 2021
2 parents 2c7021b + f8bb5af commit 3bb18ed
Show file tree
Hide file tree
Showing 10 changed files with 669 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
*.mp4
*.pptx
*.ppt
.vscode/
16 changes: 16 additions & 0 deletions Setup/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pandas
numpy

# Python Sensor Libraries
adafruit-circuitpython-tsl2591
adafruit-circuitpython-tsl2561
adafruit-circuitpython-sgp30
adafruit-circuitpython-pcf8523
crcmod
pyserial

# AWS Libraries
# boto3

#I2C tools
smbus
73 changes: 73 additions & 0 deletions bevobeacon-iaq/adafruit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Adafruit Sensors
This script handles data measurements from the Adafruit SGP30 and TSL2591 sensors.
"""
import asyncio
import time
import numpy as np

# Raspberry PI board libraries
from board import SCL, SDA
from busio import I2C

# Sensor libraries
import adafruit_sgp30
import adafruit_tsl2591


class SGP30:
""" Located within SVM30"""

def __init__(self) -> None:
i2c = I2C(SCL, SDA)
sgp30 = adafruit_sgp30.Adafruit_SGP30(i2c)
sgp30.iaq_init()
self.sgp30 = sgp30

async def scan(self):
try:
eCO2, TVOC = self.sgp30.iaq_measure()
except:
eCO2 = np.nan
TVOC = np.nan

data = {"TVOC": TVOC, "eCO2": eCO2}
return data


class TSL2591:
def __init__(self) -> None:
i2c = I2C(SCL, SDA)
tsl = adafruit_tsl2591.TSL2591(i2c)

# set gain and integration time; gain 0 = 1x & 1 = 16x. Integration time of 1 = 101ms
tsl.gain = 0
tsl.integration_time = 1 # 101 ms intergration time.

self.tsl = tsl

def enable(self):
self.tsl.enabled = True

def disable(self):
self.tsl.enabled = False

async def scan(self):
try:
tsl = self.tsl

# Retrieve sensor scan data
lux = tsl.lux
visible = tsl.visible
infrared = tsl.infrared

# Check for complete darkness
if lux == None:
lux = 0
except:
lux = np.nan
visible = np.nan
infrared = np.nan

data = {"Visible": visible, "Infrared": infrared, "Lux": lux}
return data
28 changes: 28 additions & 0 deletions bevobeacon-iaq/bevo_iaq_setup_dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

# Update package list
sudo apt-get update
sudo apt-get upgrade

# Additional apt packages
sudo apt-get install python3 -y
sudo apt-get install python3-pip -y
sudo apt-get install python3-venv -y
sudo apt-get install -y i2c-tools
sudo apt-get install libatlas-base-dev #for numpy

# Virtual Environment Setup
rm -rf ~/bevo_iaq/.venv
mkdir ~/bevo_iaq/.venv
python3 -m venv ~/bevo_iaq/.venv
source ~/bevo_iaq/.venv/bin/activate

# Install addtional packages
pip install -r Setup/requirements.txt

# Github Credentials
git config --global user.email "hagenfritz@utexas.edu"
git config --global user.name "hagenfritz"

# Set up locale, timezone, language
sudo timedatectl set-timezone US/Central
12 changes: 12 additions & 0 deletions bevobeacon-iaq/bevodev.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=Script for testing
After=bluetooth.target

[Service]
EnvironmentFile=/etc/environment
ExecStart = /home/pi/bevo_iaq/.venv/bin/python3 -E /home/pi/bevo_iaq/Setup/Code/bevo_iaq_dev.py
Restart=always
RestartSec=60s

[Install]
WantedBy=bluetooth.target
154 changes: 154 additions & 0 deletions bevobeacon-iaq/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
"""BevoBeacon-IAQ Main Script
This script serves as the entry point for the BevoBeacon sensor data measurement
program. It can be launched from the terminal and runs in a loop until terminated
by the user.
Intelligent Environments Laboratory (IEL), The University of Texas at Austin
Author: Calvin J Lin
Project: Indoor Environmental Quality and Sleep Quality
- Contact: Hagen Fritz (hagenfritz@utexas.edu)
"""
import os
import sys
import logging
import time
import datetime
import asyncio

import pandas as pd

from adafruit import SGP30, TSL2591
from sensirion import SPS30, SCD30
from spec_dgs import DGS_NO2, DGS_CO


async def main(beacon="00"):
sensor_classes = {
"sgp": SGP30,
"tsl": TSL2591,
"sps": SPS30,
"scd": SCD30,
"dgs_co": DGS_CO,
"dgs_no2": DGS_NO2,
}

sensors = {}

# Only use sensors that are available
for name, sens in sensor_classes.items():
try:
sensor = sens()
sensors.update({name: sensor})
except:
pass

# These sensors are turn on and off after each scan cycle to save power
manually_enabled_sensors = list(set(sensors) & set(["tsl", "sps", "scd"]))

time.sleep(1) # Wait for all sensors to be initialized

log.info(f"Successfully created: {sensors}")
log.info("Attempting scans")

starttime = time.time() # Used for preventing time drift
while True:
start_time = time.time() # Used for evaluating scan cycle time performance

# Turn on all sensors before starting scans
for manual_sensor in manually_enabled_sensors:
try:
sensors[manual_sensor].enable()
except:
pass

# Wait for sensors to come online
time.sleep(0.1)

data = {}

async def scan(name):
"""Scans each sensor five times and returns the median"""
df = pd.DataFrame(
[
await sensors[name].scan(),
await sensors[name].scan(),
await sensors[name].scan(),
await sensors[name].scan(),
await sensors[name].scan(),
]
)
log.info("\nScan results for " + name)
log.info(df)
data[name] = df.median()
log.info(data[name])

# Perform all scans
await asyncio.gather(*[scan(name) for name in sensors])

# Disable sensors until next measurement interval
for manual_sensor in manually_enabled_sensors:
try:
sensors[manual_sensor].disable()
except:
pass

# Combine all data from this cycle into one DataFrame
date = datetime.datetime.now()
timestamp = pd.Series({"Timestamp": date.strftime("%Y-%m-%d %H:%M:%S")})
df = pd.concat([timestamp, *data.values()]).to_frame().T.set_index("Timestamp")
df = df.rename(
columns={
"TC": "Temperature [C]",
"RH": "Relative Humidity",
"pm_n_0p5": "PM_N_0p5",
"pm_n_1": "PM_N_1",
"pm_n_2p5": "PM_N_2p5",
"pm_n_4": "PM_N_4",
"pm_n_10": "PM_N_10",
"pm_c_1": "PM_C_1",
"pm_c_2p5": "PM_C_2p5",
"pm_c_4": "PM_C_4",
"pm_c_10": "PM_C_10",
}
)
log.info(df)

# Write data to csv file
filename = f'/home/pi/DATA/b{beacon}_{date.strftime("%Y-%m-%d")}.csv'
try:
if os.path.isfile(filename):
df.to_csv(filename, mode="a", header=False)
log.info(f"Data appended to {filename}")
else:
df.to_csv(filename)
log.info(f"Data written to {filename}")
except:
pass

# Report cycle time for performance evaluation by user
elapsed_time = time.time() - start_time
log.info(f"{elapsed_time} \n\n")

# Make sure that interval between scans is exactly 60 seconds
time.sleep(60.0 - ((time.time() - starttime) % 60.0))


def setup_logger(level=logging.WARNING):

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
log.propagate = False
if log.hasHandlers():
log.handlers.clear()
sh = logging.StreamHandler(stream=sys.stdout)
sh.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(message)s")
sh.setFormatter(formatter)
log.addHandler(sh)
return log


if __name__ == "__main__":
log = setup_logger(logging.INFO)
asyncio.run(main(beacon="test"))
Loading

0 comments on commit 3bb18ed

Please sign in to comment.