Arduino Daten in MariaDB auf Raspberry

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
zeitiii_zeitii
User
Beiträge: 3
Registriert: Mittwoch 15. Februar 2023, 09:05

Hi,

Will mit meinem Arduino Messdaten des DHT22 auf einem Raspberry Pi 4 in eine MariaDB speichern.
Verbunden sind sie via USB.

Hier mein Arduino Code:

Code: Alles auswählen

#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
int HUM;
int TEMP;


void setup() {
  Serial.begin(9600);
  dht.begin();
}
void loop() {
  getDHT22();
  Serial.println(TEMP);
  Serial.println(HUM);
}


void getDHT22() {
  HUM = dht.readHumidity();
  TEMP = dht.readTemperature();
}
Am Raspberry sieht mein Python-Script so aus. Und hier tritt der Fehler ein. Die Werte, die in die Datenbank gespeichert werden, bleiben immer gleich. Ich habe bewusst durch anpusten, Feuerzeug (ja ich weiß, nicht das schlauste Idee) versucht, die Werte zu ändern. In der Datenbank blieben diese allerdings gleich.
Ich weiß absolut nichtmehr weiter, kann mir bitte bitte jemand helfen?

Raspberry Pi Code:

Code: Alles auswählen

#!/usr/bin/env python3
import serial
import mysql.connector
import time

def store_to_database(t, h):
    mydb = mysql.connector.connect(
        host="localhost",
        user="user",
        password="passme",
        database="mydb"
    )

    mycursor = mydb.cursor()

    
    sql = "INSERT INTO mydb (Temp, LF, inserttime) VALUES (%s, %s, now())"
    val = (t, h,)
    mycursor.execute(sql, val)
    # Commit the changes to the database
    mydb.commit()

   
    mycursor.close()
    mydb.close()

if __name__ == '__main__':
    ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)

    while True:
        line = ser.readline().decode('utf-8').rstrip()
        t = line.split("\n")[0]
        line = ser.readline().decode('utf-8').rstrip()
        h = line.split("\n")[0]
        store_to_database(t,h)
        ser.reset_input_buffer()
        time.sleep(30)
Bräuchte wirklich dringende Hilfe
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Code ist konzeptionell schon kaputt. Einfach zeilenweise abwechselnd werte zu schreiben und dann zu hoffen, dass man die auch genauso in der Reihenfolge einlesen wird, ist zum scheitern verurteilt. Du hast keine Ahnung beim öffnen der seriellen Schnittstelle, was gerade an Daten ansteht. Entsprechend fließen die Daten dann falsch.

Stattdessen bietet sich an, beide Werte in einer Zeile zu schreiben. Damit ist die Reihenfolge festgelegt. Natürlich mit einem Trennzeichen dazwischen. Kann ein simples Leerzeichen sein. Auch ist die Datenrate unkontrolliert und viel zu hoch. Du liest Dutzende wenn nicht mehr Male pro Sekunde ein & produzierte Ausgaben. Da braucht das eine sinnvolle Wartezeit.

Die Datenbank für jede Transaktion komplett zu öffnen und wieder zu schließen ist auch ein anti-pattern. Einmal öffnen reicht. Ich weiß aus dem Kopf nicht, ob man den Cursor wiederverwenden kann. Glaube aber schon.

Was dein Problem angeht: entweder die Daten die kommen sind immer gleich. Oder die Datenbankoperation geht schief. Das kann man einfach testen, indem man die Werte der seriellen Schnittstelle ignoriert, und statt dessen einfach Werte hochzählt, und die speichert. Wenn die in der DB landen, ist der Arduino das Problem.
Benutzeravatar
Dennis89
User
Beiträge: 1556
Registriert: Freitag 11. Dezember 2020, 15:13

"When I got the music, I got a place to go" [Rancid, 1993]
zeitiii_zeitii
User
Beiträge: 3
Registriert: Mittwoch 15. Februar 2023, 09:05

@__deets__ vielen vielen Dank schonmal!

