mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +00:00
52_I2C_MCP342x.pm: Initial release
00_RPII2C.pm: modification for 52_I2C_MCP342x.pm module git-svn-id: https://svn.fhem.de/fhem/trunk@7172 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
dee8c77aa4
commit
4baa1c8c24
@ -1,5 +1,6 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- feature: new module 52_I2C_MCP342x.pm added (klausw)
|
||||
- feature: SYSMON: read cpu temp on FritzBox
|
||||
- feature: ios7smallscreenstyle.css: table width based on screen width, new
|
||||
header, links colored in detail view
|
||||
|
@ -13,7 +13,7 @@ my @clients = qw(
|
||||
I2C_LCD
|
||||
I2C_DS1307
|
||||
I2C_PC.*
|
||||
I2C_MCP23017
|
||||
I2C_MCP.*
|
||||
I2C_BMP180
|
||||
I2C_SHT21
|
||||
I2C_TSL2561
|
||||
@ -172,7 +172,7 @@ sub RPII2C_Set($@) { #writeBlock noch nicht fertig
|
||||
my ($hash, @a) = @_;
|
||||
my $name = shift @a;
|
||||
my $type = shift @a;
|
||||
my @sets = ('writeByte', 'writeByteReg', 'writeBlock'); #, 'writeNBlock');
|
||||
my @sets = ('writeByte', 'writeByteReg', 'writeBlock', 'writeBlockReg'); #, 'writeNBlock');
|
||||
return "Unknown argument $type, choose one of " . join(" ", @sets) if @a < 2;
|
||||
|
||||
foreach (@a) { #Hexwerte pruefen und in Dezimalwerte wandeln
|
||||
@ -182,7 +182,7 @@ sub RPII2C_Set($@) { #writeBlock noch nicht fertig
|
||||
my $i2ca = shift @a;
|
||||
return "$name: I2C Address not valid" unless ($i2ca > 3 && $i2ca < 128); #pruefe auf Hexzahl zwischen 4 und 7F
|
||||
|
||||
my $i2chash = { i2caddress => $i2ca, direction => "i2cwrite" };
|
||||
my $i2chash = { i2caddress => $i2ca, direction => "i2cbytewrite", test => "local" };
|
||||
my ($reg, $nbyte, $data) = undef;
|
||||
if ($type eq "writeByte") {
|
||||
$data = join(" ", @a);
|
||||
@ -190,21 +190,17 @@ sub RPII2C_Set($@) { #writeBlock noch nicht fertig
|
||||
$reg = shift @a;
|
||||
$data = join(" ", @a);
|
||||
} elsif ($type eq "writeBlock") {
|
||||
$nbyte = int(@a);
|
||||
return "$name maximal blocksize (32byte) exeeded" if $nbyte > 32;
|
||||
$data = join(" ", @a);
|
||||
$i2chash->{direction} = "i2cwrite";
|
||||
} elsif ($type eq "writeBlockReg") {
|
||||
$reg = shift @a;
|
||||
$nbyte = int(@a);
|
||||
return "$name maximal blocksize (32byte) exeeded" if $nbyte > 32;
|
||||
$data = join(" ", @a);
|
||||
$i2chash->{direction} = "i2cblockwrite";
|
||||
#####kommt weg da sinnlos??!!! Achtung $nbyte stimmt derzeit nicht
|
||||
# } elsif ($type eq "writeNBlock") {
|
||||
# $reg = shift @a;
|
||||
# return "$name register address must be a hexvalue" if (!defined($reg) || $reg !~ /^(0x|)[0-9A-F]{1,4}$/xi);
|
||||
# $nbyte = shift @a;
|
||||
# return "$name number of bytes must be decimal value" if (!defined($nbyte) || $nbyte !~ /^[0-9]{1,2}$/);
|
||||
# return "$name data values must be n times number of bytes" if (int(@a) % $nbyte != 0);
|
||||
# $data = join(" ", @a);
|
||||
#########################################################################
|
||||
}else {
|
||||
$i2chash->{direction} = "i2cwrite";
|
||||
} else {
|
||||
return "Unknown argument $type, choose one of " . join(" ", @sets);
|
||||
}
|
||||
|
||||
@ -215,12 +211,12 @@ sub RPII2C_Set($@) { #writeBlock noch nicht fertig
|
||||
undef $i2chash; #Hash loeschen
|
||||
return undef;
|
||||
}
|
||||
##################################### fertig?
|
||||
##################################### nicht fertig!
|
||||
sub RPII2C_Get($@) { #
|
||||
my ($hash, @a) = @_;
|
||||
my $nargs = int(@a);
|
||||
my $name = $hash->{NAME};
|
||||
my @gets = ('read');
|
||||
my @gets = ('read','readblock','readblockreg');
|
||||
unless ( exists($a[1]) && $a[1] ne "?" && grep {/^$a[1]$/} @gets ) {
|
||||
return "Unknown argument $a[1], choose one of " . join(" ", @gets);
|
||||
}
|
||||
@ -229,7 +225,7 @@ sub RPII2C_Get($@) { #
|
||||
return "$name: I2C Address not valid" unless ( $a[2] =~ /^(0x|)([0-7]|)[0-9A-F]$/xi);
|
||||
return "$name register address must be a hexvalue" if (defined($a[3]) && $a[3] !~ /^(0x|)[0-9A-F]{1,4}$/xi);
|
||||
return "$name number of bytes must be decimal value" if (defined($a[4]) && $a[4] !~ /^[0-9]{1,2}$/);
|
||||
my $i2chash = { i2caddress => hex($a[2]), direction => "i2cread" };
|
||||
my $i2chash = { i2caddress => hex($a[2]), direction => "i2cbyteread" };
|
||||
$i2chash->{reg} = hex($a[3]) if defined($a[3]); #startadresse zum lesen
|
||||
$i2chash->{nbyte} = $a[4] if defined($a[4]);
|
||||
#Log3 $hash, 1, "Reg: ". $i2chash->{reg};
|
||||
@ -239,7 +235,29 @@ sub RPII2C_Get($@) { #
|
||||
my $received = $i2chash->{received}; #als Scalar
|
||||
undef $i2chash; #Hash loeschen
|
||||
return (defined($received) ? "received : " . $received ." | " : "" ) . " transmission: $status";
|
||||
}
|
||||
} elsif ($a[1] eq "readblock") {
|
||||
return "use: \"get $name $a[1] <i2cAddress> [<Number od bytes to get>]\"" if(@a < 3);
|
||||
return "$name: I2C Address not valid" unless ( $a[2] =~ /^(0x|)([0-7]|)[0-9A-F]$/xi);
|
||||
return "$name number of bytes must be decimal value" if (defined($a[3]) && $a[3] !~ /^[0-9]{1,2}$/);
|
||||
my $i2chash = { i2caddress => hex($a[2]), direction => "i2cread" };
|
||||
$i2chash->{nbyte} = $a[3] if defined($a[3]);
|
||||
my $status = &{$hash->{hwfn}}($hash, $i2chash);
|
||||
my $received = $i2chash->{received}; #als Scalar
|
||||
undef $i2chash; #Hash loeschen
|
||||
return (defined($received) ? "received : " . $received ." | " : "" ) . " transmission: $status";
|
||||
} elsif ($a[1] eq "readblockreg") {
|
||||
return "use: \"get $name $a[1] <i2cAddress> [<Number od bytes to get>]\"" if(@a < 2);
|
||||
return "$name: I2C Address not valid" unless ( $a[2] =~ /^(0x|)([0-7]|)[0-9A-F]$/xi);
|
||||
return "$name register address must be a hexvalue" if (defined($a[3]) && $a[3] !~ /^(0x|)[0-9A-F]{1,4}$/xi);
|
||||
return "$name number of bytes must be decimal value" if (defined($a[4]) && $a[4] !~ /^[0-9]{1,2}$/);
|
||||
my $i2chash = { i2caddress => hex($a[2]), direction => "i2cread" };
|
||||
$i2chash->{reg} = hex($a[3]) if defined($a[3]);
|
||||
$i2chash->{nbyte} = $a[4] if defined($a[4]);
|
||||
my $status = &{$hash->{hwfn}}($hash, $i2chash);
|
||||
my $received = $i2chash->{received}; #als Scalar
|
||||
undef $i2chash; #Hash loeschen
|
||||
return (defined($received) ? "received : " . $received ." | " : "" ) . " transmission: $status";
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
#####################################
|
||||
@ -262,7 +280,7 @@ sub RPII2C_Write($$) { #wird vom Client aufgerufen
|
||||
&& defined( $main::defs{$d}{I2C_Address} ) && defined($clientmsg->{i2caddress})
|
||||
&& $main::defs{$d}{I2C_Address} eq $clientmsg->{i2caddress} ) {
|
||||
my $chash = $main::defs{$d};
|
||||
Log3 $hash, 5, "$name ->Client gefunden: $d". ($main::defs{$d}{I2C_Address} ? ", I2Caddress: $main::defs{$d}{I2C_Address}":"") . ($clientmsg->{data} ? " Data: $clientmsg->{data}" : "");
|
||||
Log3 $hash, 5, "$name ->Client gefunden: $d". ($main::defs{$d}{I2C_Address} ? ", I2Caddress: $main::defs{$d}{I2C_Address}":"") . ($clientmsg->{data} ? " Data: $clientmsg->{data}" : "") . ($clientmsg->{received} ? " Gelesen: $clientmsg->{received}" : "");
|
||||
CallFn($d, "I2CRecFn", $chash, $clientmsg);
|
||||
undef $clientmsg #Hash loeschen nachdem Daten verteilt wurden
|
||||
}
|
||||
@ -347,25 +365,16 @@ sub RPII2C_HWACCESS($$) {
|
||||
I2CBusDevicePath => $hash->{DeviceName},
|
||||
I2CDeviceAddress => hex( sprintf("%.2X", $clientmsg->{i2caddress}) ),
|
||||
);
|
||||
if (defined($clientmsg->{nbyte}) && defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cblockwrite") { #Registerblock beschreiben
|
||||
# if (defined($clientmsg->{nbyte}) && defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cblockwrite") { #blockweise beschreiben (Register)
|
||||
if ( defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #blockweise beschreiben (Register)
|
||||
my @data = split(" ", $clientmsg->{data});
|
||||
my $dataref = \@data;
|
||||
$inh = $dev->writeBlockData( $clientmsg->{reg} , $dataref );
|
||||
my $wr = join(" ", @{$dataref});
|
||||
Log3 $hash, 5, "$hash->{NAME}: Block schreiben Register: " . sprintf("0x%.2X", $clientmsg->{reg}) . " Inhalt: " . $wr . " N: ". int(@data) ." Returnvar.: $inh";
|
||||
$status = "Ok" if $inh == 0;
|
||||
#kommt wieder weg#################
|
||||
# } elsif (defined($clientmsg->{nbyte}) && defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #Registerbereich (mehrfach) beschreiben
|
||||
# my @data = split(" ", $clientmsg->{data});
|
||||
# foreach (0..$#data) {
|
||||
# my $i = $_ -( int($_ / $clientmsg->{nbyte}) * $clientmsg->{nbyte} );
|
||||
# $inh = $dev->writeByteData( ($clientmsg->{reg} + $i ) ,$data[$_]);
|
||||
# Log3 $hash, 5, "$hash->{NAME} NReg schreiben; Reg: " . ($clientmsg->{reg} + $i) . " Inh: " . $data[$_] . " Returnvar.: $inh";
|
||||
# last if $inh != 0;
|
||||
# $status = "Ok" if $inh == 0;
|
||||
# }
|
||||
#hier Mehrfachbeschreibung eines Registers noch entfernen und dafuer Bereich mit Registeroperationen beschreiben
|
||||
} elsif (defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #Register beschreiben
|
||||
# } elsif (defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #byteweise beschreiben (Register)
|
||||
} elsif (defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cbytewrite") { #byteweise beschreiben (Register)
|
||||
my @data = split(" ", $clientmsg->{data});
|
||||
foreach (@data) {
|
||||
$inh = $dev->writeByteData($clientmsg->{reg},$_);
|
||||
@ -373,7 +382,7 @@ sub RPII2C_HWACCESS($$) {
|
||||
last if $inh != 0;
|
||||
$status = "Ok" if $inh == 0;
|
||||
}
|
||||
} elsif (defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #Byte(s) schreiben
|
||||
} elsif (defined($clientmsg->{data}) && ( $clientmsg->{direction} eq "i2cwrite" || $clientmsg->{direction} eq "i2cbytewrite" ) ) { #Byte(s) schreiben
|
||||
my @data = split(" ", $clientmsg->{data});
|
||||
foreach (@data) {
|
||||
$inh = $dev->writeByte($_);
|
||||
@ -381,7 +390,7 @@ sub RPII2C_HWACCESS($$) {
|
||||
last if $inh != 0;
|
||||
$status = "Ok" if $inh == 0;
|
||||
}
|
||||
} elsif (defined($clientmsg->{reg}) && $clientmsg->{direction} eq "i2cread") { #Register lesen
|
||||
} elsif (defined($clientmsg->{reg}) && ( $clientmsg->{direction} eq "i2cread" || $clientmsg->{direction} eq "i2cbyteread" ) ) { #byteweise lesen (Register)
|
||||
my $nbyte = defined($clientmsg->{nbyte}) ? $clientmsg->{nbyte} : 1;
|
||||
my $rmsg = "";
|
||||
for (my $n = 0; $n < $nbyte; $n++) {
|
||||
@ -395,7 +404,7 @@ sub RPII2C_HWACCESS($$) {
|
||||
}
|
||||
#@{$clientmsg->{received}} = split(" ", $rmsg) if($rmsg); #Daten als Array uebertragen
|
||||
$clientmsg->{received} = $rmsg if($rmsg); #Daten als Scalar uebertragen
|
||||
} elsif ($clientmsg->{direction} eq "i2cread") { #Byte lesen #Byte lesen
|
||||
} elsif ($clientmsg->{direction} eq "i2cread"|| $clientmsg->{direction} eq "i2cbyteread") { #Byte lesen
|
||||
my $nbyte = defined($clientmsg->{nbyte}) ? $clientmsg->{nbyte} : 1;
|
||||
my $rmsg = "";
|
||||
for (my $n = 0; $n < $nbyte; $n++) {
|
||||
@ -425,43 +434,46 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
my $ankommen = "$hash->{NAME}: vom client empfangen";
|
||||
foreach my $av (keys %{$clientmsg}) { $ankommen .= "|" . $av . ": " . $clientmsg->{$av}; }
|
||||
Log3 $hash, 5, $ankommen;
|
||||
#Log3 $hash, 1, $ankommen if $clientmsg->{test} eq "local";
|
||||
|
||||
my $i2caddr = hex(sprintf "%x", $clientmsg->{i2caddress});
|
||||
if ( sysopen(my $fh, $hash->{DeviceName}, O_RDWR) != 1) { #Datei oeffnen
|
||||
if ( sysopen(my $fh, $hash->{DeviceName}, O_RDWR) != 1) { #Datei oeffnen
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess sysopen failure: $!"
|
||||
} elsif( not defined( ioctl($fh,$I2C_SLAVE,$i2caddr) ) ) { #I2C Adresse per ioctl setzen
|
||||
} elsif( not defined( ioctl($fh,$I2C_SLAVE,$i2caddr) ) ) { #I2C Adresse per ioctl setzen
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess (0x".unpack( "H2",pack "C", $clientmsg->{i2caddress}).") ioctl failure: $!"
|
||||
} elsif (defined($clientmsg->{nbyte}) && defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cblockwrite") { #Registerblock beschreiben
|
||||
my $data = chr($clientmsg->{reg});
|
||||
# } elsif (defined($clientmsg->{nbyte}) && defined($clientmsg->{reg}) && defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cblockwrite") { #blockweise schreiben
|
||||
} elsif ( defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #blockweise schreiben
|
||||
my $data = defined($clientmsg->{reg}) ? chr($clientmsg->{reg}) : undef;
|
||||
foreach (split(" ", $clientmsg->{data})) {
|
||||
$data .= chr($_);
|
||||
}
|
||||
my $retval = syswrite($fh, $data, length($data));
|
||||
unless (defined($retval) && $retval == length($data)) {
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess blockweise nach 0x".unpack( "H2",pack "C", $clientmsg->{i2caddress})." schreiben, Reg: 0x". unpack( "H2",pack "C", $clientmsg->{reg}) . " Inh: $clientmsg->{data}, laenge: ".length($data)."| -> syswrite failure: $!";
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess blockweise nach 0x".unpack( "H2",pack "C", $clientmsg->{i2caddress})." schreiben, " . (defined($clientmsg->{reg}) ? "Reg: 0x". unpack( "H2",pack "C", $clientmsg->{reg}) : "") . " Inh: $clientmsg->{data}, laenge: ".length($data)."| -> syswrite failure: $!";
|
||||
} else {
|
||||
$status = "Ok";
|
||||
Log3 $hash, 5, "$hash->{NAME}: HWaccess block schreiben, Reg: 0x". unpack( "H2",pack "C", $clientmsg->{reg}) . " Inh(dec):|$clientmsg->{data}|, laenge: |".length($data)."|";
|
||||
Log3 $hash, 5, "$hash->{NAME}: HWaccess block schreiben, " . (defined($clientmsg->{reg}) ? "Reg: 0x". unpack( "H2",pack "C", $clientmsg->{reg}) : "") . " Inh(dec):|$clientmsg->{data}|, laenge: |".length($data)."|";
|
||||
}
|
||||
#(my $datah = $data) =~ s/(.|\n)/sprintf("%.2X ",ord($1))/eg;
|
||||
#Log3 $hash, 1, "$hash->{NAME}: HWaccess block schreiben data:|$clientmsg->{data}|, laenge: |".length($data)."|";
|
||||
#$status = "Ok" if $resulw == length($data);
|
||||
|
||||
} elsif (defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #byteweise beschreiben
|
||||
my $reg = undef;
|
||||
# } elsif (defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cwrite") { #byteweise schreiben
|
||||
} elsif (defined($clientmsg->{data}) && $clientmsg->{direction} eq "i2cbytewrite") { #byteweise schreiben
|
||||
my $reg = undef;
|
||||
$reg = $clientmsg->{reg} if (defined($clientmsg->{reg}));
|
||||
$status = "Ok";
|
||||
foreach (split(" ", $clientmsg->{data})) {
|
||||
my $data = (defined($reg) ? chr($reg++) : "") . chr($_);
|
||||
my $retval = syswrite($fh, $data, length($data));
|
||||
#Log3 $hash, 1, "retval= $retval" if $clientmsg->{test} eq "local";
|
||||
unless (defined($retval) && $retval == length($data)) {
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess byteweise nach 0x".unpack( "H2",pack "C", $clientmsg->{i2caddress})." schreiben, ". (defined($reg) ? "Reg: 0x". unpack( "H2",pack "C", ($reg - 1)) . " " : "")."Inh: 0x" . unpack( "H2",pack "C", $_) .", laenge: ".length($data)."| -> syswrite failure: $!";
|
||||
$status = "error";
|
||||
last;
|
||||
}
|
||||
Log3 $hash, 5, "$hash->{NAME}: HWaccess byteweise schreiben, ". (defined($reg) ? "Reg: 0x". unpack( "H2",pack "C", ($reg - 1)) . " " : "")."Inh: 0x" . unpack( "H2",pack "C", $_) .", laenge: ".length($data);
|
||||
Log3 $hash, 5, "$hash->{NAME}: HWaccess byteweise schreiben, ". (defined($reg) ? "Reg: 0x". unpack( "H2",pack "C", ($reg - 1)) . " " : "")."Inh: 0x" . unpack( "H2",pack "C", $_) .", laenge: ".length($data);
|
||||
#Log3 $hash, 1, "$hash->{NAME}: HWaccess byteweise zu 0x".unpack( "H2",pack "C", $clientmsg->{i2caddress})." schreiben, ". (defined($reg) ? "Reg: 0x". unpack( "H2",pack "C", ($reg - 1)) . " " : "")."Inh: 0x" . unpack( "H2",pack "C", $_) .", laenge: ".length($data) if $clientmsg->{test} eq "local";
|
||||
}
|
||||
} elsif ($clientmsg->{direction} eq "i2cread") { #vom I2C lesen
|
||||
# } elsif ($clientmsg->{direction} eq "i2cread") { #byteweise lesen
|
||||
} elsif ($clientmsg->{direction} eq "i2cbyteread") { #byteweise lesen
|
||||
my $nbyte = defined($clientmsg->{nbyte}) ? $clientmsg->{nbyte} : 1;
|
||||
my $rmsg = "";
|
||||
foreach (my $n = 0; $n < $nbyte; $n++) {
|
||||
@ -483,7 +495,34 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
$rmsg .= " " if $n <= $nbyte;
|
||||
$status = "Ok" if ($n + 1) == $nbyte;
|
||||
}
|
||||
$clientmsg->{received} = $rmsg if($rmsg); #Daten als Scalar uebertragen
|
||||
$clientmsg->{received} = $rmsg if($rmsg); #Daten als Scalar uebertragen
|
||||
# } elsif ($clientmsg->{direction} eq "i2cblockread") { #blockweise lesen
|
||||
} elsif ($clientmsg->{direction} eq "i2cread") { #blockweise lesen
|
||||
my $nbyte = defined($clientmsg->{nbyte}) ? $clientmsg->{nbyte} : 1;
|
||||
#Log3 $hash, 1, "test Blockweise lese menge: |$nbyte|, reg: |". $clientmsg->{reg} ."|";
|
||||
my $rmsg = "";
|
||||
if ( defined($clientmsg->{reg}) ) {
|
||||
Log3 $hash, 4, "$hash->{NAME}: HWaccess blockweise lesen setze Registerpointer auf " . ($clientmsg->{reg});
|
||||
my $retval = syswrite($fh, chr($clientmsg->{reg}), 1);
|
||||
unless (defined($retval) && $retval == 1) {
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess blockweise von 0x".unpack( "H2",pack "C", $clientmsg->{i2caddress})." lesen,". (defined($clientmsg->{reg}) ? " Reg: 0x". unpack( "H2",pack "C", ($clientmsg->{reg})) : "") . " -> syswrite failure: $!" if $!;
|
||||
last;
|
||||
}
|
||||
}
|
||||
my $buf = undef;
|
||||
my $retval = sysread($fh, $buf, $nbyte);
|
||||
#Log3 $hash, 1, "test Blockweise lesen menge: |$nbyte|, return: |$retval|, inh: |$buf|";
|
||||
unless (defined($retval) && $retval == $nbyte) {
|
||||
Log3 $hash, 3, "$hash->{NAME}: HWaccess blockweise von 0x".unpack( "H2",pack "C", $clientmsg->{i2caddress})." lesen,". (defined($clientmsg->{reg}) ? " Reg: 0x". unpack( "H2",pack "C", ($clientmsg->{reg})) : "") . " -> sysread failure: $!" if $!;
|
||||
last;
|
||||
} else {
|
||||
$status = "Ok"
|
||||
}
|
||||
#Log3 $hash, 1, "test Blockweise lesen menge: |$nbyte|, inh: $buf";
|
||||
$rmsg = $buf;
|
||||
$rmsg =~ s/(.|\n)/sprintf("%u ",ord($1))/eg;
|
||||
#Log3 $hash, 1, "test Blockweise lesen ergebnis: |$rmsg|";
|
||||
$clientmsg->{received} = $rmsg if($rmsg); #Daten als Scalar uebertragen
|
||||
}
|
||||
$hash->{STATE} = $status;
|
||||
$hash->{ERRORCNT} = defined($hash->{ERRORCNT}) ? $hash->{ERRORCNT} += 1 : 1 if $status ne "Ok";
|
||||
@ -540,7 +579,7 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>
|
||||
<b>Optional</b>: access via IOCTL will be used if Device::SMBus is not present.<br>
|
||||
<b>Optional</b>: access via IOCTL will be used (RECOMMENDED) if Device::SMBus is not present.<br>
|
||||
To access the I2C-Bus via the Device::SMBus module, following steps are necessary:<br>
|
||||
<ul><code>sudo apt-get install libmoose-perl<br>
|
||||
sudo cpan Device::SMBus</code></ul><br>
|
||||
@ -567,11 +606,15 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
</li>
|
||||
<li>
|
||||
Write n-bytes to an register range (as an series of single register write operations), beginning at the specified register:<br>
|
||||
<code>set <name> writeByteReg <I2C Address> <Register Address> <value></code><br><br>
|
||||
<code>set <name> writeByteReg <I2C Address> <Register Address> <value> [<value> [..]]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Write n-bytes directly to an I2C device (as an block write operation):<br>
|
||||
<code>set <name> writeBlock <I2C Address> <Register Address> <value> [<value> [..]]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Write n-bytes to an register range (as an block write operation), beginning at the specified register:<br>
|
||||
<code>set <name> writeBlock <I2C Address> <Register Address> <value></code><br><br>
|
||||
<code>set <name> writeBlockReg <I2C Address> <Register Address> <value> [<value> [..]]</code><br><br>
|
||||
</li><br>
|
||||
Examples:
|
||||
<ul>
|
||||
@ -590,13 +633,22 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
<a name="RPII2CGet"></a>
|
||||
<b>Get</b>
|
||||
<ul>
|
||||
<code>get <name> read <I2C Address> [<Register Address> [<number of registers>]] </code>
|
||||
<br>
|
||||
gets value of I2C device's registers<br><br>
|
||||
<li>
|
||||
Gets value of I2C device's registers:<br>
|
||||
<code>get <name> read <I2C Address> [<Register Address> [<number of registers>]]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Gets value of I2C device in blockwise mode:<br>
|
||||
<code>get <name> readblock <I2C Address> [<number of registers>]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Gets value of I2C device's registers in blockwise mode:<br>
|
||||
<code>get <name> readblockreg <I2C Address> <Register Address> [<number of registers>]</code><br><br>
|
||||
</li><br>
|
||||
Examples:
|
||||
<ul>
|
||||
Reads byte from device with I2C address 0x60<br>
|
||||
<code>get test1 writeByte 60</code><br>
|
||||
<code>get test1 read 60</code><br>
|
||||
Reads register 0x01 of device with I2C address 0x6E.<br>
|
||||
<code>get test1 read 6E 01 AA 55</code><br>
|
||||
Reads register 0x03 to 0x06 of device with I2C address 0x60.<br>
|
||||
@ -672,7 +724,7 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>
|
||||
<b>Optional</b>: Hardwarezugriff via IOCTL wird standardmäßig genutzt, wenn Device::SMBus nicht installiert ist<br>
|
||||
<b>Optional</b>: Hardwarezugriff via IOCTL wird standardmäßig genutzt (EMPFOHLEN), wenn Device::SMBus nicht installiert ist<br>
|
||||
Soll der Hardwarezugriff über das Perl Modul Device::SMBus erfolgen sind diese Schritte notwendig:<br>
|
||||
<ul><code>sudo apt-get install libmoose-perl<br>
|
||||
sudo cpan Device::SMBus</code></ul><br>
|
||||
@ -699,11 +751,15 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
</li>
|
||||
<li>
|
||||
Schreibe n-bytes auf einen Registerbereich (als Folge von Einzelbefehlen), beginnend mit dem angegebenen Register:<br>
|
||||
<code>set <name> writeByteReg <I2C Address> <Register Address> <value></code><br><br>
|
||||
<code>set <name> writeByteReg <I2C Address> <Register Address> <value> [<value> [..]]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Schreibe n-bytes auf ein I2C device (als Blockoperation):<br>
|
||||
<code>set <name> writeBlock <I2C Address> <value> [<value> [..]]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Schreibe n-bytes auf einen Registerbereich (als Blockoperation), beginnend mit dem angegebenen Register:<br>
|
||||
<code>set <name> writeBlock <I2C Address> <Register Address> <value></code><br><br>
|
||||
<code>set <name> writeBlockReg <I2C Address> <Register Address> <value> [<value> [..]]</code><br><br>
|
||||
</li><br>
|
||||
Beispiele:
|
||||
<ul>
|
||||
@ -714,20 +770,29 @@ sub RPII2C_HWACCESS_ioctl($$) {
|
||||
Schreibe 0xAA zu Register 0x01 des Moduls mit der I2C Adresse 0x6E, schreibe danach 0x55 in das Register 0x02 als einzelne Befehle<br>
|
||||
<code>set test1 writeByteReg 6E 01 AA 55</code><br>
|
||||
Schreibe 0xA4 zu Register 0x03, 0x00 zu Register 0x04 und 0xDA zu Register 0x05 des Moduls mit der I2C Adresse 0x60 zusammen als ein Blockbefehl<br>
|
||||
<code>set test1 writeBlock 60 03 A4 00 DA</code><br>
|
||||
<code>set test1 writeBlockReg 60 03 A4 00 DA</code><br>
|
||||
</ul><br>
|
||||
</ul>
|
||||
|
||||
<a name="RPII2CGet"></a>
|
||||
<b>Get</b>
|
||||
<ul>
|
||||
<code>get <name> read <I2C Address> [<Register Address> [<number of registers>]] </code>
|
||||
<br>
|
||||
Auslesen der Registerinhalte des I2C Moduls<br><br>
|
||||
Examples:
|
||||
<li>
|
||||
Auslesen der Registerinhalte des I2C Moduls:<br>
|
||||
<code>get <name> read <I2C Address> [<Register Address> [<number of registers>]]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Blockweises Auslesen des I2C Moduls (ohne separate Register):<br>
|
||||
<code>get <name> readblock <I2C Address> [<number of registers>]</code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Blockweises Auslesen der Registerinhalte des I2C Moduls:<br>
|
||||
<code>get <name> readblockreg <I2C Address> <Register Address> [<number of registers>]</code><br><br>
|
||||
</li><br>
|
||||
Beispiele:
|
||||
<ul>
|
||||
Lese Byte vom Modul mit der I2C Adresse 0x60<br>
|
||||
<code>get test1 writeByte 60</code><br>
|
||||
<code>get test1 read 60</code><br>
|
||||
Lese den Inhalt des Registers 0x01 vom Modul mit der I2C Adresse 0x6E.<br>
|
||||
<code>get test1 read 6E 01 AA 55</code><br>
|
||||
Lese den Inhalt des Registerbereichs 0x03 bis 0x06 vom Modul mit der I2C Adresse 0x60.<br>
|
||||
|
448
fhem/FHEM/52_I2C_MCP342x.pm
Normal file
448
fhem/FHEM/52_I2C_MCP342x.pm
Normal file
@ -0,0 +1,448 @@
|
||||
##############################################
|
||||
# $Id: 52_MCP342x.pm 5865 2014-05-14 23:00:12Z klauswitt $
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Time::HiRes qw(usleep);
|
||||
use Scalar::Util qw(looks_like_number);
|
||||
#use Error qw(:try);
|
||||
|
||||
use constant {
|
||||
MCP3422_I2C_ADDRESS => '0x68',
|
||||
};
|
||||
|
||||
##################################################
|
||||
# Forward declarations
|
||||
#
|
||||
sub I2C_MCP342x_Initialize($);
|
||||
sub I2C_MCP342x_Define($$);
|
||||
sub I2C_MCP342x_Attr(@);
|
||||
sub I2C_MCP342x_Poll($);
|
||||
sub I2C_MCP342x_Set($@);
|
||||
sub I2C_MCP342x_Undef($$);
|
||||
|
||||
|
||||
my %resols = (
|
||||
'12' => {
|
||||
code => 0b00000000,
|
||||
delay => 5690,
|
||||
lsb => 1000,
|
||||
},
|
||||
'14' => {
|
||||
code => 0b00000100,
|
||||
delay => 22730,
|
||||
lsb => 250,
|
||||
},
|
||||
'16' => {
|
||||
code => 0b00001000,
|
||||
delay => 90910,
|
||||
lsb => 62.5,
|
||||
},
|
||||
'18' => {
|
||||
code => 0b00001100,
|
||||
delay => 363640,
|
||||
lsb => 15.625,
|
||||
},
|
||||
);
|
||||
|
||||
my %gains = (
|
||||
'1' => 0b00000000,
|
||||
'2' => 0b00000001,
|
||||
'4' => 0b00000010,
|
||||
'8' => 0b00000011,
|
||||
);
|
||||
|
||||
sub I2C_MCP342x_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{DefFn} = 'I2C_MCP342x_Define';
|
||||
$hash->{InitFn} = 'I2C_MCP342x_Init';
|
||||
$hash->{AttrFn} = 'I2C_MCP342x_Attr';
|
||||
$hash->{GetFn} = 'I2C_MCP342x_Get';
|
||||
$hash->{UndefFn} = 'I2C_MCP342x_Undef';
|
||||
$hash->{I2CRecFn} = 'I2C_MCP342x_I2CRec';
|
||||
|
||||
$hash->{AttrList} = 'IODev do_not_notify:0,1 showtime:0,1 poll_interval:1,2,5,10,20,30 ' .
|
||||
'ch1roundDecimal:0,1,2,3 ch1gain:1,2,4,8 ch1resolution:12,14,16,18 ch1factor '.
|
||||
'ch2roundDecimal:0,1,2,3 ch2gain:1,2,4,8 ch2resolution:12,14,16,18 ch2factor '.
|
||||
'ch3roundDecimal:0,1,2,3 ch3gain:1,2,4,8 ch3resolution:12,14,16,18 ch3factor '.
|
||||
'ch4roundDecimal:0,1,2,3 ch4gain:1,2,4,8 ch4resolution:12,14,16,18 ch4factor '.
|
||||
$readingFnAttributes;
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Define($$) {
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split('[ \t][ \t]*', $def);
|
||||
|
||||
$hash->{STATE} = "defined";
|
||||
|
||||
if ($main::init_done) {
|
||||
eval { I2C_MCP342x_Init( $hash, [ @a[ 2 .. scalar(@a) - 1 ] ] ); };
|
||||
return I2C_MCP342x_Catch($@) if $@;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Init($$) {
|
||||
my ( $hash, $args ) = @_;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
if (defined $args && int(@$args) > 1)
|
||||
{
|
||||
return "Define: Wrong syntax. Usage:\n" .
|
||||
"define <name> MCP342x [<i2caddress>] [<type>]";
|
||||
}
|
||||
|
||||
if (defined (my $address = shift @$args)) {
|
||||
$hash->{I2C_Address} = $address =~ /^0.*$/ ? oct($address) : $address;
|
||||
return "$name I2C Address not valid" unless ($address < 128 && $address > 3);
|
||||
} else {
|
||||
$hash->{I2C_Address} = hex(MCP3422_I2C_ADDRESS);
|
||||
}
|
||||
|
||||
if (defined (my $channels = shift @$args)) {
|
||||
$hash->{channels} = $channels if $channels == 2 || $channels == 4;
|
||||
} else {
|
||||
$hash->{channels} = 2;
|
||||
}
|
||||
|
||||
|
||||
my $msg = '';
|
||||
# create default attributes
|
||||
#$msg = CommandAttr(undef, $name . ' poll_interval 5');
|
||||
if ($msg) {
|
||||
Log3 ($hash, 1, $msg);
|
||||
return $msg;
|
||||
}
|
||||
AssignIoPort($hash);
|
||||
$hash->{STATE} = 'Initialized';
|
||||
|
||||
# my %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread" );
|
||||
# $sendpackage{reg} = hex("AA");
|
||||
# $sendpackage{nbyte} = 22;
|
||||
# return "$name: no IO device defined" unless ($hash->{IODev});
|
||||
# my $phash = $hash->{IODev};
|
||||
# my $pname = $phash->{NAME};
|
||||
# CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Catch($) {
|
||||
my $exception = shift;
|
||||
if ($exception) {
|
||||
$exception =~ /^(.*)( at.*FHEM.*)$/;
|
||||
return $1;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Attr (@) {# hier noch Werteueberpruefung einfuegen
|
||||
my ($command, $name, $attr, $val) = @_;
|
||||
my $hash = $defs{$name};
|
||||
my $msg = '';
|
||||
if ($command && $command eq "set" && $attr && $attr eq "IODev") {
|
||||
if ($main::init_done and (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $val)) {
|
||||
main::AssignIoPort($hash,$val);
|
||||
my @def = split (' ',$hash->{DEF});
|
||||
I2C_MCP342x_Init($hash,\@def) if (defined ($hash->{IODev}));
|
||||
}
|
||||
}
|
||||
if ($attr && $attr eq 'poll_interval') {
|
||||
#my $pollInterval = (defined($val) && looks_like_number($val) && $val > 0) ? $val : 0;
|
||||
if (!defined($val) ) {
|
||||
RemoveInternalTimer($hash);
|
||||
} elsif ($val > 0) {
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer(1, 'I2C_MCP23017_Poll', $hash, 0);
|
||||
} else {
|
||||
$msg = 'Wrong poll intervall defined. poll_interval must be a number > 0';
|
||||
}
|
||||
} elsif ($attr eq 'roundDecimal') {
|
||||
$msg = 'Wrong $attr defined. Use one of 0, 1, 2' if defined($val) && $val <= 0 && $val >= 3 ;
|
||||
} elsif ($attr eq 'gain') {
|
||||
foreach (split (/,/,$val)) {
|
||||
my @pair = split (/=/,$_);
|
||||
$msg = "wrong value: $_ for \"attr $hash->{NAME} $attr\" use comma separated <channel>=1|2|4|8 where <channel> = 1-$hash->{channels}"
|
||||
unless ( ( scalar(@pair) == 2 &&
|
||||
$pair[0] =~ m/^[1-4]$/i && $pair[0] <= $hash->{channels} &&
|
||||
$pair[1] =~ m/^(1|2|4|8)$/i ) ||
|
||||
$val =~ m/^(1|2|4|8)$/i);
|
||||
}
|
||||
} elsif ($attr eq 'resolution') {
|
||||
foreach (split (/,/,$val)) {
|
||||
my @pair = split (/=/,$_);
|
||||
$msg = "wrong value: $_ for \"attr $hash->{NAME} $attr\" use comma separated <channel>=12|14|16|18 where <channel> = 1-$hash->{channels}"
|
||||
unless ( ( scalar(@pair) == 2 &&
|
||||
$pair[0] =~ m/^[1-4]$/i &&
|
||||
$pair[1] =~ m/^1(2|4|6|8)$/i ) &&
|
||||
$val =~ m/^1(2|4|6|8)$/i );
|
||||
}
|
||||
}
|
||||
|
||||
return ($msg) ? $msg : undef;
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Poll($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
# Read values
|
||||
I2C_MCP342x_Get($hash, $name);
|
||||
|
||||
my $pollInterval = AttrVal($hash->{NAME}, 'poll_interval', 0);
|
||||
if ($pollInterval > 0) {
|
||||
InternalTimer(gettimeofday() + ($pollInterval * 60), 'I2C_MCP342x_Poll', $hash, 0);
|
||||
}
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Get($@) {
|
||||
my ($hash, @a) = @_;
|
||||
my $name = $a[0];
|
||||
my $cmd = $a[1];
|
||||
|
||||
my $rex = "^[1-" . $hash->{channels} . "]\$";
|
||||
if ($cmd =~ m/$rex/i) {
|
||||
my $resol = defined $a[2] ? $a[2] : AttrVal($hash->{NAME},("ch" . $cmd . "resolution"),"12");
|
||||
return "Wrong resolution, use 12, 14, 16 or 18" unless $resol =~ m/^1(2|4|6|8)$/i;
|
||||
my $gain = defined $a[3] ? $a[3] : AttrVal($hash->{NAME},("ch" . $cmd . "gain"),"1");
|
||||
return "Wrong gain, use 1, 2, 4 or 8" unless $gain =~ m/^(1|2|4|8)$/i;
|
||||
my $ts = ReadingsTimestamp($hash->{NAME},("Channel".$cmd),0);
|
||||
I2C_MCP342x_readvoltage($hash,$cmd,$resol,$gain);
|
||||
foreach (1..400) { #max 2s warten
|
||||
usleep 5000;
|
||||
return ReadingsVal($hash->{NAME},("Channel".$cmd),undef) if $ts ne ReadingsTimestamp($hash->{NAME},("Channel".$cmd),0);
|
||||
}
|
||||
} else {
|
||||
foreach (1..$hash->{channels}) {
|
||||
my $resol = defined $a[3] ? $a[3] : AttrVal($hash->{NAME},("ch" . $_ . "resolution"),"12");
|
||||
return "Wrong resolution, use 12, 14, 16 or 18" unless $resol =~ m/^1(2|4|6|8)$/i;
|
||||
my $gain = defined $a[4] ? $a[4] : AttrVal($hash->{NAME},("ch" . $_ . "gain"),"1");
|
||||
return "Wrong gain, use 1, 2, 4 or 8" unless $gain =~ m/^(1|2|4|8)$/i;
|
||||
I2C_MCP342x_readvoltage($hash,$_,$resol,$gain);
|
||||
}
|
||||
my @gets = ('1', '2');
|
||||
push(@gets,('3', '4')) if $hash->{channels} == 4;
|
||||
return 'Unknown argument ' . $cmd . ', choose one of ' . join(' ', @gets)
|
||||
}
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_Undef($$) {
|
||||
my ($hash, $arg) = @_;
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_I2CRec ($$) {
|
||||
my ($hash, $clientmsg) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $phash = $hash->{IODev};
|
||||
my $pname = $phash->{NAME};
|
||||
while ( my ( $k, $v ) = each %$clientmsg ) { #erzeugen von Internals fuer alle Keys in $clientmsg die mit dem physical Namen beginnen
|
||||
$hash->{$k} = $v if $k =~ /^$pname/ ;
|
||||
}
|
||||
#my $ankommen = "$hash->{NAME}: vom physical empfangen";
|
||||
# foreach my $av (keys %{$clientmsg}) { $ankommen .= "|" . $av . ": " . $clientmsg->{$av}; }
|
||||
#Log3 $hash, 1, $ankommen;
|
||||
if ($clientmsg->{direction} && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") {
|
||||
readingsSingleUpdate($hash,"state", "Ok", 1);
|
||||
if ( $clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received}) ) {###hier noch normal read rein,wenn alles wieder ok
|
||||
#Log3 $hash, 1, "empfangen: $clientmsg->{received}";
|
||||
I2C_MCP342x_GetVoltage ($hash, $clientmsg->{received}); # if $clientmsg->{type} eq "temp" && $clientmsg->{nbyte} == 2;
|
||||
}
|
||||
} else {
|
||||
readingsSingleUpdate($hash,"state", "transmission error", 1);
|
||||
Log3 $hash, 3, "$name: failurei in message from $pname";
|
||||
Log3 $hash, 3,(defined($clientmsg->{direction}) ? "Direction: " . $clientmsg->{direction} : "Direction: undef").
|
||||
(defined($clientmsg->{i2caddress}) ? " I2Caddress: " . sprintf("0x%.2X", $clientmsg->{i2caddress}) : " I2Caddress: undef").
|
||||
(defined($clientmsg->{reg}) ? " Register: " . sprintf("0x%.2X", $clientmsg->{reg}) : " Register: undef").
|
||||
(defined($clientmsg->{data}) ? " Data: " . sprintf("0x%.2X", $clientmsg->{data}) : " Data: undef").
|
||||
(defined($clientmsg->{received}) ? " received: " . sprintf("0x%.2X", $clientmsg->{received}) : " received: undef");
|
||||
}
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_GetVoltage ($$) {
|
||||
my ($hash, $rawdata) = @_;
|
||||
my @raw = split(" ",$rawdata);
|
||||
if ( defined($raw[4]) ) {
|
||||
if ( ($raw[4] & 0b10000000) == 0 ) {
|
||||
my $channel = 1 + (($raw[4] & 0b01100000) >> 5 );
|
||||
my $resol = 2 * (($raw[4] & 0b00001100) >> 2 ) + 12;
|
||||
my $gain = 2 ** ($raw[4] & 0b00000011);
|
||||
my $rawvolt;
|
||||
if ($resol == 18) {
|
||||
$rawvolt = ($raw[0] & 0b00000011) << 16 | $raw[1] << 8 | $raw[2];
|
||||
} else {
|
||||
$rawvolt = $raw[0] << 8 | $raw[1];
|
||||
}
|
||||
#Log3 $hash, 1, "Kanal: $channel, rawvolt: $rawvolt, Aufloesung: $resol, Gain: $gain, LSB: $resols{$resol}{lsb}";
|
||||
$rawvolt -= (1 << $resol) if $rawvolt >= (1 << ($resol - 1));
|
||||
#Log3 $hash, 1, "Kanal: $channel, Unsignedrawvolt: $rawvolt";
|
||||
|
||||
my $voltage = ( $rawvolt * $resols{$resol}{lsb} ) / $gain ;
|
||||
#$voltage /= 1000000;
|
||||
$voltage *= AttrVal($hash->{NAME},("ch" . $channel . "factor"),"1");
|
||||
$voltage = sprintf(
|
||||
'%.' . AttrVal($hash->{NAME}, ('ch' . $channel . 'roundDecimal'), 3) . 'f',
|
||||
$voltage
|
||||
);
|
||||
$voltage .= " overflow" if ( $rawvolt == ( (1<<($resol-1)) - 1) || $rawvolt == (1<<($resol-1)) );
|
||||
readingsSingleUpdate($hash,"Channel$channel", $voltage, 1);
|
||||
#Log3 $hash, 1, "Kanal: $channel, Fertig: $voltage";
|
||||
} else {
|
||||
Log3 $hash, 3, $hash->{NAME} . " error, output conversion not finished";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub I2C_MCP342x_readvoltage($@) {
|
||||
my ($hash, $channel, $resol, $gain) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
return "$name: no IO device defined" unless ($hash->{IODev});
|
||||
my $phash = $hash->{IODev};
|
||||
my $pname = $phash->{NAME};
|
||||
#0b10010000
|
||||
my $confreg = 1 << 7; # 1|| |||| Initiate a new conversion
|
||||
$confreg |= ($channel - 1) << 5; # 11 |||| Channel Selection Bits
|
||||
$confreg |= $resols{$resol}{code}; # 11|| Sample Rate Selection Bit
|
||||
$confreg |= $gains{$gain}; # 11 PGA Gain Selection Bits
|
||||
#Log3 $hash, 1, "confinhalt: " . sprintf ('0b%08b', $confreg);
|
||||
|
||||
# Write CONFIGURATION REGISTER to device. This requests a conversion process
|
||||
my $i2creq = { i2caddress => $hash->{I2C_Address}, direction => "i2cwrite" };
|
||||
$i2creq->{data} = $confreg;
|
||||
CallFn($pname, "I2CWrtFn", $phash, $i2creq);
|
||||
usleep($resols{$resol}{delay}); #Verzoegerung
|
||||
|
||||
# Read the result from device
|
||||
my $i2cread = { i2caddress => $hash->{I2C_Address}, direction => "i2cread" };
|
||||
$i2cread->{nbyte} = 5;
|
||||
#$i2cread->{type} = "temp";
|
||||
CallFn($pname, "I2CWrtFn", $phash, $i2cread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
=begin html
|
||||
|
||||
<a name="I2C_MCP342x"></a>
|
||||
<h3>I2C_MCP342x</h3>
|
||||
<ul>
|
||||
<a name="I2C_MCP342x"></a>
|
||||
Provides an interface to the MCP3422/3/4 A/D converter.
|
||||
The I2C messages are send through an I2C interface module like <a href="#RPII2C">RPII2C</a>, <a href="#FRM">FRM</a>
|
||||
or <a href="#NetzerI2C">NetzerI2C</a> so this device must be defined first.<br>
|
||||
<b>attribute IODev must be set</b><br>
|
||||
<a name="I2C_MCP342xDefine"></a><br>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> I2C_MCP342x [[<I2C Address>] <n channels>]</code><br>
|
||||
where <I2C Address> is without direction bit and <n channels> is the number of A/D channels<br><br>
|
||||
</ul>
|
||||
<a name="I2C_MCP342xSet"></a>
|
||||
<b>Get</b>
|
||||
<ul>
|
||||
<code>get <name> [[[<channel>] <resolution> ] <gain>]</code><br>
|
||||
Returns the level on specific <channel>. <resolution> and <gain> will override attibutes for actual operation.
|
||||
Without attributes only the readings will be refreshed.<br><br>
|
||||
</ul>
|
||||
<a name="I2C_MCP342xAttr"></a>
|
||||
<b>Attributes</b>
|
||||
<ul>
|
||||
<li>poll_interval<br>
|
||||
Set the polling interval in minutes to query data from sensor<br>
|
||||
Default: 5, valid values: 1,2,5,10,20,30<br><br>
|
||||
</li>
|
||||
Following attributes are separate for all channels.<br><br>
|
||||
<li>ch1resolution<br>
|
||||
resolution settings<br>
|
||||
the bigger the resolution the longer the conversion time.<br>
|
||||
Default: 12, valid values: 12,14,16,18<br><br>
|
||||
</li>
|
||||
<li>ch1gain<br>
|
||||
gain setting<br>
|
||||
Important: the gain setting will reduce the measurement range an may produce an overflow. In this case "overflow" will be added to reading<br>
|
||||
Default: 1, valid values: 1,2,4,8<br><br>
|
||||
</li>
|
||||
<li>ch1factor<br>
|
||||
correction factor (will be mutiplied to channel value)<br>
|
||||
Default: 1, valid values: number<br><br>
|
||||
</li>
|
||||
<li>ch1roundDecimal<br>
|
||||
Number of decimal places for value<br>
|
||||
Default: 3, valid values: 0,1,2,3<br><br>
|
||||
</li>
|
||||
<li><a href="#IODev">IODev</a></li>
|
||||
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
</ul><br>
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
|
||||
=begin html_DE
|
||||
|
||||
<a name="I2C_MCP342x"></a>
|
||||
<h3>I2C_MCP342x</h3>
|
||||
<ul>
|
||||
<a name="I2C_MCP342x"></a>
|
||||
Ermöglicht die Verwendung eines MCP3422/3/4 I2C A/D Wandler.
|
||||
I2C-Botschaften werden über ein I2C Interface Modul wie beispielsweise das <a href="#RPII2C">RPII2C</a>, <a href="#FRM">FRM</a>
|
||||
oder <a href="#NetzerI2C">NetzerI2C</a> gesendet. Daher muss dieses vorher definiert werden.<br>
|
||||
<b>Das Attribut IODev muss definiert sein.</b><br>
|
||||
<a name="I2C_MCP342xDefine"></a><br>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> I2C_MCP342x [[<I2C Address>] <n channels>]</code><br>
|
||||
Der Wert <code><I2C Address></code> ist die I2C Adresse ohne Richtungsbit und <n channels> die Anzahl der A/D Kanäle.<br>
|
||||
</ul>
|
||||
<a name="I2C_MCP342xGet"></a>
|
||||
<b>Get</b>
|
||||
<ul>
|
||||
<code>get <name> [[[<channel>] <resolution> ] <gain>]</code><br>
|
||||
Aktuelle Werte vom entstrechenden <channel> lesen. <resolution> und <gain> überschreiben die entsprechenden Attribute für diesen Lesevorgang<br><br>
|
||||
</ul>
|
||||
<a name="I2C_MCP342xAttr"></a>
|
||||
<b>Attribute</b>
|
||||
<ul>
|
||||
<li>poll_interval<br>
|
||||
Aktualisierungsintervall aller Werte in Minuten.<br>
|
||||
Standard: 5, gültige Werte: 1,2,5,10,20,30<br><br>
|
||||
</li>
|
||||
Folgende Attribute existieren separat für alle Kanäle.<br><br>
|
||||
<li>ch1resolution<br>
|
||||
Auflösung des Kanals<br>
|
||||
Je größer die Auflösung desto länger die Lesezeit.<br>
|
||||
Standard: 12, gültige Werte: 12,14,16,18<br><br>
|
||||
</li>
|
||||
<li>ch1gain<br>
|
||||
Verstärkungsfaktor<br>
|
||||
Wichtig: Der Verstärkungsfaktor verringert den Messbereich entsprechend und kann zu einem Überlauf führen. In diesem Fall wird "overflow" an das reading angehängt.<br>
|
||||
Standard: 1, gültige Werte: 1,2,4,8<br><br>
|
||||
</li>
|
||||
<li>ch1factor<br>
|
||||
Korrekturfaktor (Wird zum Kanalwert multipliziert.)<br>
|
||||
Standard: 1, gültige Werte: Zahl<br><br>
|
||||
</li>
|
||||
<li>ch1roundDecimal<br>
|
||||
Anzahl Dezimalstellen für den Messwert<br>
|
||||
Standard: 3, gültige Werte: 0,1,2,3<br><br>
|
||||
</li>
|
||||
<li><a href="#IODev">IODev</a></li>
|
||||
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
</ul><br>
|
||||
</ul>
|
||||
|
||||
=end html_DE
|
||||
|
||||
=cut
|
@ -151,6 +151,7 @@ FHEM/52_I2C_EEPROM.pm klausw http://forum.fhem.de Sonstige
|
||||
FHEM/52_I2C_LCD ntruchsess http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/52_I2C_MCP23008 klausw http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/52_I2C_MCP23017 klausw http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/52_I2C_MCP342x klausw http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/52_I2C_PCA9532 klausw http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/52_I2C_PCF8574 klausw http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/52_I2C_SHT21 klausw http://forum.fhem.de Sonstige Systeme
|
||||
|
Loading…
Reference in New Issue
Block a user