Dies ist eine alte Version des Dokuments!
Idee: Das kleine Sternrad des Wasserzählers mit einem Laser anvisieren.
Den Laser gibt es im Zehnerpack bei Ebay ab 2,50: http://www.ebay.de/sch/i.html?_odkw=laser+10+st%C3%BCck&_osacat=0&_from=R40&_trksid=p2045573.m570.l1313.TR0.TRC0.H0.Xlaser+10+st%C3%BCck+5mW+Dioden.TRS0&_nkw=laser+10+st%C3%BCck+5mW+Dioden&_sacat=0
Das ganze habe ich mit einer BPW34 http://www.vishay.com/docs/81521/bpw34.pdf Photodiode gekoppelt. Als Schaltung habe ich das hier gewählt:
https://www.mikrocontroller.net/articles/Lichtsensor_/_Helligkeitssensor#Konstantstromquelle_mit_Arbeitswiderstand (Konstantstromquelle mit Arbeitswiderstand)
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://www.vishay.com/docs/83760/tcrt5000.pdf
Beide Zähler gehen an einen Analog in eines Arduino V3 (Ebay, deutlich unter 10 Euro) http://www.ebay.de/sch/i.html?_odkw=nano+arduino&_osacat=0&_from=R40&_trksid=p2045573.m570.l1313.TR10.TRC1.A0.H0.Xnano+arduino+v3.TRS0&_nkw=nano+arduino+v3&_sacat=0
Das ist der Code auf dem Arduino. Die Idee ist die Differenz zwischen dem Tal und dem Berg bei dem analogen Sensort als Trigger zu verwenden
//sets ground pin to LOW and input pin to HIGH void setup() { Serial.begin(38400); //digitalWrite(A0, HIGH); digitalWrite(A1, HIGH); } long wasser_counter = 0; long gas_counter = 0; int wasser_max = 0; int gas_max = 0; int wasser = 0; int gas = 0; int wasser_z = 0; int gas_z = 0; unsigned long lastlog = 0; unsigned long time; void loop() { int gas = analogRead(1); int wasser = analogRead(0); wasser_max = max(wasser_max, wasser ); gas_max = max(gas_max, gas ); if ((wasser_max - 400) > wasser ) { wasser_z++; } else { wasser_z = 0; } if ((gas_max - 110) > gas ) { gas_z++; } else { gas_z = 0; } if (gas_z > 100){ gas_counter++; gas_max= 0; } if (wasser_z > 100){ wasser_counter++; wasser_max= 0; } time = millis(); if (time - lastlog > 1000){ // Serial.print("Time: "); 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.println(wasser_max); } }
Der Code auf der PC/Raspberry-Seite:
#!/usr/bin/perl # Set up the serial port use DBI; #use LWP::UserAgent; use Time::HiRes qw(usleep nanosleep time); my $dbh2 = DBI->connect("DBI:mysql:database=volkszaehler;", "vz", "GEHEIM" ) or die $DBI::errstr; my $sth3 = $dbh2->prepare("INSERT INTO `data` (`channel_id`, `timestamp`, `value`) VALUES (?, ?, ?)"); #my $Gas_offset = $dbh2->selectrow_array('SELECT count(*) FROM table WHERE...', undef, @params); #my $wasser_offset = system("stty -F /dev/usb-arduino_nano 1:4:cbf:a30:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"); my $dbh = DBI->connect("DBI:mysql:database=test2;", "test2", "NOCHGEHEIMER" ) or die $DBI::errstr; my $sth = $dbh->prepare("INSERT INTO `test`(`timestamp`, `wert`, wert2 ) VALUES (?,?, ?)"); my $sth2 = $dbh->prepare("delete from `test`"); $sth2->execute(); #1014 open(LOGGING, ">>", "/tmp/logging.txt") ; open(SERIAL, "</dev/usb-arduino_nano"); while (1) { # Poll to see if any data is coming in #https://groups.google.com/forum/#!topic/comp.lang.perl.misc/cZwsvIla1cM eval { local $SIG{ALRM} = sub { die "Zeitlimit überschritten $!"}; # alarm(x) muss in den eval()-Block alarm(10); # Maximale Zeit: 9 bis 10 Sekunden $test = <SERIAL>; # Kritische Operation alarm(0); # alarm zurücksetzen }; ## end of eval # Irgendetwas schiefgelaufen? if ($@) { print "timeout\n"; die(); } elsif (length($test)==0){ print "länge 0\n"; 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){ $gas = $2; $gas_counter = $3; $wasser = $4; $wasser_counter = $5; $sth->execute ($1,$gas, $wasser); if ($wasser_counter > $wasser_counter_old){ $sth3->execute (12,int(time * 1000), $wasser_counter - $wasser_counter_old); } $wasser_counter_old = $wasser_counter; if ($gas_counter > $gas_counter_old){ $sth3->execute (9,int(time2rSCju5dKmVCPx7x * 1000), $gas_counter - $gas_counter_old); } $gas_counter_old = $gas_counter; chop($test); chop($test); print LOGGING $test.`date`; print $test.`date`; } }
Was noch justiert werden muss, ist die Differenz, die zwischen Tal und Berg nötig ist:
<?php //include ("/usr/share/jpgraph/jpgraph.php"); //include ("/usr/share/jpgraph/jpgraph_line.php"); include ("/var/www/z/graph/src/jpgraph.php"); include ("/var/www/z/graph/src/jpgraph_line.php"); include ("/var/www/z/graph/src/jpgraph_date.php"); $graph = new Graph(3000,500); $graph->img->SetMargin(40,40,40,40); //$graph->SetScale("textlin"); //$graph->SetScale('intlin',0,50,0,24); $graph->legend->SetColumns(1); $graph->legend->SetPos(0.05,0.5,'right','center'); #$graph->yaxis->scale->ticks->Set(45,50); //$graph->SetShadow(); $graph->title->Set("Gaskurve"); $graph->title->SetFont(FF_FONT1,FS_BOLD); $graph->SetScale('datlin'); $graph->xaxis->SetLabelAngle(90); $graph->xaxis->scale->SetDateFormat('H:i:s'); $connection = mysql_connect("localhost", "test2", "GEHEIMER"); $db_selected = mysql_select_db("test2"); if (!$connection) { die('Not connected : ' . mysql_error()); } if (!$db_selected) { die('Can\'t use db : ' . mysql_error()); } $query = "SELECT *, UNIX_TIMESTAMP(datum) zeitunix FROM `test` where datum > '".$_GET["a"]."' "; $result = mysql_query($query); $i=0; while ($row = @mysql_fetch_assoc($result)) { $ywert[$i] = $row['wert2']; $stunden[$i] = $row['zeitunix']; $i +=1; } $lineplot=new LinePlot($ywert, $stunden ); $lineplot->SetLegend ("Wert"); $graph->Add($lineplot); $graph->Stroke(); ?>
So sieht so eine Grafik aus: