3. Erweiterung Spannungsmessung: Zeitseriendatenbank & Grafana

3.1. Einleitung

In unseren vorherigen Projekten (Projekt 1 & Projekt 2) haben wir eine Spannungsmessung mithilfe eines Raspberry Pi Zero 2W und eines INA219-Moduls durchgeführt und anschließend um eine Live-Plot-Anwendung ergänzt. Im vergangenen Projekt wurden die Messdaten in Echtzeit visualisiert und auf einer Weboberfläche angezeigt. In diesem Projekt war das Ziel, die Anwendung so zu erweitern, dass auch zurückliegende Daten, die in einer Datenbank abgelegt werden, ebenfalls abgebildet werden können. Außerdem setzen wir auf Grafana für die bessere Visualisierung der Daten. Zuletzt wurde die Spannungsmessung von einem INA219-Modul auf einen ADS1115-Analog-Digital-Wandler (ADC) umgestellt.

3.2. Grundlagen

3.2.1. Datenbank

Die Daten, die innerhalb dieses Projekts erfasst werden, sollen innerhalb einer Datenbank abgelegt werden. Wir haben uns hierbei für eine Zeitreihendatenbank entschieden, weil diese für die effiziente Verarbeitung und Speicherung von Sensordaten mit Zeitstempel entwickelt wurden.
InfluxDB und TimescaleDB sind die führenden Open-Source-Datenbanksysteme.
InfluxDB ist eine NoSQL-Datenbank mit eigener Storage-Engine und Datenmodell. Die Datenbank ist für schnelle Ingestion und effiziente Speicherung von Messdaten optimiert. Für die Abfrage wird die Sprache Flux genutzt, die wenig verbreitet ist.
TimescaleDB hingegen basiert auf PostgreSQL und erweitert dieses um spezielle Zeitreihenfunktionen. Dadurch bietet die Datenbank alle Vorteile eines relationalen Datenbanksystems (z. B. Joins) und ist besonders für komplexe Datenstrukturen geeignet. Datenabfragen werden in SQL durchgeführt, das durch die Zeitreihenfunktionalitäten erweitert wurde.
Im Vergleich zu Influx werden bei TimescaleDB zwar mehr Ressourcen benötigt, allerdings sind die Daten bei komplexeren Strukturen besser skaliert, und TimescaleDB benötigt bei den Prozessen weniger Arbeitsspeicher.
Die Influx-Datenbank unterliegt der MIT-Lizenz, TimescaleDB unterliegt der Apache-2-Lizenz.
[Influx vs TimescaleDB]

3.2.2. Docker Compose

Eine Möglichkeit, um eine Datenbank einfach und schnell bereitzustellen, ist die Verwendung von Docker-Containern.
Wir haben uns dazu entschieden, Docker Compose zu verwenden, weil dies die Bereitstellung, Verwaltung und Skalierung der Datenbank erleichtert. Mithilfe einer Docker-Compose-YAML-Datei kann man alle Konfigurationen der Datenbank, wie Ports und Umgebungsvariablen, zentral in einer einzigen Datei festlegen. Somit kann die TimescaleDB nicht nur schnell gestartet und gestoppt werden, sondern auch in Multi-Container-Setups erweitert werden. Hierbei werden die persistenten Daten über Volumes verwaltet, sodass Daten auch nach einem Neustart oder Austausch des Containers erhalten bleiben.
[TimescaleDB & Docker]

3.2.3. Grafana

Grafana ist ein Open-Source-Plattform zur Analyse und Visualisierung von Daten.
Diese Daten können aus verschiedenen Datenbanken geholt werden und in interaktiven Dashboards dargestellt werden.
Zur Erstellung von Dashboards bietet Grafana eine benutzerfreundliche Weboberfläche, in der Benutzer Diagramme, Graphen und Alarme erstellen können.
[Grafana Overview]

3.3. Durchführung

3.3.1. Hardware

Bisher setzte die Spannungsmessung auf ein INA219 Modul, das zwar eine recht genaue Messung der Spannung am Bus erlaubt, jedoch nicht direkt für diesen Einsatz vorgesehen ist.
Deshalb wurde das Modul durch ein ADS1115 ersetzt. Der ADS1115 ist ein Analog-Digital-Wandler (ADC) und bietet vier Kanäle mit 16-Bit Auflösung.

Um eine Spannung von 12V messen zu können, wurde ein Spannungsteiler bestehend aus einem 10 kOhm und einem 47 kOhm Widerstand verwendet. Die Spannung wird so um den Faktor 5,7 geteilt.
So kann der ADS1115 mit 3.3V betrieben werden.

Die Formel zur Berechnung der geteilten Spannung lautet:

\[V_{\text{out}} = V_{\text{in}} \cdot \frac{R_2}{R_1 + R_2}\]

Die Komponenten wurden entsprechend folgendem Schaltplan verbunden:

Spannungsverlauf Grafana

3.3.2. Software

3.3.2.1. Spannungsmessung

Das Skript zur Spannungsmessung wurde für die Verwendung des ADS1115 umgeschrieben.
Zur Kommunikation mit dem ADS1115 wird die Bibliothek adafruit_ads1x15 verwendet.
Die TimescaleDB wird über die Bibliothek psycopg2 angesprochen.

3.3.2.2. Docker Compose

Zum Starten und Stoppen der Datenbank wurde eine Docker-Compose-YAML-Datei verwendet. Diese Datei verwendet das TimescaleDB-Image und enthält die Konfigurationsparameter für die Datenbank.

Zur Darstellung der Daten in Graphen wurde die bisherige Webanwendung, die auf Plotly Dash basiert, durch Grafana ergänzt. Grafana ist ein Open-Source-Tool zur Visualisierung von Daten und bietet eine Vielzahl von Funktionen zur Erstellung von Dashboards und Grafiken. Grafana kann verschiedene Datenquellen einbinden, darunter auch TimescaleDB.

3.3.2.3. Datenbank

Um die gewünschten Funktionen in der Datenbank zu erstellen, wurde ein Skript zur Verwaltung von Zeitreihendaten einer TimescaleDB-Datenbank erstellt. Das Skript umfasst Funktionen zum Erstellen, Befüllen, Abrufen und Löschen von Daten sowie zur Aktivierung von TimescaleDB-spezifischen Funktionen wie Hypertables und Komprimierung. Die Tabellen wurden in Hypertables konvertiert, da diese für die Speicherung und Abfragen optimiert wurden. Die Komprimierung wurde mithilfe einer Komprimierungsrichtlinie umgesetzt, die ältere Daten minütlich komprimieren soll.

3.3.3. Ausgabe

Die Ausgabe der Daten erfolgt mittels Grafana. Hierbei wird zuerst die TimescaleDB als Datenquelle hinterlegt. Anschließend wird ein Dashboard erstellt, in dem die gewünschten Grafiken dargestellt werden. Die folgende Grafik zeigt die Spannung über einen gewissen Zeitraum. Neben den aktuellen Messwerten wird auch eine Kurve angezeigt, die die Spannungen in 1-minütige Intervalle zusammenfasst.

Spannungsverlauf Grafana

Diese Art der Datenverarbeitung ist ein großer Vorteil von Zeitreihendatenbanken, da sie eine effiziente Speicherung und Abfrage von großen Datenmengen über lange Zeiträume ermöglichen. TimescaleDB erlaubt dies in Kombination mit bekannter SQL-Syntax, wie der folgende Ausschnitt zeigt:

SELECT
  time_bucket('1 minute', timestamp) AS average,
  ROUND(AVG(voltage)::numeric, 3) AS voltage_mean
FROM measurements
WHERE $__timeFilter(timestamp)
GROUP BY average
ORDER BY average

3.4. Quellen

Influx-vs-TimescaleDB: https://risingwave.com/blog/influxdb-vs-timescale-a-detailed-comparison/

TimescaleDB-Docker: https://docs.timescale.com/self-hosted/latest/install/installation-docker/

Grafana-Overview: https://grafana.com/docs/grafana/latest/?pg=oss-graf&plcmt=hero-btn-2

adafruit_ads1x15: https://pypi.org/project/Adafruit-ADS1x15

psycopg2: https://pypi.org/project/psycopg2/