Ein Freund und ich versuchen aktuell unser eigenes Smart Home-System zum laufen zu bringen. Für diesen Zweck haben wir bereits ein eigenes User-Interface in Form einer Web-Applikation entworfen. Verschiedene Arduino-Sensoren (ESP8266 Node-MCU-12 Module) kommunizieren bereits mit einer Datenbank, die von dem UI ausgelesen wird.
Allerdings haben wir noch ein grundsätzliches Problem: Wir verwenden einen Magnetsensor (switchReed) als Türsensor, um zu überprüfen, ob die Haustür geöffnet oder geschlossen ist. Bei dem jeweiligen Zustand wird entweder eine "1" (geöffnet) oder eine "0" (geschlossen) in die Datenbank geschrieben und die Web-Oberfläche liest die Datenbank aus, um dann das richtige Icon anzuzeigen. Dieser Vorgang funktioniert bereits. Zusätzlich soll nun ein Buzzer über die Web-Oberfläche gesteuert werden können (Alarmfunktion ein- und ausschalten). Die Buttons für das Ein- und Ausschalten der Alarmanlage schreiben ebenfalls "1" (aktiv) und "0" (inaktiv) in eine separate Datenbank. Nun soll der Arduino-Sketch neben der Meldung (Türstatus offen/ geschlossen) eine Abfrage starten, ob der Alarm aktiv oder inaktiv ist. Sofern dieser aktiv ist, muss der Buzzer einen Ton erklingen lassen, sobald die Tür geöffnet wird.
Im Folgenden nun also unter Sketch. Wir wissen absolut nicht weiter und wenn uns jemand einen Weg aufzeigen kann, wie wir das Problem beheben können, wären wir dankbar:
//MySQL
#include <MySQL_Connection.h> // Einbindung Bibliothek; Verbindung zum MySQL-Server
#include <MySQL_Cursor.h> // Einbindung Bibliothek; Schreiben in die MySQL-Datenbank
#include <ESP8266WiFi.h> // Einbindung Bibliothek; Verwendung des Arduino ESP8266
#include <WiFiClient.h> // Einbindung Bibliothek; Verbindung zum WLAN
const int switchReed=13; // Deklarierung der Variable switchReed; Festlegung des PINS 12
const int buzzer = 12;
//WiFi + MySQL
WiFiServer server(301); // Initalisierung eines WiFi-Servers mit dem entsprechenden Port
const char *ssid = "UNSER WLAN"; // Name des WLAN's, mit dem sich der Arduino verbinden soll
const char *pass = "UNSER PASSWORT"; // Passwort des WLAN's, mit dem verbunden werden soll
const char* host = ""; // Offizieller Name des Hosts
byte mac[6]; // Mac-Adresse für den WiFi-Shield
WiFiClient client; // Erstellung eines Clients zur Verbindung mit einer spezifizierten IP-Adresse
MySQL_Connection conn((Client *)&client); // Erstellung eines Clients zur Verbindung mit einem MySQL-Server
char query[] = "SELECT Spalte FROM Datenbankname.Datenbanktabelle";
char INSERT_SQL[] = "INSERT INTO Datenbankname.Datenbanktabelle(Spalte) VALUES (%d)"; // Anweisung, dass erhobene Daten in die entsprechende Datenbank geschrieben werden soll
IPAddress server_addr(XXX, XXX, XXX, XXX); // IP-Adresse des MySQL-Servers
char user[] = "UNSER BENUTZER"; // Benutzername für die MySQL-Datenbank
char password[] = "UNSER BENUTZER_PASSWORT"; // Passwort für die MySQL-Datenbank
void setup() { // Void Setup; Initialisierung einmaliger Vorgänge
Serial.begin(9600); // Initialisierung der seriellen Schnittstelle
pinMode(switchReed, INPUT); // Auslesen des Magnetsensors
pinMode(buzzer, OUTPUT);
//WiFi + MySQL
Serial.begin(9600); // Initialisierung der seriellen Schnittstelle
delay(10); // Unterbrechung (10 Millisekunden)
Serial.println("Connecting to "); // Serielle Textausgabe "Connecting to" in neuer Zeile
Serial.println(ssid); // Serielle Textausgabe des Netzwerk-Names in neuer Zeile
WiFi.begin(ssid, pass); // Initialisierung der Netzwerk-Einstellungen aus Bibliothek; Abgleich des Netzwerknames und des Passworts
while (WiFi.status() != WL_CONNECTED) { // While-Schleife; Anweisung etwas zu tun, solange die Verbindung zum Netzwerk nicht hergestellt ist
delay(500); // Unterbrechung (500 Millisekunden)
Serial.print("."); // Serielle Textausgabe "."
}
Serial.println(""); // Serielle Textausgabe " " in neuer Zeile
Serial.println("WiFi connected"); // Serielle Textausgabe "Wifi Connected" in neuer Zeile
WiFi.macAddress(mac); // Abfrage der MAC-Adresse für den WiFi-Shield des EPS8266
Serial.print("MAC: "); // Serielle Textausgabe "MAC: "
Serial.print(mac[5],HEX); // Serielle Textausgabe der MAC-Adresse; Speicherung in einem 5-Byte-Array
Serial.print(":"); // Serielle Textausgabe ":"
Serial.print(mac[4],HEX); // Serielle Textausgabe der MAC-Adresse; Speicherung in einem 4-Byte-Array
Serial.print(":"); // Serielle Textausgabe ":"
Serial.print(mac[3],HEX); // Serielle Textausgabe der MAC-Adresse; Speicherung in einem 3-Byte-Array
Serial.print(":"); // Serielle Textausgabe ":"
Serial.print(mac[2],HEX); // Serielle Textausgabe der MAC-Adresse; Speicherung in einem 2-Byte-Array
Serial.print(":"); // Serielle Textausgabe ":"
Serial.print(mac[1],HEX); // Serielle Textausgabe der MAC-Adresse; Speicherung in einem 1-Byte-Array
Serial.print(":"); // Serielle Textausgabe ":"
Serial.println(mac[0],HEX); // Serielle Textausgabe der MAC-Adresse; Speicherung in einem 0-Byte-Array in neuer Zeile
Serial.println(""); // Serielle Textausgabe " " in neuer Zeile
Serial.print("Assigned IP: "); // Serielle Textausgabe "Assigned IP: "
Serial.print(WiFi.localIP()); // Serielle Textausgabe der für die dem WiFi-Shield zugewiesene IP-Adresse
Serial.println(""); // Serielle Textausgabe " " in neuer Zeile
}
void loop() {
row_values *row = NULL;
long head_count = 0;
delay(1000);
//---------------------------------------------------------SENDING DOOR STATUS------------------------------------------------------------------
if (conn.connect(server_addr, 3306, user, password)) { // While-Schleife; Abgleich der MySQL-Server-Adresse, des Server-Ports, des Benutzernamens und des Benutzer-Passworts
// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
if (digitalRead(switchReed)==HIGH){ // if-Schleife; Anweisung etwas zu tun, wenn Daten vom Magnet-Sensot empfangen werden
Serial.println("Your Door is Closed"); // Serielle Textausgabe "Your Door is Closed" in neuer Zeile
sprintf(query, INSERT_SQL, 0); // Schreiben des Wertes "0" in die deklarierte MySQL-Datenbank
}
else { // else-Anweisung; alternative Anweisung, wenn die if-Schleife nicht erfüllt ist
Serial.println("Your Door is Open"); // Serielle Textausgabe "Your Door is Open" in neuer Zeile
sprintf(query, INSERT_SQL, 1); // Schreiben des Wertes "1" in die deklarierte MySQL-Datenbank
}
delay(100);
delete cur_mem;
// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
Serial.println("Data recorded.");
}
else {
Serial.println("Connection failed.");
}
//--------------------------------------------------------READING BUZZER STATUS----------------------------------------------------------------------
Serial.println("Hier stoppt der Sketch?!");
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
// Execute the query
// cur_mem->execute(query);
// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();
// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();
if (row != NULL) {
head_count = atol(row->values[0]);
}
} while (row != NULL);
// Deleting the cursor also frees up memory used
delay(500);
if (head_count == 1 && digitalRead(switchReed)==LOW) // if-Schleife; Anweisung etwas zu tun, wenn der auslesene Wert größer als die Variable sensorThres ist
{
Serial.println("Der Buzzer ist !!!>AKTIV<!!!"); // Serielle Textausgabe "Achtung! Feueralarm!" in neuer Zeile
tone(buzzer, 1000); // Send 1KHz sound signal...
delay(1); // ...for 1 sec
tone(buzzer, 1000); // Send 1KHz sound signal...
delay(1); // ...for 1sec
}
else
{
Serial.println("Der Buzzer ist !!!>INAKTIV<!!!");// Serielle Textausgabe "Keine Rauch- und Feuermeldungen vorhanden" in neuer Zeile
noTone(buzzer); // Stop sound...
}
delay(100); // Unterbrechung (5 Millisekunden)
cur_mem->execute(query);
delete cur_mem;
conn.close();
delay (10000);
}
Unser generelles Problem betrifft den void loop () ... dieser startet erfolgreich, indem er den Magnetsensor (switchReed) ausliest und den Status an die Datenbank weitergibt. Allerdings stoppt der
Sketch nach diesem Vorgang.
Wie lange dauert ein loop() Durchlauf bei euch?
Passt das zu der AlarmPiepser-Funktion ? Wenn nicht, solltet ihr die delay(10000); u.ä. durch eine nicht blockierende Zustandsführung ersetzen.
Wenn ich Kommentare wie
Serial.println("Hier stoppt der Sketch?!");
sehe, wundere ich mich etwas.
Auch
// Deleting the cursor also frees up memory used
ohne entsprechenden Code macht mich stutzig, ob man das nicht erst reparieren sollte, bevor man weitere Funktionen anfügt. ( Edit: Ah, weiter hinten schwirrt ein delete rum )
Also: bitte erstmal aufräumen und Kommentare korrigieren,
dann die eigentliche Frage dieses Threads
"MySQL Datenabfrage und Datenempfang in gleichem Sketch"
durch eine einfache TestLED realisieren und schauen ob die vorhandenen Verzögerungen so erträglich sind.
Ich würde eher einmal die Connection öffnen, lesen (SELECT) nur bei Bedarf ein schreib (INSERT) durchführen und wieder schliessen.
Wie lange soll es übrigens piepsen? Bis Tür zu, Freigabe weg, Datenbank-Freigabe weg, aber mindestens mal 1 sec lang?
Daraus ergibt sich schonmal ein Anhalts-Wert für das max. erlaubte delay in loop()
Das würde ich Dir gerne beantworten, aber selbst nach einigen Minuten warten, reagiert der Sketch nicht mehr ... also kann ich es leider nicht sagen.
Also: bitte erstmal aufräumen und Kommentare korrigieren,
dann die eigentliche Frage dieses Threads
"MySQL Datenabfrage und Datenempfang in gleichem Sketch"
durch eine einfache TestLED realisieren und schauen ob die vorhandenen Verzögerungen so erträglich sind.
Ich würde eher einmal die Connection öffnen, lesen (SELECT) nur bei Bedarf ein schreib (INSERT) durchführen und wieder schliessen.
Wir haben eine Abfrage unserer Datenbank bereits realisiert. In diesem Fall funktioniert es problemlos. Wir können mit Hilfe unserer Benutzeroberfläche eine Lampe ein- und ausschalten. Der Anwendungsfall ist ähnlich dem der Alarmanlage: Wenn wir den Einschaltbutton für das Licht betätigen, wird eine "1" an die Datenbank gesendet, beim Ausschalten eine "0". Der Arduino-Sketch fragt ab, ob eine "1" in der Datenbank
gespeichert wurde. Wenn ja, wird die Lampe eingeschaltet.
Wie lange soll es übrigens piepsen? Bis Tür zu, Freigabe weg, Datenbank-Freigabe weg, aber mindestens mal 1 sec lang?
Daraus ergibt sich schonmal ein Anhalts-Wert für das max. erlaubte delay in loop()
Insgesamt soll es solange piepsen, bis die Tür wieder geschlossen wird (bei aktivierter Alarmschaltung) ... wenn die Alarmschaltung inaktiv ist, soll der Buzzer natürlich weder bei geöffneter noch bei geschlossener
Tür piepsen.
Welchen Sinn macht es die MacAdresse gespiegelt auszugeben?
Für was braucht man das?
Gruß Fips
Vielen Dank für deine Antwort. Grundsätzlich hast du recht, dass es nicht benötigt wird. Allerdings
ist der Code in dieser Form in unserer Quelle angegeben und wir haben den Sketch nicht weiter in dieser Hinsicht bearbeitet.
Deine Anmerkung haben wir umgesetzt und einen Code gebastelt, allerdings funktioniert er noch nicht:
//MySQL
#include <MySQL_Connection.h> // Einbindung Bibliothek; Verbindung zum MySQL-Server
#include <MySQL_Cursor.h> // Einbindung Bibliothek; Schreiben in die MySQL-Datenbank
#include <ESP8266WiFi.h> // Einbindung Bibliothek; Verwendung des Arduino ESP8266
#include <WiFiClient.h> // Einbindung Bibliothek; Verbindung zum WLAN
int buzzer = 12;
const int switchReed=13;
//WiFi + MySQL
WiFiServer server(301); // Initalisierung eines WiFi-Servers mit dem entsprechenden Port
const char *ssid = "UNSER WLAN"; // Name des WLAN's, mit dem sich der Arduino verbinden soll
const char *pass = "UNSER PASSWORT"; // Passwort des WLAN's, mit dem verbunden werden soll
const char* host = ""; // Offizieller Name des Hosts
byte mac[6]; // Mac-Adresse für den WiFi-Shield
WiFiClient client; // Erstellung eines Clients zur Verbindung mit einer spezifizierten IP-Adresse
MySQL_Connection conn((Client *)&client); // Erstellung eines Clients zur Verbindung mit einem MySQL-Server
IPAddress server_addr(XXX, XX, XX, XX); // IP-Adresse des MySQL-Servers
char user[] = "BENUTZER"; // Benutzername für die MySQL-Datenbank
char password[] = "PASSWORT"; // Passwort für die MySQL-Datenbank
// Sample query
char query[] = "SELECT light FROM k71273_esp.02_fl_bulb";
char INSERT_SQL[] = "INSERT INTO k71273_esp.02_fl_door(status) VALUES (%d)"; // Anweisung, dass erhobene Daten in die entsprechende Datenbank geschrieben werden soll
void setup() { // Void Setup; Initialisierung einmaliger Vorgänge
pinMode(buzzer, OUTPUT);
//WiFi + MySQL
Serial.begin(9600); // Initialisierung der seriellen Schnittstelle
delay(10); // Unterbrechung (10 Millisekunden)
Serial.println("Connecting to "); // Serielle Textausgabe "Connecting to" in neuer Zeile
Serial.println(ssid); // Serielle Textausgabe des Netzwerk-Names in neuer Zeile
WiFi.begin(ssid, pass); // Initialisierung der Netzwerk-Einstellungen aus Bibliothek; Abgleich des Netzwerknames und des Passworts
while (WiFi.status() != WL_CONNECTED) { // While-Schleife; Anweisung etwas zu tun, solange die Verbindung zum Netzwerk nicht hergestellt ist
delay(500); // Unterbrechung (500 Millisekunden)
Serial.print("."); // Serielle Textausgabe "."
}
Serial.println(""); // Serielle Textausgabe " " in neuer Zeile
Serial.println("WiFi connected"); // Serielle Textausgabe "Wifi Connected" in neuer Zeile
WiFi.macAddress(mac); // Abfrage der MAC-Adresse für den WiFi-Shield des EPS8266
Serial.println("Connecting to database"); // Serielle Textausgabe "Connecting to database" in neuer Zeile
while (conn.connect(server_addr, 3306, user, password) != true) { // While-Schleife; Abgleich der MySQL-Server-Adresse, des Server-Ports, des Benutzernamens und des Benutzer-Passworts
delay(5); // Unterbrechung (5 Millisekunden)
Serial.print ( "." ); // Serielle Textausgabe "."
}
Serial.println(""); // Serielle Textausgabe " " in neuer Zeile
Serial.println("Connected to SQL Server!"); // Serielle Textausgabe "Connected to SQL Server!" in neuer Zeile; Mitteilung erfolgreiche Verbindung
}
void BuzzerOnOff() {
MySQL_Cursor cur = MySQL_Cursor(&conn);
row_values *row = NULL;
long head_count = 0;
delay(1000);
Serial.println("1) Demonstrating using a cursor dynamically allocated.");
// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
// Execute the query
cur_mem->execute(query);
// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();
// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();
if (row != NULL) {
head_count = atol(row->values[0]);
}
} while (row != NULL);
// Deleting the cursor also frees up memory used
delete cur_mem;
// Show the result
// Serial.print(" NYC pop = ");
// Serial.println(head_count);
delay(500);
if (head_count == 1) // if-Schleife; Anweisung etwas zu tun, wenn der auslesene Wert größer als die Variable sensorThres ist
{
Serial.println("Der Alarm ist !>aktiv<!"); // Serielle Textausgabe "Achtung! Feueralarm!" in neuer Zeile
tone(buzzer, 1000);
}
else
{
Serial.println("Der Alarm ist !>inaktiv<!"); // Serielle Textausgabe "Keine Rauch- und Feuermeldungen vorhanden" in neuer Zeile
noTone(buzzer);
}
}
void loop() { // Ausführung des eigentlichen Programms
if (digitalRead(switchReed)==LOW){ // if-Schleife; Anweisung etwas zu tun, wenn Daten vom Magnet-Sensot empfangen werden
Serial.println("Your Door is Open"); // Serielle Textausgabe "Your Door is Closed" in neuer Zeile
BuzzerOnOff(); // Ausführen der Anweisung "BuzzerOnOff"
sprintf(query, INSERT_SQL, 1); // Schreiben des Wertes "0" in die deklarierte MySQL-Datenbank
}
else { // else-Anweisung; alternative Anweisung, wenn die if-Schleife nicht erfüllt ist
Serial.println("Your Door is Closed"); // Serielle Textausgabe "Your Door is Open" in neuer Zeile
sprintf(query, INSERT_SQL, 0); // Schreiben des Wertes "1" in die deklarierte MySQL-Datenbank
}
delay(100); // Unterbrechung (5 Millisekunden)
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
cur_mem->execute(query);
delete cur_mem;
}