Benutzer-Werkzeuge

Webseiten-Werkzeuge


hardware:channels:meters:water:wasserzaehler_ohne_s0

Idee: Das kleine Sternrad des Wasserzählers mit einem Laser anvisieren.

Ein roter Laser mit einer Strahlungsleistung von 5mW entspricht der Laserklasse 3R. Die zugängliche Laserstrahlung liegt im Wellenlängenbereich von 302,5 nm bis 10^6 nm und ist gefährlich für das Auge.
Sicherheitsmaßnahmen:
Niemals direkt in den Strahlengang blicken.
Im Laserbereich sind gut reflektierende Flächen zu vermeiden.
Vorgeschriebene Laserschutzbrillen unbedingt tragen.


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 Die Reflexlichtschranke ist auf einen Einkaufswagenchip geklebt. Dieser ist mit Wiederlösbares Montageband (Aldi, bzw. 3M) auf den Gaszähler geklebt.

Externer Link

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;
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))/4;
	time = millis();
        if (time < lastlog ){ //time ist übergelaufen
          lastlog = 0;
          last_gas= 0;
          last_wasser = 0;
        }
	wasser_max = max(wasser_max, wasser );
	gas_max = max(gas_max, gas );
	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("Time: ");
		lastlog = time;
		long checksum = time + gas + gas_counter + wasser + wasser_counter;
 
		use Proc::PID::File;
  die "Already running!" if Proc::PID::File->running();
 
		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;
 
	}
 
}

Der Code auf der PC/Raspberry-Seite: (Aufruf mit Cron regelmäßig, falls etwas abbricht. Job startet sich nur einmal, falls er noch läuft)

#!/usr/bin/perl
# Set up the serial port
use Proc::PID::File;
  die "Already running!" if Proc::PID::File->running();
 
use DBI;
#use LWP::UserAgent;
use Time::HiRes qw(usleep nanosleep time);
 
my $dbh2 = DBI->connect("DBI:mysql:database=volkszaehler;", "vz", "dfdfdfdf" ) 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", "dfdfdfdfdf" ) or die $DBI::errstr;
my $sth = $dbh->prepare("INSERT INTO `test`(`timestamp`, `wert`, wert2 ) VALUES (?,?, ?)");
my $sth2 = $dbh->prepare("delete from  `test`") ;
$sth2->execute() or die "Couldn't execute statement: " . $sth2->errstr;
 
#1014
 
open(LOGGING, ">>", "/tmp/logging.txt") ;
open(SERIAL, "</dev/usb-arduino_nano");
$time_offset = 0;
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){
		$time = $1;
		$time_offset2 =  int(time * 1000) - $time;
		if (abs($time_offset-$time_offset2) >=5000){
		$time_offset =  $time_offset2;
		}
		$gas = $2;
		$gas_counter = $3;
		$wasser = $4;
		$wasser_counter = $5;
#		$sth->execute ($1,$gas, $wasser);
 
		if ($wasser_counter > $wasser_counter_old){
			$sth3->execute (12,$time_offset + $time, $wasser_counter - $wasser_counter_old) or die "Couldn't execute statement: " . $sth3->errstr;
 
		}
		$wasser_counter_old = $wasser_counter;
		if ($gas_counter > $gas_counter_old){
			$sth3->execute (9,$time_offset + $time, $gas_counter - $gas_counter_old) or die "Couldn't execute statement: " . $sth3->errstr;
 
		}
		$gas_counter_old = $gas_counter;
		chop($test);
		chop($test);
		print LOGGING $test.gmtime()."\n";
		print $test.gmtime()."\n";
	}
 
 
 
}

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:

gas.png

hardware/channels/meters/water/wasserzaehler_ohne_s0.txt · Zuletzt geändert: 2016/01/08 20:33 von mikemiller