Vollautomatische Katzenwaage - Programmversion 0.5
Bis einschließlich Programmversion 0.4 wird das berechnete Gewicht Leonie zugewiesen, wenn das Ergebnis zwischen 3 und 4 Kiligramm ist, und Leslie, wenn es zwischen 4 und 5 Kilogramm liegt. Das funktioniert sehr gut, besser wäre aber eine dynamische Bestimmung der Grenzwerte. Denn es hat sich gezeigt, dass Leonie, wenn sie einen Krankheitsschub hat, den unteren Grenzwert unterschreitet. Nun könnte freilich der untere Grenzwert entsprechend geändert werden. Schöner wäre es aber, wenn die Grenzwerte dynamisch bestimmt werden würden.
Das Einfachste wäre, diese Grenzwerte auf der Basis der Mittelwerte der letzten Messungen auf der Waage zu berechnen. Das Problem ist allerdings, dass Leonie hin und wieder eine der beiden Waagen viele Tage nicht benutzt. Die Daten auf dieser Waage würden dann also nicht aktualisiert. Nähme Leonie nun aufgrund eines Krankheitsschubs innerhalb weniger Tage stark ab könnte es passieren, dass dass die andere Waage Leonie nicht mehr erkennt. Jetzt könnten die Grenzwerte freilich größer gewählt werden. Aber der Sinn der Übung ist ja, die Grenzwerte möglichst klein zu halten.
Daher wird die Berechnung der Mittelwerte nicht auf den Waagen durchgeführt, sondern auf dem Server. Dafür müssen die Daten vom Server abgerufen und gespeichert werden. Erfahrungsgeäß kann dabei viel schief gehen. Daher wird der Datenabruf zunächst getestet.
Programmversion 0.5.1 ruft dafür alle 10 Minuten die Mittelwerte vom Server ab und stellt sie in der zweiten Zeile des Displays dar. Außerdem wird angezeigt, wie viel Zeit seit dem letzten erfolgreichen Abruf der Daten vergangen ist.
Programmversion 0.5.3 ruft die Daten vom Server ab, bevor die Zuordnung einer Messung zu einer katze erfolgt. Messungen, die keiner Katze zugeordnet werden können werden nicht mehr verworfen, sondern mit der cat_id = 99 gesendet.
PHP-Skript zur Abfrage der Gewichtsmittelwerte für Leonie und Leslie basierend auf den letzten 10 Messungen:
<?php // Diese Datei gibt den Mittelwert der Körpergewichte von Leonie und Leslie der letzten 10 Messungen aus include_once 'connectdb.php'; #Die Datenbank wird eingebunden $pdo = new PDO("mysql:host={$dbhost};dbname={$dbname}",$dbuser,$dbpass); #Es werden die Daten abgefragt $statement = $pdo->prepare("SELECT (SELECT AVG(t.cat_weight) FROM (SELECT cat_weight FROM catscales WHERE cat_id = 0 ORDER BY id DESC LIMIT 5) AS t) AS weight_leonie_avg, (SELECT AVG(t.cat_weight) FROM (SELECT cat_weight FROM catscales WHERE cat_id = 1 ORDER BY id DESC LIMIT 5) AS t) AS weight_leslie_avg"); $statement->execute(); $results = $statement->fetchAll(PDO::FETCH_ASSOC); #Es werden die Daten kodiert $json = json_encode($results); #Es werden die Daten ausgegeben print json_encode($results); ?>
Arduino-Code für die Abfrage der Daten vom Server:
if (WiFi.status() == WL_CONNECTED) {
// Daten von iot.frickelpiet.de/getdata.php holen
if (client.connect(server, port)) {
#ifdef DEBUG
Serial.println("Server connection OK");
#endif
// Send HTTP request
client.println(F("GET /getweight.php HTTP/1.0"));
client.println(F("Host: iot.frickelpiet.de"));
client.println(F("Connection: close"));
if (client.println() == 0) {
#ifdef DEBUG
Serial.println(F("Failed to send request"));
#endif
}
else {
// Check HTTP status
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
#ifdef DEBUG
Serial.print(F("Unexpected response: "));
Serial.println(status);
#endif
}
else {
// Skip HTTP headers
char endOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders)) {
#ifdef DEBUG
Serial.println(F("Invalid response"));
#endif
}
else {
// Allocate JsonBuffer
// Use arduinojson.org/assistant to compute the capacity.
const size_t bufferSize = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(3) + 60;
DynamicJsonBuffer jsonBuffer(bufferSize);
// Parse JSON object
JsonArray& root = jsonBuffer.parseArray(client);
if (!root.success()) {
#ifdef DEBUG
Serial.println(F("Parsing failed!"));
#endif
}
else {
// Extract values
JsonObject& root_0 = root[0];
weight_leonie_avg = root_0["weight_leonie_avg"];
weight_leslie_avg = root_0["weight_leslie_avg"];
#ifdef DEBUG
Serial.print("Mittelwert Leonie: "); Serial.println(weight_leonie_avg);
Serial.print("Mittelwert Leslie: "); Serial.println(weight_leslie_avg);
#endif
}
dataReceived = true;
lastDataReceived = currentMillis;
}
}
}
// Disconnect
client.stop();
}
}
Beobachtungen:
- Ein „Unexpected response“ des Servers hält die Programmschleife nicht an.