Compare commits
27 Commits
master-slo
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dc9fecff6 | ||
|
|
57d10a5ae5
|
||
|
|
2cc0fd977b | ||
|
|
3d3254c4a7 | ||
|
|
cfe6e3c286 | ||
|
|
7a3877b34b | ||
|
|
f20dd30292 | ||
|
|
ef5c87d8d2 | ||
|
|
4878df9ca8 | ||
|
|
89ea9564c8 | ||
|
|
00c619ce34 | ||
|
|
8f22a6baee | ||
|
|
fa2c1cccb1 | ||
|
|
7058512ee0 | ||
|
|
325f1176c3 | ||
|
|
0a9e610dd7 | ||
|
|
43b5277923 | ||
|
|
5265ba9ae9 | ||
|
|
16e9c52194 | ||
|
|
c5db357cc0 | ||
|
|
b7eb29f78b | ||
|
|
1457655f16 | ||
|
|
a3f3558f7c | ||
|
|
bc72207187 | ||
|
|
7837f605cf | ||
|
|
3d1a925ba6 | ||
|
|
682fe20db2 |
BIN
..gitignore.swp
BIN
..gitignore.swp
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
[](https://terahz.readthedocs.io/en/latest/?badge=latest)
|
||||
# <img alt="TeraHz logo" src="docs/imgs/logo-sq.png" width="200px"> TeraHz
|
||||
|
||||
*This project is currently at a standstill because SparkFUN stopped making one of the board this project needs. TeraHz will return in a better form some day!*
|
||||
*Za slovensko različico se odpravite na <http://git.sckr-lab.tk/kristjank/TeraHz>*
|
||||
|
||||
TeraHz is a low-cost portable spectrometer based on Raspberry Pi and a few
|
||||
@@ -32,3 +32,6 @@ More documentation is available at <https://terahz.readthedocs.io>
|
||||
- Kristjan Komloši (cls-02) - Project leader and main programmer
|
||||
- Jakob Kosec (D3m1j4ck) - Frontend designer
|
||||
- Juš Dolžan (ANormalPerson) - Math double-checker
|
||||
|
||||
<img alt="TeraHz logo" src="http://www.sckr.si/documents/upload/konektor/logo/_SC.gif" width="200px">
|
||||
TeraHz has been developed under guidance and financial support of Šolski Center Kranj (Kranj School Centre). Without their support, this project might have never been possible.
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
# app.py - main backend program
|
||||
'''Main TeraHz backend program'''
|
||||
# All code in this file is licensed under the ISC license, provided in LICENSE.txt
|
||||
from flask import Flask
|
||||
import flask
|
||||
from flask import Flask, jsonify
|
||||
import sensors
|
||||
|
||||
app = Flask(__name__)
|
||||
@app.route('/data')
|
||||
def sendData():
|
||||
'''Responder function for /data route'''
|
||||
s = sensors.Spectrometer(path='/dev/serial0', baudrate=115200, tout=1)
|
||||
s = sensors.Spectrometer(path='/dev/serial0')
|
||||
u = sensors.UVSensor()
|
||||
l = sensors.LxMeter()
|
||||
response = flask.jsonify([s.getData(), l.getData(), u.getABI()])
|
||||
response = jsonify([s.getData(), l.getData(), u.getABI()])
|
||||
response.headers.add('Access-Control-Allow-Origin', '*')
|
||||
return response
|
||||
|
||||
Binary file not shown.
@@ -6,8 +6,13 @@ import serial as ser
|
||||
import pandas as pd
|
||||
import smbus2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Spectrometer:
|
||||
'''Class representing the AS7265X specrometer'''
|
||||
|
||||
def initializeSensor(self):
|
||||
'''confirm the sensor is responding and proceed\
|
||||
with spectrometer initialization'''
|
||||
@@ -23,8 +28,7 @@ class Spectrometer:
|
||||
if rstring == 'ERROR':
|
||||
raise Exception # sensor is in error state
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception ocurred when performing spectrometer handshake')
|
||||
raise Exception('No AT command response')
|
||||
|
||||
def setParameters(self, parameters):
|
||||
'''applies the parameters like LED light and gain to the spectrometer'''
|
||||
@@ -53,8 +57,7 @@ class Spectrometer:
|
||||
self.serialObject.write('ATLED3={}\n'.format(led).encode())
|
||||
self.serialObject.readline()
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured during spectrometer initialization')
|
||||
raise Exception('Error setting spectrometer parameters')
|
||||
|
||||
def getData(self):
|
||||
'''Returns spectral data in a pandas DataFrame.'''
|
||||
@@ -62,11 +65,10 @@ class Spectrometer:
|
||||
self.serialObject.write(b'ATCDATA\n')
|
||||
rawresp = self.serialObject.readline().decode()
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occurred when polling for spectrometer data')
|
||||
raise Exception('Error polling spectrometer data')
|
||||
else:
|
||||
responseorder = [i for i in 'RSTUVWGHIJKLABCDEF']
|
||||
realorder = [i for i in 'ABCDEFGHRISJTUVWKL']
|
||||
responseorder = list('RSTUVWGHIJKLABCDEF')
|
||||
realorder = list('ABCDEFGHRISJTUVWKL')
|
||||
response = pd.Series(
|
||||
[float(i) / 35.0 for i in rawresp[:-3].split(',')], index=responseorder)
|
||||
return pd.DataFrame(response, index=realorder, columns=['uW/cm^2']).to_dict()['uW/cm^2']
|
||||
@@ -78,14 +80,14 @@ class Spectrometer:
|
||||
try:
|
||||
self.serialObject = ser.Serial(path, baudrate, timeout=tout)
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured when opening the serial port at {}'.format(path))
|
||||
raise Exception('Error opening serial port: {}'.format(path))
|
||||
else:
|
||||
self.initializeSensor()
|
||||
|
||||
|
||||
class LxMeter:
|
||||
'''Class representing the APDS-9301 digital photometer.'''
|
||||
|
||||
def __init__(self, busNumber=1, addr=0x39):
|
||||
self.addr = addr
|
||||
try:
|
||||
@@ -93,14 +95,14 @@ class LxMeter:
|
||||
self.bus = smbus2.SMBus(busNumber)
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured opening the SMBus {}'.format(self.bus))
|
||||
'Error opening SMBus {}'.format(self.bus))
|
||||
|
||||
try:
|
||||
self.bus.write_byte_data(
|
||||
self.addr, 0xa0, 0x03) # enable the sensor
|
||||
self.setGain(16)
|
||||
except:
|
||||
raise Exception('An exception occured when enabling lux meter')
|
||||
raise Exception('Error enabling lux meter')
|
||||
|
||||
def setGain(self, gain):
|
||||
'''Set the sensor gain. Either 1 or 16.'''
|
||||
@@ -109,15 +111,13 @@ class LxMeter:
|
||||
temp = self.bus.read_byte_data(self.addr, 0xa1)
|
||||
self.bus.write_byte_data(self.addr, 0xa1, 0xef & temp)
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured when setting lux meter gain')
|
||||
raise Exception('Error setting lux meter gain')
|
||||
if gain == 16:
|
||||
try:
|
||||
temp = self.bus.read_byte_data(self.addr, 0xa1)
|
||||
self.bus.write_byte_data(self.addr, 0xa1, 0x10 | temp)
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured when setting lux meter gain')
|
||||
raise Exception('Error setting lux meter gain')
|
||||
else:
|
||||
raise Exception('Invalid gain')
|
||||
|
||||
@@ -160,7 +160,7 @@ class LxMeter:
|
||||
except:
|
||||
raise Exception('An exception occured fetching lux channels')
|
||||
|
||||
# scary computations ahead! refer to the apds-9301 datasheet!
|
||||
# Refer to APDS-9301 datasheet!
|
||||
if chB / chA <= 0.5 and chB / chA > 0:
|
||||
lux = 0.0304 * chA - 0.062 * chA * (chB / chA)**1.4
|
||||
elif chB / chA <= 0.61 and chB / chA > 0.5:
|
||||
@@ -176,6 +176,7 @@ class LxMeter:
|
||||
|
||||
class UVSensor:
|
||||
'''Class representing VEML6075 UVA/B meter'''
|
||||
|
||||
def __init__(self, bus=1, addr=0x10):
|
||||
self.addr = addr
|
||||
try:
|
||||
@@ -187,9 +188,16 @@ class UVSensor:
|
||||
try:
|
||||
# enable the sensor and set the integration time
|
||||
self.bus.write_byte_data(self.addr, 0x00, 0b00010000)
|
||||
|
||||
# trigger a measurement to prevent bus errors at first read
|
||||
self.bus.write_byte_data(self.addr, 0x00, 0b00010010) # UV_AF=1
|
||||
self.bus.write_byte_data(self.addr, 0x00, 0b00010110) # UV_TRIG=1
|
||||
self.bus.write_byte_data(
|
||||
self.addr, 0x00, 0b00010000) # normal mode
|
||||
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured when initalizing the UV Sensor')
|
||||
'Error initalizing the UV Sensor')
|
||||
|
||||
def getABI(self):
|
||||
'''Calculates the UVA and UVB irradiances,
|
||||
@@ -202,40 +210,16 @@ class UVSensor:
|
||||
c1 = self.bus.read_word_data(self.addr, 0x0a)
|
||||
c2 = self.bus.read_word_data(self.addr, 0x0b)
|
||||
except:
|
||||
raise Exception('An exception occured when fetching raw UV data')
|
||||
# scary computations ahead! refer to Vishay app note 84339 and Sparkfun
|
||||
# VEML6075 documentation.
|
||||
|
||||
# compensate for visible and IR noise
|
||||
aCorr = aRaw - 2.22 * c1 - 1.33 * c2
|
||||
bCorr = bRaw - 2.95 * c1 - 1.74 * c2
|
||||
|
||||
# convert values into irradiances
|
||||
a = aCorr * 1.06
|
||||
b = bCorr * 0.48
|
||||
|
||||
# zero out negative results (readings with no uv)
|
||||
if a < 0:
|
||||
a = 0
|
||||
if b < 0:
|
||||
b = 0
|
||||
# last, calculate the UV index
|
||||
i = (a + b) / 2
|
||||
raise Exception('Error fetching raw UV data')
|
||||
# Refer to Vishay app note 84339 and Sparkfun VEML6075 documentation.
|
||||
# The computed values may be negative if UV is vastly weaker than
|
||||
# visible and IR light. This is not a bug!
|
||||
|
||||
a = (aRaw - 2.22 * c1 - 1.33 * c2) * 1.06
|
||||
b = (bRaw - 2.95 * c1 - 1.74 * c2) * 0.48
|
||||
i = (a + b) / 2 # calculate UV index
|
||||
return [a, b, i]
|
||||
|
||||
def getA(self):
|
||||
'''Returns UVA value. A getABI() wrapper.'''
|
||||
return self.getABI()[0]
|
||||
|
||||
def getB(self):
|
||||
'''Returns UVB value. A getABI() wrapper.'''
|
||||
return self.getABI()[1]
|
||||
|
||||
def getI(self):
|
||||
'''Returns UV index. A getABI() wrapper.'''
|
||||
return self.getABI()[2]
|
||||
|
||||
def on(self):
|
||||
'''Turns the UV sensor on after shutdown.'''
|
||||
try:
|
||||
@@ -244,7 +228,7 @@ class UVSensor:
|
||||
self.bus.write_byte_data(self.addr, 0x00, 0x10)
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured when turning the UV sensor on')
|
||||
'Error turning the UV sensor on')
|
||||
|
||||
def off(self):
|
||||
'''Shuts the UV sensor down.'''
|
||||
@@ -254,4 +238,4 @@ class UVSensor:
|
||||
self.bus.write_byte_data(self.addr, 0x00, 0x11)
|
||||
except:
|
||||
raise Exception(
|
||||
'An exception occured when shutting the UV sensor down')
|
||||
'Error shutting the UV sensor down')
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# storage.py - storage backend for TeraHz
|
||||
'''TeraHz storage backend'''
|
||||
# Copyright Kristjan Komloši 2019
|
||||
# All code in this file is licensed under the ISC license,
|
||||
# provided in LICENSE.txt
|
||||
|
||||
|
||||
import sqlite3
|
||||
class jsonStorage:
|
||||
'''Class for simple sqlite3 database of JSON entries'''
|
||||
def __init__(self, dbFile):
|
||||
'''Storage object constructor. Argument is filename'''
|
||||
self.db = sqlite3.connect(dbFile)
|
||||
|
||||
def listJSONs(self):
|
||||
'''Returns a list of all existing entries.'''
|
||||
c = self.db.cursor()
|
||||
c.execute('SELECT * FROM storage')
|
||||
result = c.fetchall()
|
||||
c.close()
|
||||
return result
|
||||
|
||||
def storeJSON(self, jsonString, comment):
|
||||
'''Stores a JSON entry along with a timestamp and a comment.'''
|
||||
c = self.db.cursor()
|
||||
c.execute(('INSERT INTO storage VALUES (datetime'
|
||||
'(\'now\', \'localtime\'), ?, ?)'), (comment, jsonString))
|
||||
c.close()
|
||||
self.db.commit()
|
||||
|
||||
def retrieveJSON(self, timestamp):
|
||||
'''Retrieves a JSON entry. Takes a timestamp string'''
|
||||
c = self.db.cursor()
|
||||
c.execute('SELECT * FROM storage WHERE timestamp = ?', (timestamp,))
|
||||
result = c.fetchall()
|
||||
c.close()
|
||||
return result
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# Minimal flup configuration for Flask
|
||||
from flup.server.fcgi import WSGIServer
|
||||
from app import app
|
||||
|
||||
if __name__ == '__main__':
|
||||
WSGIServer(app, bindAddress='/var/www/api/terahz.sock').run()
|
||||
@@ -1,4 +1,4 @@
|
||||
# install.sh - install TeraHz onto a Raspbian or DietPi installation
|
||||
# install.sh - install TeraHz onto a Raspbian Lite instance
|
||||
cd `dirname $0`
|
||||
|
||||
apt -y update
|
||||
@@ -6,13 +6,16 @@ apt -y full-upgrade
|
||||
apt install -y python3 python3-pip lighttpd dnsmasq hostapd libatlas-base-dev
|
||||
pip3 install numpy pandas flask smbus2 pyserial gunicorn
|
||||
|
||||
cp -R hostapd/ /etc
|
||||
cp -R hostapd/* /etc/hostapd/
|
||||
chmod +rx /etc/hostapd/edit_ssid.sh
|
||||
cp dnsmasq.conf /etc
|
||||
cp rc.local /etc
|
||||
cp dnsmasq.conf /etc/
|
||||
|
||||
cp rc.local /etc/
|
||||
chmod +rx /etc/rc.local
|
||||
cp interfaces-terahz /etc/network/interfaces.d/
|
||||
|
||||
cp -R ../frontend/* /var/www/html
|
||||
cp -R ../frontend/* /var/www/html/
|
||||
|
||||
mkdir -p /usr/local/lib/terahz
|
||||
cp -R ../backend/* /usr/local/lib/terahz
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
server.modules = (
|
||||
"mod_access",
|
||||
"mod_alias",
|
||||
"mod_compress",
|
||||
"mod_redirect"
|
||||
)
|
||||
|
||||
server.document-root = "/var/www/html"
|
||||
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
||||
server.errorlog = "/var/log/lighttpd/error.log"
|
||||
server.pid-file = "/var/run/lighttpd.pid"
|
||||
server.username = "www-data"
|
||||
server.groupname = "www-data"
|
||||
server.port = 80
|
||||
|
||||
|
||||
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
||||
url.access-deny = ( "~", ".inc" )
|
||||
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
||||
|
||||
compress.cache-dir = "/var/cache/lighttpd/compress/"
|
||||
compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" )
|
||||
|
||||
# default listening port for IPv6 falls back to the IPv4 port
|
||||
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
|
||||
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
|
||||
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
|
||||
0
etcs/rc.local
Normal file → Executable file
0
etcs/rc.local
Normal file → Executable file
@@ -1,7 +1,5 @@
|
||||
// All code in this file is licensed under the ISC license, provided in LICENSE.txt
|
||||
$('#update').click(function () {
|
||||
updateData();
|
||||
});
|
||||
$('#update').click(updateData);
|
||||
// jQuery event binder
|
||||
|
||||
function updateData () {
|
||||
@@ -22,14 +20,14 @@ function graphSpectralData (obj, dom) {
|
||||
var graphPoints = [];
|
||||
var graphXTicks = [];
|
||||
|
||||
Object.keys(obj).forEach((element, index) => {
|
||||
graphPoints.push([index, obj[element]]); // build array of points
|
||||
graphXTicks.push([index, element]); // build array of axis labels
|
||||
});
|
||||
// console.log(graphPoints);
|
||||
const specter = 'ABCDEFGHRISJTUVWKL';
|
||||
for (var i = 0; i < specter.length; i++) {
|
||||
graphPoints.push([i, obj[specter[i]]]);
|
||||
graphXTicks.push([i, specter[i]]);
|
||||
}
|
||||
const options = {
|
||||
grid: {color: 'white'},
|
||||
xaxis: {ticks: graphXTicks}
|
||||
grid: { color: 'white' },
|
||||
xaxis: { ticks: graphXTicks }
|
||||
};
|
||||
$.plot('#graph', [graphPoints], options);
|
||||
// flot expects an array of arrays (lines) of 2-element arrays (points)
|
||||
|
||||
@@ -6,146 +6,6 @@
|
||||
<link rel="stylesheet" href="lib/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="stylesheet.css">
|
||||
<title>TeraHz</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container text-center">
|
||||
<h1><img src="lib/logo-sq.png" height="64px">TeraHz</h1>
|
||||
|
||||
</div>
|
||||
<div class="container">
|
||||
<button id="update" class="btn btn-primary m-1 float-right">Get data</button>
|
||||
<p id="debug">
|
||||
</p>
|
||||
<h3>Spectrogram</h3>
|
||||
<div id="graph" style="height:480px;width:720px"></div>
|
||||
<h3>Spectral readings</h3>
|
||||
<table class="table table-dark table-sm" id="specter">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Band</th>
|
||||
<th>Wavelength [nm]</th>
|
||||
<th>Irradiance [μW/cm²]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>A</td>
|
||||
<td>410 nm</td>
|
||||
<td id="A">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B</td>
|
||||
<td>435 nm</td>
|
||||
<td id="B">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C</td>
|
||||
<td>460 nm</td>
|
||||
<td id="C">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>D</td>
|
||||
<td>485 nm</td>
|
||||
<td id="D">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E</td>
|
||||
<td>510 nm</td>
|
||||
<td id="E">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>F</td>
|
||||
<td>535 nm</td>
|
||||
<td id="F">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>G</td>
|
||||
<td>560 nm</td>
|
||||
<td id="G">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>H</td>
|
||||
<td>585 nm</td>
|
||||
<td id="H">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>R</td>
|
||||
<td>610 nm</td>
|
||||
<td id="R">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>I</td>
|
||||
<td>645 nm</td>
|
||||
<td id="I">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S</td>
|
||||
<td>680 nm</td>
|
||||
<td id="S">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>J</td>
|
||||
<td>705 nm</td>
|
||||
<td id="J">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>T</td>
|
||||
<td>730 nm</td>
|
||||
<td id="T">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>U</td>
|
||||
<td>760 nm</td>
|
||||
<td id="U">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>V</td>
|
||||
<td>810 nm</td>
|
||||
<td id="V">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>W</td>
|
||||
<td>860 nm</td>
|
||||
<td id="W">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>K</td>
|
||||
<td>900 nm</td>
|
||||
<td id="K">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>L</td>
|
||||
<td>940 nm</td>
|
||||
<td id="L">---</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<h3>Lux and UV readings</h3>
|
||||
<table class="table-dark table" id="luxuv">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>Illuminance [lx]</td>
|
||||
<td id="lx">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UVA irradiance [μW/cm²]</td>
|
||||
<td id="uva">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UVB irradiance [μW/cm²]</td>
|
||||
<td id="uvb">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UVA/UVB average [μW/cm²]</td>
|
||||
<td id="uvi">---</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="lib/bootstrap.bundle.min.js"></script>
|
||||
<script src="lib/jquery-3.4.1.min.js"></script>
|
||||
<script src="lib/flot/jquery.flot.js"></script>
|
||||
@@ -157,6 +17,157 @@
|
||||
<script src="lib/flot/jquery.flot.browser.js"></script>
|
||||
<script src="lib/flot/jquery.flot.drawSeries.js"></script>
|
||||
<script src="lib/flot/jquery.flot.uiConstants.js"></script>
|
||||
</body>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container text-center">
|
||||
<h1><img src="lib/logo-sq.png" height="64px">TeraHz</h1>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<button id="update" onclick="updateData()" class="btn btn-primary">Get data</button>
|
||||
<!-- <button id="download" class="btn btn-primary">Download</button>
|
||||
<button id="debug" class="btn btn-danger">DEBUG</button> -->
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<h4>Spectrogram</h4>
|
||||
<div id="graph" style="height:480px;width:720px"></div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm">
|
||||
<h4>Visible+IR spectrum</h4>
|
||||
<table class="table table-dark table-sm" id="specter">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Band</th>
|
||||
<th>Wavelength [nm]</th>
|
||||
<th>Irradiance [μW/cm²]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>A</td>
|
||||
<td>410 nm</td>
|
||||
<td id="A">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B</td>
|
||||
<td>435 nm</td>
|
||||
<td id="B">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C</td>
|
||||
<td>460 nm</td>
|
||||
<td id="C">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>D</td>
|
||||
<td>485 nm</td>
|
||||
<td id="D">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E</td>
|
||||
<td>510 nm</td>
|
||||
<td id="E">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>F</td>
|
||||
<td>535 nm</td>
|
||||
<td id="F">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>G</td>
|
||||
<td>560 nm</td>
|
||||
<td id="G">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>H</td>
|
||||
<td>585 nm</td>
|
||||
<td id="H">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>R</td>
|
||||
<td>610 nm</td>
|
||||
<td id="R">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>I</td>
|
||||
<td>645 nm</td>
|
||||
<td id="I">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S</td>
|
||||
<td>680 nm</td>
|
||||
<td id="S">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>J</td>
|
||||
<td>705 nm</td>
|
||||
<td id="J">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>T</td>
|
||||
<td>730 nm</td>
|
||||
<td id="T">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>U</td>
|
||||
<td>760 nm</td>
|
||||
<td id="U">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>V</td>
|
||||
<td>810 nm</td>
|
||||
<td id="V">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>W</td>
|
||||
<td>860 nm</td>
|
||||
<td id="W">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>K</td>
|
||||
<td>900 nm</td>
|
||||
<td id="K">---</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td>L</td>
|
||||
<td>940 nm</td>
|
||||
<td id="L">---</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="col-sm">
|
||||
<h4>UV+Illuminance</h4>
|
||||
<table class="table-dark table table-sm" id="luxuv">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>Illuminance [lx]</td>
|
||||
<td id="lx">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UVA irradiance [μW/cm²]</td>
|
||||
<td id="uva">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UVB irradiance [μW/cm²]</td>
|
||||
<td id="uvb">---</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UVA/UVB average [μW/cm²]</td>
|
||||
<td id="uvi">---</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# getcdata.py - fetch the calibrated data from the AS7265x module
|
||||
# All code in this file is licensed under the ISC license, provided in LICENSE.txt
|
||||
|
||||
import serial as ser
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import time
|
||||
#global variables
|
||||
uartpath = '/dev/ttyUSB0'
|
||||
uartbaud = 115200
|
||||
uarttout = 5
|
||||
|
||||
wl = [410, 435, 460, 485, 510, 535, 560, 585, 610, 645, 680, 705, 730, 760, 810, 860, 900, 940]
|
||||
responseorder = [i for i in 'RSTUVWGHIJKLABCDEF'] # works, do NOT touch!
|
||||
realorder = [i for i in 'ABCDEFGHRISJTUVWKL']
|
||||
|
||||
|
||||
print('getcdata')
|
||||
print('This utility is part of the TeraHz project')
|
||||
|
||||
wavelens = pd.Series(realorder)
|
||||
|
||||
|
||||
plt.ion()
|
||||
win = plt.figure()
|
||||
spectrum=win.add_subplot(111)
|
||||
|
||||
|
||||
with ser.Serial(uartpath, uartbaud, timeout=uarttout) as sensor:
|
||||
while True:
|
||||
sensor.write(b'ATCDATA\n')
|
||||
rawresp = sensor.readline().decode()
|
||||
# parses, calculates and saves the data
|
||||
response = pd.Series([float(i)/35.0 for i in rawresp[:-3].split(',')], index=responseorder)
|
||||
data = pd.DataFrame(response, index=realorder, columns = ['uW/cm^2']) # puts data into a DataFrame
|
||||
data.insert(0, 'wavelenght', wl) #inserts a legend
|
||||
print(data)
|
||||
spectrum.cla()
|
||||
spectrum.plot(data['wavelenght'], data['uW/cm^2'])
|
||||
spectrum.set_xlabel('Valovna dolžina')
|
||||
spectrum.set_ylabel('uW/cm2')
|
||||
win.canvas.draw()
|
||||
|
||||
time.sleep(0.1)
|
||||
@@ -1,12 +0,0 @@
|
||||
import smbus2
|
||||
|
||||
bus = smbus2.SMBus(1)
|
||||
|
||||
result = bus.read_byte_data(0x39, 0x8a)
|
||||
print('LUX Meter ID = {}'.format(result))
|
||||
|
||||
result = bus.read_word_data(0x10, 0x0c)
|
||||
print('UV sensor ID = {}'.format(result))
|
||||
|
||||
result = bus.read_word_data(0x39, 0xec)
|
||||
print('LUX chan 0 = {}'.format(result))
|
||||
@@ -1,22 +0,0 @@
|
||||
from serial import Serial
|
||||
import tkinter as tk
|
||||
import pandas as pd
|
||||
|
||||
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
|
||||
from matplotlib.backend_bases import key_press_handler
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
uartpath = '/dev/ttyUSB0'
|
||||
uartbaud = 115200
|
||||
uarttout = 5
|
||||
|
||||
wl = [410, 435, 460, 485, 510, 535, 560, 585, 610, 645, 680, 705, 730, 760, 810, 860, 900, 940]
|
||||
responseorder = [i for i in 'RSTUVWGHIJKLABCDEF'] # works, do NOT touch!
|
||||
realorder = [i for i in 'ABCDEFGHRISJTUVWKL']
|
||||
|
||||
root = tk.Tk()
|
||||
root.wm_title('TeraHz Demo')
|
||||
|
||||
fig = Figure(figsize=(5, 4), dpi=100)
|
||||
plot = fig.add_subplot(111)
|
||||
canvas = FigureCanvasTkAgg(fig, master=root)
|
||||
Reference in New Issue
Block a user