hardware:channels:meters:water:wasserzaehler_ohne_s0
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
hardware:channels:meters:water:wasserzaehler_ohne_s0 [2019/06/20 08:12] – gabinvigoss_gmail.com | hardware:channels:meters:water:wasserzaehler_ohne_s0 [2024/04/23 18:03] (aktuell) – Fehler beim REST Aufruf jau | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== | + | ====== |
- | ===== Le pointeur laser pour la pratique | + | ===== Ansatz 1: Text-/ |
- | Avez-vous besoin du **pointeur laser (https:// | + | **Idee:** Die Ziffern und Rädchen des Wasserzählers über eine Text-/Mustererkennung auslesen und bereitstellen.\\ |
+ | **Vorteil:** Auslesen des definierten Wertes des Wasserzählers mit geringen Kosten\\ | ||
+ | **Nachteil: | ||
+ | {{https:// | ||
+ | ==== Hardware ==== | ||
- | Si vous ne pouvez pas faire preuve de souplesse en raison de vos besoins, de votre patience ou du prix des unités, vous devez considérer que les plafonds peuvent échouer et échouent comme vous le lirez de temps en temps ici. J'ai continué à pratiquer, après quelques minutes, le laser s'est évanoui. Je pensais que les piles devaient être vieilles, alors comme j'ai commandé | + | Folgende Hardware (Gesamtkosten ~15€) wird benötigt: |
+ | * ESP32-CAM WiFi | ||
+ | * USB zu TTL UART Serial Converter zum Download | ||
+ | * Stromversorgung | ||
- | Il n'y a aucun moyen d' | + | ==== Software ==== |
- | Une autre recommandation: assurez-vous de nettoyer votre canon, surtout si vous tirez des recharges, car elles ne brûlent souvent pas aussi proprement. Je me suis rendu compte que le pointeur laser bleu 30000mW était éteint avec un baril sale. Je suis du genre à croire que la pratique rend parfait et je pense que c'est particulièrement vrai lorsqu' | + | Die Idee und Software stammt von Jomjol - die Software und eine Anleitung sind hier hinterlegt: https:// |
+ | * Für den ersten Download empfehle ich folgende Schaltung: https://www.fambach.net/ | ||
+ | * Bei Nichterkennung | ||
+ | * Bei Verbindungsproblemen -> USB-TTL/ | ||
- | Le laser est décentré d' | + | ==== vzlogger-Integration ==== |
- | //Les modules laser habituels sont disponibles avec une longueur d'onde différente: laser bleu-violet 405 nm, laser bleu 450 nm, 460 nm et 473 nm, laser vert 532 nm, laser rouge, 650 nm et laser rouge, module laser infrarouge 808 nm et 980 nm, etc. large plage de 1 mW à 30 W ou même haute.// | + | Hier der Code für die vzlogger.conf zum Abholen und Verknüpfen der Daten: |
+ | < | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }], | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Folgende Parameter müssen im Code ersetzt werden: | ||
+ | * UUID_FRONTEND: | ||
+ | * IP-ADDRESS_ESP: | ||
+ | |||
+ | Der Parameter | ||
+ | |||
+ | |||
+ | ===== Ansatz 2: Laser ===== | ||
+ | |||
+ | Idee: Das kleine Sternrad des Wasserzählers mit einem Laser anvisieren und die Reflexionen mit Photodiode und Arduino-Mikrocontroller auswerten. | ||
+ | |||
+ | ==== Hardware ==== | ||
+ | |||
+ | <note important> | ||
+ | \\ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Den Laser gibt es im Zehnerpack bei Ebay ab 2,50: | ||
+ | [[http:// | ||
+ | |||
+ | Das ganze habe ich mit einer BPW34 [[http:// | ||
+ | Als Schaltung habe ich das hier gewählt: | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | Halterung ist ein abgesägtes Stück graues PVC-Rohr. Abgesägt ist das Stück, wo normalerweise die Dichtung drin ist. | ||
+ | Darauf ist ein Aluminium Flachprofil geschraubt. | ||
+ | |||
+ | So sieht es aus, wenn es fertig ist: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Neben dem Wasserzähler greife ich auch den Gaszähler ab. Auf dem letzten Rädchen ist hier ein silber beschichtetets Stück, das hervoragend reflektiert. Hier musste ich nicht den Aufwand mit dem Laser machen, sondern nutze hier dieses Bauteil [[http:// | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Beide Zähler gehen an einen Analog in eines Arduino V3 (Ebay, deutlich unter 10 Euro) [[http:// | ||
+ | |||
+ | Es empfiehlt sich, das Analogsignal, | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | ==== Über Script in die Datenbank ==== | ||
+ | |||
+ | Für Gas- und Wasserzähler, | ||
+ | |||
+ | === Arduino === | ||
+ | |||
+ | Das ist der Code auf dem Arduino. Die Idee ist die Differenz zwischen dem Tal und dem Berg bei dem analogen Sensor als Trigger zu verwenden | ||
+ | |||
+ | <code c> | ||
+ | |||
+ | //sets ground pin to LOW and input pin to HIGH | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(38400); | ||
+ | // | ||
+ | digitalWrite(A1, | ||
+ | } | ||
+ | long wasser_counter = 0; | ||
+ | long gas_counter = 0; | ||
+ | long loops = 0; | ||
+ | int wasser_max = 0; | ||
+ | int gas_max = 0; | ||
+ | long wasser = 0; | ||
+ | long gas = 0; | ||
+ | int wasser_z = 0; | ||
+ | int gas_z = 0; | ||
+ | unsigned long lastlog = 0; | ||
+ | unsigned long last_gas = 0; | ||
+ | unsigned long last_wasser = 0; | ||
+ | unsigned long time; | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | // Gleitender Durchschnitt anwenden. | ||
+ | gas = ((gas *9) + analogRead(1)) /10; | ||
+ | wasser = ((wasser *3) + analogRead(0))/ | ||
+ | time = millis(); | ||
+ | if (time < lastlog ){ //time ist übergelaufen | ||
+ | lastlog = 0; | ||
+ | last_gas= 0; | ||
+ | last_wasser = 0; | ||
+ | } | ||
+ | wasser_max = max(wasser_max, | ||
+ | gas_max = max(gas_max, | ||
+ | loops++; | ||
+ | if ((wasser_max - 400) > wasser | ||
+ | { | ||
+ | wasser_z++; | ||
+ | } else { | ||
+ | wasser_z = 0; | ||
+ | } | ||
+ | |||
+ | if ((gas_max - 100) > gas ) | ||
+ | { | ||
+ | gas_z++; | ||
+ | } else { | ||
+ | gas_z = 0; | ||
+ | } | ||
+ | |||
+ | if (gas_z > 100 && time - last_gas > 500){ | ||
+ | gas_counter++; | ||
+ | gas_max= 0; | ||
+ | last_gas = time; | ||
+ | } | ||
+ | //Qn 2.5 =2500 Liter die Stunde = 60000 Markierungen am Raedchen 0,06 Sekunden (=60 ms für einen Durchgang) | ||
+ | if (wasser_z > 40 && time - last_wasser > 30){ | ||
+ | wasser_counter++; | ||
+ | wasser_max= 0; | ||
+ | last_wasser = time; | ||
+ | } | ||
+ | |||
+ | |||
+ | if (time - lastlog > 50){ | ||
+ | // Serial.print(" | ||
+ | lastlog = time; | ||
+ | long checksum = time + gas + gas_counter + wasser + wasser_counter; | ||
+ | |||
+ | Serial.print(time); | ||
+ | Serial.print(" | ||
+ | Serial.print(gas); | ||
+ | Serial.print(" | ||
+ | Serial.print(gas_counter); | ||
+ | Serial.print(" | ||
+ | Serial.print(wasser); | ||
+ | Serial.print(" | ||
+ | Serial.print(wasser_counter); | ||
+ | Serial.print(" | ||
+ | Serial.print(checksum); | ||
+ | Serial.print(" | ||
+ | Serial.print(gas_max); | ||
+ | Serial.print(" | ||
+ | Serial.print(wasser_max); | ||
+ | Serial.print(" | ||
+ | Serial.println(loops); | ||
+ | loops=0; | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === Script zur Datenübernahme === | ||
+ | |||
+ | Der Code auf der PC/Raspberry-Seite: | ||
+ | (Aufruf mit Cron regelmäßig, | ||
+ | |||
+ | <code perl> | ||
+ | # | ||
+ | # Set up the serial port | ||
+ | use Proc:: | ||
+ | die " | ||
+ | |||
+ | use DBI; | ||
+ | #use LWP:: | ||
+ | use Time::HiRes qw(usleep nanosleep time); | ||
+ | |||
+ | my $dbh2 = DBI-> | ||
+ | my $sth3 = $dbh2-> | ||
+ | #my $Gas_offset | ||
+ | #my $wasser_offset = | ||
+ | |||
+ | system(" | ||
+ | my $dbh = DBI-> | ||
+ | my $sth = $dbh-> | ||
+ | my $sth2 = $dbh-> | ||
+ | $sth2-> | ||
+ | |||
+ | #1014 | ||
+ | |||
+ | open(LOGGING, | ||
+ | open(SERIAL, | ||
+ | $time_offset = 0; | ||
+ | while (1) { | ||
+ | # Poll to see if any data is coming in | ||
+ | # | ||
+ | eval { | ||
+ | local $SIG{ALRM} = sub { die " | ||
+ | |||
+ | # alarm(x) muss in den eval()-Block | ||
+ | alarm(10); | ||
+ | $test = < | ||
+ | alarm(0); | ||
+ | |||
+ | }; ## end of eval | ||
+ | |||
+ | # Irgendetwas schiefgelaufen? | ||
+ | if ($@) { | ||
+ | print " | ||
+ | die(); | ||
+ | } | ||
+ | |||
+ | elsif (length($test)==0){ | ||
+ | print " | ||
+ | sleep 20; | ||
+ | die(); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | if ( $test =~ /([0-9]*) - ([0-9]*) - ([0-9]*) - ([0-9]*) - ([0-9]*) - ([0-9]*) - ([0-9]*) - ([0-9]*)/ && $1 + $2 + $3 + $4 + $5 == $6){ | ||
+ | $time = $1; | ||
+ | $time_offset2 = int(time * 1000) - $time; | ||
+ | if (abs($time_offset-$time_offset2) > | ||
+ | $time_offset = $time_offset2; | ||
+ | } | ||
+ | $gas = $2; | ||
+ | $gas_counter = $3; | ||
+ | $wasser = $4; | ||
+ | $wasser_counter = $5; | ||
+ | # | ||
+ | |||
+ | if ($wasser_counter > $wasser_counter_old){ | ||
+ | $sth3-> | ||
+ | |||
+ | } | ||
+ | $wasser_counter_old = $wasser_counter; | ||
+ | if ($gas_counter > $gas_counter_old){ | ||
+ | $sth3-> | ||
+ | |||
+ | } | ||
+ | $gas_counter_old = $gas_counter; | ||
+ | chop($test); | ||
+ | chop($test); | ||
+ | print LOGGING $test.gmtime()." | ||
+ | print $test.gmtime()." | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | < | ||
+ | Die Kanäle (channel_id) sind hart codiert: 12 und 9.</ | ||
+ | |||
+ | Was noch justiert werden muss, ist die Differenz, die zwischen Tal und Berg nötig ist: | ||
+ | |||
+ | <code php> | ||
+ | <?php | ||
+ | //include ("/ | ||
+ | //include ("/ | ||
+ | include ("/ | ||
+ | include ("/ | ||
+ | include ("/ | ||
+ | |||
+ | $graph = new Graph(3000, | ||
+ | $graph-> | ||
+ | |||
+ | // | ||
+ | // | ||
+ | $graph-> | ||
+ | $graph-> | ||
+ | # | ||
+ | // | ||
+ | $graph-> | ||
+ | $graph-> | ||
+ | $graph-> | ||
+ | $graph-> | ||
+ | $graph-> | ||
+ | |||
+ | |||
+ | $connection = mysql_connect(" | ||
+ | $db_selected = mysql_select_db(" | ||
+ | if (!$connection) | ||
+ | { | ||
+ | die(' | ||
+ | } | ||
+ | if (!$db_selected) | ||
+ | { | ||
+ | die(' | ||
+ | } | ||
+ | $query = " | ||
+ | $result = mysql_query($query); | ||
+ | $i=0; | ||
+ | while ($row = @mysql_fetch_assoc($result)) | ||
+ | { | ||
+ | $ywert[$i] = $row[' | ||
+ | |||
+ | $stunden[$i] = $row[' | ||
+ | $i +=1; | ||
+ | } | ||
+ | |||
+ | $lineplot=new LinePlot($ywert, | ||
+ | $lineplot-> | ||
+ | |||
+ | $graph-> | ||
+ | $graph-> | ||
+ | |||
+ | ?> | ||
+ | |||
+ | </ | ||
+ | |||
+ | So sieht so eine Grafik aus: | ||
+ | |||
+ | {{: | ||
+ | {{: | ||
+ | |||
+ | <note tip>Oder den " | ||
+ | |||
+ | ==== Über vzlogger an die Middleware ==== | ||
+ | |||
+ | Für **nur einen** Wasserzähler, | ||
+ | |||
+ | === Arduino === | ||
+ | |||
+ | Hier der Code für den Arduino. Verkürzte Version von oben, weil nur eine Diode ausgewertet wird und die Impulse im Arduino nicht gezählt werden. | ||
+ | |||
+ | <code c> | ||
+ | |||
+ | // Original von mikemiller 2015-2016 | ||
+ | // Reduziert auf nur 1 Wasserzähler mit Ausgabe | ||
+ | // des Impulses auf die USB-Schnittstelle | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(300); | ||
+ | // Open serial communications and wait for port to open: | ||
+ | // A baud rate of 115200 is used instead of 9600 for a faster data rate | ||
+ | // on non-native USB ports | ||
+ | // | ||
+ | while (!Serial) { | ||
+ | ; // wait for serial port to connect. Needed for native USB port only | ||
+ | } | ||
+ | |||
+ | // | ||
+ | pinMode(A0, INPUT); | ||
+ | digitalWrite(A1, | ||
+ | } | ||
+ | int wasser_max = 0; | ||
+ | long wasser = 0; | ||
+ | int wasser_z = 0; | ||
+ | unsigned long lastlog = 0; | ||
+ | unsigned long last_wasser = 0; | ||
+ | unsigned long time; | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | // Gleitender Durchschnitt anwenden. | ||
+ | wasser = ((wasser *3) + analogRead(0))/ | ||
+ | time = millis(); | ||
+ | if (time < lastlog ){ //time ist übergelaufen | ||
+ | lastlog = 0; | ||
+ | last_wasser = 0; | ||
+ | } | ||
+ | wasser_max = max(wasser_max, | ||
+ | |||
+ | if ((wasser_max - 200) > wasser) | ||
+ | { | ||
+ | wasser_z++; | ||
+ | } else { | ||
+ | wasser_z = 0; | ||
+ | } | ||
+ | |||
+ | // Qn 2,5 m³/h = 2.500 Liter pro Stunde | ||
+ | // Das Raedchen hat 6 Fluegel und dreht sich 1x je 0,1 Liter --> 60 Impulse je Liter | ||
+ | // Bei Maximaldurchfluss 2.500 l/h * 60 Imp/l = 2.500*60 Imp/h = 2.500/60 Imp/s = 41,7 Imp/s | ||
+ | // --> Mindestens 24 ms zwischen zwei Impulsen (" | ||
+ | |||
+ | if (wasser_z > 40 && time - last_wasser > 30) { | ||
+ | wasser_max= 0; | ||
+ | lastlog = time; | ||
+ | last_wasser = time; | ||
+ | Serial.print(0x00); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | Die Differenz zwischen Hell und Dunkel muss für dieses Code-Beispiel mindestens 200 betragen, sonst wird kein Impuls erzeugt. | ||
+ | |||
+ | === Frontend === | ||
+ | |||
+ | Kanal erstellen als Wassermengenzähler mit einer Auflösung von 60 (Impulse/l, siehe Berechnung im Code) und Stil=steps. UUID notieren. | ||
+ | |||
+ | === Beispielkonfiguration === | ||
+ | Exemplarische / | ||
+ | <code base vzlogger.conf> | ||
+ | { | ||
+ | // Water as S0 meter | ||
+ | |||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | |||
+ | " | ||
+ | " | ||
+ | |||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | // " | ||
+ | // " | ||
+ | // " | ||
+ | " | ||
+ | } | ||
+ | } // meter | ||
+ | </ | ||
+ | |||
+ | ===== Ansatz 3: grüne LED und Fototransistor ===== | ||
+ | |||
+ | Im [[https:// | ||
+ | |||
+ | Beim Nachbau hat es sich gezeigt, dass es u.a. auf die Helligkeit der verwendeten LED ankommt. Die zuerst beschafft LED war nicht hell genug, um den Fototransistor selbst bei direkter Belichtung durchzusteuern. Mit der nachbeschafften Nichia NSPG300D gelang der Betrieb dann auf Anhieb. | ||
+ | |||
+ | Wie in der Original-Anleitung beschrieben, | ||
+ | |||
+ | Dieser Impulsgenerator ließ sich dann einfach aufbauen und funktioniert in der Tat viel besser als die einfache Schaltung. Ob das an der Verwendung eines Mikrocontrollers oder an dem mit Linse fokussierten Lichtstrahl der LED liegt, ist unklar. Die Montage auf dem Wasserzähler und die Justage war jedenfalls in wenigen Minuten erledigt. Zum Schutz von Fremdlicht habe ich ein HT-Rohr mit Deckel über den Wasserzähler gestülpt. | ||
+ | |||
+ | Nach Lektüre des Artikels über [[: | ||
+ | - Einen USB-to-Serial-Adapter mit extra herausgeführtem Vcc-Pin aus der Schublade geholt | ||
+ | - diesen gleich zur Spannungsversorgung des STALL-Impulsgebers verwendet | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Die Idee ist wie bei der Schaltung aus [[: | ||
+ | |||
+ | < | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }] | ||
+ | } | ||
+ | ]} | ||
+ | </ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | So besonders gut scheint die Middleware mit den groben Impulsen (1 Impuls pro Liter) und dem oft stundenlangen Ruhen des Messwertes nicht klarzukommen; | ||
+ | |||
+ | {{: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | ===== Ansatz 4: 3D Druck Optik und OPT101 ===== | ||
+ | Ich hatte den Laser-Ansatz für Jahre in Gebrauch. Abgesehen von den Sicherheitsproblemen hatte ich nach ein paar Jahren Algen im Wasserzähler. | ||
+ | Daher die Idee auch mit grüner LED zu arbeiten. Da 3D-Drucker vorhanden habe ich eine Halterung für eine Linse entworfen, deren Fokuspunkt direkt auf dem Rad liegt. | ||
+ | https:// | ||
+ | Impulse werden mit einem OPT101 Chip (intgrierter Verstärker) abgenommen. | ||
+ | {{: |
hardware/channels/meters/water/wasserzaehler_ohne_s0.1561011142.txt.gz · Zuletzt geändert: 2019/06/20 08:12 von gabinvigoss_gmail.com