Werd deine tipps versuchsen
Ich glaube aber trotzdem das im skript etwas nixht passt und die werte nur einmal eingelesen werden. Wenn ich ein skript erstelle und in dem die eingänge ausgeben lasse verändern sich diese werte.
Glaube das das db Skript einmal die serielle Schnittstelle abfragt und dann nichtmehr.

Kannst du mir bitte noch mehr helfen?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@zeitii_zeitii: wenn du das glaubst, dann kannst du das ueberpruefen, indem du zB print-statements in das DB-Skript packst, die dir mitteilen, ob da Daten eingelesen werden.
zeitiii_zeitii
User
Beiträge: 3
Registriert: Mittwoch 15. Februar 2023, 09:05

Habe das Problem gelöst.

Nochmal zur Klarstellung des Projekts (für Suchende in der Zukunft evtl).

Es wird ein Raspberry Pi 4 als "Server" genutzt. Auf diesem läuft ein lighttpd Webserver und eine MariaDB.
Der Raspberry ist via USB mit einem Arduino Micro verbunden. Der Arduino Micro steuert verschiedene Sensoren, welche Werte aus der Luft auslesen (DHT22, MH-Z19b, etc.).
Diese Werte sollen an den Raspberry geschickt werden, damit dieser sie in die Datenbank speichern. Die Messergebnisse werden auf einer Website dargestellt.

Die Lösung meines Problems war:
Der Arduino sendete durchgehend seine Daten, aber eigentlich wollte ich nur, das diese sendet wenn der Raspberry dies anfordert.
Quasi der Raspberry gibt dem Arduino das Zeichen, das er senden darf.

Am Raspberry Pi läuft dieses Skript (wird noch angepasst das es als Service läuft und direkt beim Booten gestartet wird):

Code: Alles auswählen

import serial
import mariadb
import sys
import time

# Konfiguration für die Serielle Schnittstelle
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)

# Konfiguration für die Datenbankverbindung
config = {
  'host': 'localhost',
  'user': 'my_user',
  'password': 'my_pw',
  'database': 'mydb'
}

# Verbindung zur Datenbank herstellen
try:
    conn = mariadb.connect(**config)
except mariadb.Error as e:
    print(f"Fehler bei der Verbindung zur Datenbank: {e}")
    sys.exit(1)

# Cursor erstellen
cur = conn.cursor()

while True:
    try:
        # Arduino fragen, wie hoch die Werte momentan sind
        ser.write(b'r')
        arduino_data = ser.readline().decode('utf-8').strip().split('\t')
        temperature = float(arduino_data[0])
        humidity = float(arduino_data[1])

        # Daten in die Datenbank speichern
        cur.execute("INSERT INTO mydb (Temp, LF, inserttime) VALUES (?, ?, now())", (temperature, humidity))
        conn.commit()

        print(f"Temperatur: {temperature}°C, Luftfeuchtigkeit: {humidity}%")

    except (IndexError, ValueError, mariadb.Error) as e:
        print(f"Fehler beim Auslesen oder Speichern der Daten: {e}")
        time.sleep(1)
        continue

    time.sleep(10)
Die zu installierenden Pakete:
sudo pip install pyserial
pip install mariadb


Der Arduino Code:

Code: Alles auswählen

#include "DHT.h"

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
}

void loop() {
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == 'r') {
      int h = dht.readHumidity();
      int t = dht.readTemperature();

      if (isnan(t) || isnan(h)) {
        Serial.println("Failed to read from DHT");
      } else {
        Serial.print(t);
        Serial.print('\t');
        Serial.println(h);
      }
    }
  }
}
Am Raspberry wird über die serielle Schnittstelle ein 'r' gesendet, erhält der Arduino dieses, printet er die Daten aus (quasi schicken der Daten)


Vielen Dank an alle die sich beteiligt haben in diesem Thread!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der isnan-Check ist Quatsch. Ein int kennt keine NaNs. Also ist das zwingend immer wahr.
Antworten