hardware:channels:meters:water:wasserzaehler_ohne_s0
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende Überarbeitung | Nächste ÜberarbeitungBeide Seiten der Revision | ||
hardware:channels:meters:water:wasserzaehler_ohne_s0 [2019/06/20 08:12] – gabinvigoss_gmail.com | hardware:channels:meters:water:wasserzaehler_ohne_s0 [2019/06/22 13:02] – alte Version wiederhergestellt (2019/06/02 16:55) justinotherguy | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== | + | ====== |
- | ===== Le pointeur laser pour la pratique | + | ===== Ansatz 1: Laser ===== |
- | Avez-vous besoin du **pointeur laser (https:// | + | Idee: Das kleine Sternrad des Wasserzählers mit einem Laser anvisieren und die Reflexionen mit Photodiode und Arduino-Mikrocontroller auswerten. |
- | 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é des piles supplémentaires, | + | ==== Hardware ==== |
- | Il n'y a aucun moyen d' | + | <note important> |
+ | \\ | ||
- | 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'il s'agit d'utiliser une arme à feu pour se défendre. J'en ai eu une pour mes deux armes de poing et je les utilise au moins une fois par mois entre le temps de passage et les matchs IDPA. Néanmoins, il est plus que précis pour la pratique du dessin contre le Mutant Zombie Biker portant votre pardessus debout dans votre placard à deux pas ou les Walkers qui ont soudainement éclaté devant votre porte et vous avez besoin de dessiner et de viser votre cible. feu "Je les ai également utilisées pour montrer à un nouveau tireur les rudiments | + | {{:hardware: |
+ | |||
+ | 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 | ||
+ | |||
+ | < | ||
+ | |||
+ | //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; | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Script zur Datenübernahme === | ||
+ | |||
+ | Der Code auf der PC/ | ||
+ | (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('Can\'t use db : ' . mysql_error()); | ||
+ | } | ||
+ | $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 2: 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 [[: | ||
+ | |||
+ | < | ||
+ | "meters" | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }] | ||
+ | } | ||
+ | ]} | ||
+ | </ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | So besonders gut scheint die Middleware mit den groben Impulsen (1 Impuls pro Liter) und dem oft stundenlangen Ruhen des Messwertes nicht klarzukommen; | ||
+ | |||
+ | {{: | ||
+ | |||
+ | {{: | ||
- | Le laser est décentré d' | ||
- | //Les modules laser habituels sont disponibles avec une longueur d'onde différente: |
hardware/channels/meters/water/wasserzaehler_ohne_s0.txt · Zuletzt geändert: 2021/01/25 21:48 von jau