-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from intelligent-environments-lab/revision
software update
- Loading branch information
Showing
10 changed files
with
669 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ | |
*.mp4 | ||
*.pptx | ||
*.ppt | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")) |
Oops, something went wrong.