Photo-Resistor-Daten mit Web-Interface
Grundlegendes
Bei diesem Projekt ist der Arduino via USB-Kabel mit einem Raspberry Pi verbunden, auf dem Apache und PHP7 installiert ist.
Der Arduino zeichnet alle 5s einen Helligkeiswert auf und schickt diesen über das USB-Kabel an den Raspberry Pi. Via Python werden dort die vom Arduino empfangenen Helligkeitswerte in einer CSV-Datei gespeichert. Via p5.js wird die CSV-Datei ausgelesen und als Graph im Browser dargestellt.
Arduino-Hardware-Aufbau
Der Arduino-Hardware-Aufbau ist identisch mit dem vorherigen Aufbau („Photo-Resistor (Fotozelle)“)
Der Arduino-Code unterscheidet sich auch nicht groß, nur das Abfrage-Intervall wurde auf 5s verlängert!
Arduino
int fotozelle = A0; // Pin Zuweisung bei A0; Widerstand 10 kOhm
void setup() {
pinMode(fotozelle, INPUT);
Serial.begin(9600);
}
void loop() {
int hell = analogRead(fotozelle); // Wert, den Fotozelle ausgibt, wird gelesen
Serial.println(hell); // Ausgabe des Helligkeitswertes der Foto-Zelle
// alle 5sek Messung, entsprechend Python-Script "fotozelle_csv_datei.py"
delay(5000);
}
Das hier gezeigte Python-Script läuft auf dem Raspberry Pi und erzeugt die CSV-Datei "data_log.csv" und speichert diese an einer Stelle, an der p5.js einfach darauf zugreifen kann:
Python
#!/user/bin/env python
# speichert die CSV-Datei im Ordner "/var/www/html/fotozelle/"
# damit das geht, muss das Script mit "sudo" ausgefuehrt werden
# sudo python fotozelle_csv_datei_2.py
import os
import time
from time import sleep
from datetime import datetime
import serial
# hier richtigen Serial-Port des Arduinos angeben!
port = "/dev/ttyACM0"
# pfad zum HTML-Ordner
pfadDatei = "/var/www/html/fotozelle/daten/data_log.csv"
# Geschwindigkeit muss identisch wie bei Arduino-Script sein!
s1 = serial.Serial(port,9600)
s1.flushInput()
file = open(pfadDatei, "a")
while True:
if s1.inWaiting()>0:
# formatierte Datum- und Zeit-Kombination
now = datetime.now().strftime('%Y-%m-%d,%H:%M:%S')
# gibt den Helligkeiswert jeweil in einer Zeile aus
inputValue =s1.readline()
# "\n" macht jeweils eine Leerzeile
file.write(str(now)+","+inputValue+"\n")
file.flush()
# Script wartet 5 Sekunden, bis es sich wiederholt (entsprechend der Zeit im Arduino-Sketch
time.sleep(5)
file.close()
Das oben gezeigte Python-Script erzeugt eine CSV-Datei "data_log.csv", die beispielsweise so aussehen könnte:
CSV-Datei (Ausschnitt)
2018-11-03,14:59:43,793
2018-11-03,14:59:48,815
2018-11-03,14:59:53,352
2018-11-03,14:59:58,46
2018-11-03,15:00:03,29
2018-11-03,15:00:08,794
2018-11-03,15:00:13,793
2018-11-03,15:00:18,810
Via p5.js wird diese CSV-Datei eingelesen und als Graph im Canvas einer Website dargestellt
p5.js
var aktuelleWerte;
var HelligkeitsPunkte = [];
var factor = 0.6; // um wieviel wird Skala und Wert skaliert
var breite = 20; // Breite der Säulen
var abstand = 5; // Abstand der Säulen
var rowCount = 0; // wieviele Datensätze sind vorhanden?
var x; // Position des senkrechtes Nullpunktes
var y; // Position des waagrechten Nullpunktes
function preload() {
// alle 5 Sekunden Werte laden
loadTable("daten/data_log.csv", tableFuellen);
}
function tableFuellen(data) {
aktuelleWerte = data;
// console.log(aktuelleWerte);
}
function setup() {
var myCanvas = createCanvas(800, 658);
myCanvas.parent("graph");
x = 35;
y = height - 20;
textFont("roboto_condensedregular");
textStyle(NORMAL);
// Ausgabe der aktuellen Zeit
zeitAngabe();
// wieviele Datensätze befinden sich in der CSV-Datei?
rowCount = aktuelleWerte.getRowCount();
AnzeigeUeberCanvas();
// wieviele Werte sollen dargestellt werden?
var anzahl;
if (rowCount >= 30) {
anzahl = 30;
} else {
anzahl = rowCount;
}
noStroke();
// Darstellung der Rechtecke mit den Helligkeitswerten
// werden von rechts nach links dargestellt
// der aktuellste Wert ist also recht, nach links geht es in die Vergangenheit
for (var i = 0; i <= anzahl; i++) {
var helligkeit = HelligkeitsPunkte[rowCount - i];
// Rechtecke werden Stufenweise dunkler
fill(255 - 8.5 * i, 0, 0);
rect(
width - 5 - (breite + abstand) * i,
y,
breite,
helligkeit * -1 * factor
);
}
// Zeichnen von Skala, senkrechter Beschriftung
SkalaLinien();
}
function draw() {}
// Angaben zu Anzahl Datensätzen und letztem Wert oberhalb des Canvas
function AnzeigeUeberCanvas() {
var ausgabe = "Datensätze: " + rowCount;
document.getElementById("AnzahlDaten").innerHTML = ausgabe;
for (var i = 0; i < rowCount; i++) {
HelligkeitsPunkte[i] = aktuelleWerte.getNum(i, 2);
}
var letzterWert = HelligkeitsPunkte[rowCount - 1];
var ausgabe = "letzter Wert: " + letzterWert;
document.getElementById("letzterWert").innerHTML = ausgabe;
}
function zeitAngabe() {
var a = new Date();
var h = a.getHours();
var m = a.getMinutes();
var s = a.getSeconds();
var tag = a.getDate();
var mon = a.getMonth() + 1; //Monat fängt bei 0 an
var jahr = a.getFullYear();
var h = zahlenAuffuellen(h);
var m = zahlenAuffuellen(m);
var s = zahlenAuffuellen(s);
akt_datum = tag + "." + mon + "." + jahr;
akt_zeit = h + ":" + m + ":" + s;
var ausgabe = "Aktualisiert am " + akt_datum + " um " + akt_zeit + " Uhr";
document.getElementById("AktualisierungsDatum").innerHTML = ausgabe;
}
// wenn Stunden, Minuten, Sekunden nur einstellig sind
// werden diese mit einer Null aufgefüllt
function zahlenAuffuellen(ziffer) {
if (ziffer < 10) {
ziffer = "0" + ziffer;
}
return ziffer;
}
function SkalaLinien() {
stroke(150);
// X-Linie
line(x, y, width, y);
// Y-Linie
line(x, 10, x, y + 5);
// waagrechte SkalaLinien
stroke(190);
for (var i = 0; i <= 10; i++) {
line(x - 3, y - i * 100 * factor, width, y - i * 100 * factor);
}
// Einstellungen für Beschriftung
noStroke();
fill(100);
textSize(16);
textAlign(RIGHT);
// Beschriftung der Y-Achse
for (var i = 0; i <= 10; i++) {
var yBeschriftung = 100 * i;
text(yBeschriftung, x - 5, y - yBeschriftung * factor + 5);
}
// Beschriftung der X-Achse
textAlign(CENTER);
for (var i = 0; i <= 29; i = i + 2) {
var xBeschriftung = -5 * i + "s";
// width - 5 - (breite + abstand) * i
text(xBeschriftung, width - 20 - (breite + abstand) * i, y + 18);
}
}