52_I2C_PCA9685.pm: fix, wrow version wal uploaded
git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@10420 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -118,10 +118,10 @@ sub I2C_PCA9685_Init($$) { #
|
|||||||
I2C_PCA9685_Attr(undef, $name, "modreg1", AttrVal($name, "modreg1", ""));
|
I2C_PCA9685_Attr(undef, $name, "modreg1", AttrVal($name, "modreg1", ""));
|
||||||
I2C_PCA9685_Attr(undef, $name, "modreg2", AttrVal($name, "modreg2", ""));
|
I2C_PCA9685_Attr(undef, $name, "modreg2", AttrVal($name, "modreg2", ""));
|
||||||
#alternative I2C Adressen wiederherstellen
|
#alternative I2C Adressen wiederherstellen
|
||||||
I2C_PCA9685_I2CSet($hash,AttrVal($name, "subadr1", $defaultreg{'sub1'}) << 1, 2) if defined AttrVal($name, "subadr1", undef);
|
I2C_PCA9685_i2cwrite($hash,AttrVal($name, $defaultreg{'sub1'}, "subadr1") << 1, 2) if defined AttrVal($name, "subadr1", undef);
|
||||||
I2C_PCA9685_I2CSet($hash,AttrVal($name, "subadr2", $defaultreg{'sub2'}) << 1, 3) if defined AttrVal($name, "subadr2", undef);
|
I2C_PCA9685_i2cwrite($hash,AttrVal($name, $defaultreg{'sub2'}, "subadr2") << 1, 3) if defined AttrVal($name, "subadr2", undef);
|
||||||
I2C_PCA9685_I2CSet($hash,AttrVal($name, "subadr3", $defaultreg{'sub3'}) << 1, 4) if defined AttrVal($name, "subadr3", undef);
|
I2C_PCA9685_i2cwrite($hash,AttrVal($name, $defaultreg{'sub3'}, "subadr3") << 1, 4) if defined AttrVal($name, "subadr3", undef);
|
||||||
I2C_PCA9685_I2CSet($hash,AttrVal($name, "allcalladr", $defaultreg{'allc'}) << 1, 5) if defined AttrVal($name, "allcalladr", undef);
|
I2C_PCA9685_i2cwrite($hash,AttrVal($name, $defaultreg{'allc'}, "allcalladr") << 1, 5) if defined AttrVal($name, "allcalladr", undef);
|
||||||
#PWM Frequenz wiederherstellen
|
#PWM Frequenz wiederherstellen
|
||||||
I2C_PCA9685_Attr(undef, $name, "prescale", AttrVal($name, "prescale", $defaultreg{'presc'})) if defined AttrVal($name, "prescale", undef);
|
I2C_PCA9685_Attr(undef, $name, "prescale", AttrVal($name, "prescale", $defaultreg{'presc'})) if defined AttrVal($name, "prescale", undef);
|
||||||
#Portzustände wiederherstellen
|
#Portzustände wiederherstellen
|
||||||
@@ -131,9 +131,6 @@ sub I2C_PCA9685_Init($$) { #
|
|||||||
$hash->{STATE} = 'Initialized';
|
$hash->{STATE} = 'Initialized';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
{"RX: ". ReadingsVal($name,'RX',"-") . " / TX: ". ReadingsVal($name,'TX',"-")}
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
sub I2C_PCA9685_Catch($) { #
|
sub I2C_PCA9685_Catch($) { #
|
||||||
my $exception = shift;
|
my $exception = shift;
|
||||||
@@ -183,16 +180,16 @@ sub I2C_PCA9685_Attr(@) { #
|
|||||||
unless(looks_like_number($val) && $val >= 0 && $val < 256);
|
unless(looks_like_number($val) && $val >= 0 && $val < 256);
|
||||||
my $modereg1 = defined $hash->{confregs}{0} ? $hash->{confregs}{0} : $defaultreg{'modreg1'};
|
my $modereg1 = defined $hash->{confregs}{0} ? $hash->{confregs}{0} : $defaultreg{'modreg1'};
|
||||||
my $modereg1mod = ( $modereg1 & 0x7F ) | $mr1{ "SLEEP" };
|
my $modereg1mod = ( $modereg1 & 0x7F ) | $mr1{ "SLEEP" };
|
||||||
$msg = I2C_PCA9685_I2CSet($hash,$modereg1mod, 0); #sleep Mode aktivieren
|
$msg = I2C_PCA9685_i2cwrite($hash, 0, $modereg1mod); #sleep Mode aktivieren
|
||||||
$msg .= I2C_PCA9685_I2CSet($hash,$val, 254); #Frequenz aktualisieren
|
$msg .= I2C_PCA9685_i2cwrite($hash, 254 ,$val); #Frequenz aktualisieren
|
||||||
$msg .= I2C_PCA9685_I2CSet($hash,$modereg1, 0); #sleep Mode wieder aus
|
$msg .= I2C_PCA9685_i2cwrite($hash, 0 ,$modereg1); #sleep Mode wieder aus
|
||||||
#Log3 $hash, 1, "testprescale: $modereg1 | $modereg1mod | $val";
|
#Log3 $hash, 1, "testprescale: $modereg1 | $modereg1mod | $val";
|
||||||
} elsif ($attr && $attr =~ m/^(subadr[1-3])|allcalladr$/i) {
|
} elsif ($attr && $attr =~ m/^(subadr[1-3])|allcalladr$/i) {
|
||||||
substr($attr,0,6,""); #weitere I2C Adressen
|
substr($attr,0,6,""); #weitere I2C Adressen
|
||||||
my $regaddr = ($attr =~ m/^l/i) ? 5 : $attr + 1;
|
my $regaddr = ($attr =~ m/^l/i) ? 5 : $attr + 1;
|
||||||
my $subadr = $val =~ /^0.*$/ ? oct($val) : $val;
|
my $subadr = $val =~ /^0.*$/ ? oct($val) : $val;
|
||||||
return "I2C Address not valid" if $subadr > 127;
|
return "I2C Address not valid" if $subadr > 127;
|
||||||
$msg = I2C_PCA9685_I2CSet($hash,$subadr << 1,$regaddr);
|
$msg = I2C_PCA9685_i2cwrite($hash, $regaddr ,$subadr << 1);
|
||||||
} elsif ($attr && $attr =~ m/^modreg1$/i) { #Mode register 1
|
} elsif ($attr && $attr =~ m/^modreg1$/i) { #Mode register 1
|
||||||
my @inp = split(/,/, $val) if defined($val);
|
my @inp = split(/,/, $val) if defined($val);
|
||||||
my $data = 32; # Auto increment soll immer gesetzt sein
|
my $data = 32; # Auto increment soll immer gesetzt sein
|
||||||
@@ -204,16 +201,16 @@ sub I2C_PCA9685_Attr(@) { #
|
|||||||
my $modereg1 = defined $hash->{confregs}{0} ? $hash->{confregs}{0} : $defaultreg{'modreg1'};
|
my $modereg1 = defined $hash->{confregs}{0} ? $hash->{confregs}{0} : $defaultreg{'modreg1'};
|
||||||
my $modereg1mod = ( $modereg1 & 0x7F ) | $mr1{ "SLEEP" };
|
my $modereg1mod = ( $modereg1 & 0x7F ) | $mr1{ "SLEEP" };
|
||||||
Log3 $hash, 5, "$hash->{NAME}: sleep Mode aktivieren (Vorbereitung fuer EXTCLK)";
|
Log3 $hash, 5, "$hash->{NAME}: sleep Mode aktivieren (Vorbereitung fuer EXTCLK)";
|
||||||
$msg = I2C_PCA9685_I2CSet($hash,$modereg1mod, 0); #sleep Mode aktivieren
|
$msg = I2C_PCA9685_i2cwrite($hash, 0 ,$modereg1mod); #sleep Mode aktivieren
|
||||||
$data += $mr1{"SLEEP"};
|
$data += $mr1{"SLEEP"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#my $modereg1 = defined $hash->{confregs}{0} ? $hash->{confregs}{0} : $defaultreg{'modreg1'};
|
#my $modereg1 = defined $hash->{confregs}{0} ? $hash->{confregs}{0} : $defaultreg{'modreg1'};
|
||||||
#Log3 $hash, 1, "test1: " . ($hash->{confregs}{0} & $mr1{"EXTCLK"}) . "|" . $hash->{confregs}{0} ."|". $mr1{"EXTCLK"} . " test2: ". ($data & $mr1{"EXTCLK"}) ."|" . $data ."|". $mr1{"EXTCLK"};
|
#Log3 $hash, 1, "test1: " . ($hash->{confregs}{0} & $mr1{"EXTCLK"}) . "|" . $hash->{confregs}{0} ."|". $mr1{"EXTCLK"} . " test2: ". ($data & $mr1{"EXTCLK"}) ."|" . $data ."|". $mr1{"EXTCLK"};
|
||||||
if ( defined $hash->{confregs}{0} && ($hash->{confregs}{0} & $mr1{"EXTCLK"}) == $mr1{"EXTCLK"} && ($data & $mr1{"EXTCLK"}) == 0 ) { #reset wenn EXTCLK abgeschaltet wird
|
if ( defined $hash->{confregs}{0} && ($hash->{confregs}{0} & $mr1{"EXTCLK"}) == $mr1{"EXTCLK"} && ($data & $mr1{"EXTCLK"}) == 0 ) { #reset wenn EXTCLK abgeschaltet wird
|
||||||
$msg = I2C_PCA9685_I2CSet($hash, $data | 0x80, 0);
|
$msg = I2C_PCA9685_i2cwrite($hash, 0 , $data | 0x80);
|
||||||
}
|
}
|
||||||
$msg = I2C_PCA9685_I2CSet($hash, $data, 0);
|
$msg = I2C_PCA9685_i2cwrite($hash, 0 , $data);
|
||||||
} elsif ($attr && $attr =~ m/^modreg2$/i) { #Mode register 2
|
} elsif ($attr && $attr =~ m/^modreg2$/i) { #Mode register 2
|
||||||
my @inp = split(/,/, $val) if defined($val);
|
my @inp = split(/,/, $val) if defined($val);
|
||||||
my $data = 0; # Auto increment soll immer gesetzt sein
|
my $data = 0; # Auto increment soll immer gesetzt sein
|
||||||
@@ -222,7 +219,7 @@ sub I2C_PCA9685_Attr(@) { #
|
|||||||
unless(exists($mr2{$_}));
|
unless(exists($mr2{$_}));
|
||||||
$data += $mr2{$_};
|
$data += $mr2{$_};
|
||||||
}
|
}
|
||||||
$msg = I2C_PCA9685_I2CSet($hash, $data, 1);
|
$msg = I2C_PCA9685_i2cwrite($hash, 1, $data);
|
||||||
} elsif ($attr && $attr eq "OnStartup") {
|
} elsif ($attr && $attr eq "OnStartup") {
|
||||||
# Das muss noch angepasst werden !!!!!!!!!!!!!!!!!!!!
|
# Das muss noch angepasst werden !!!!!!!!!!!!!!!!!!!!
|
||||||
if (defined $val) {
|
if (defined $val) {
|
||||||
@@ -240,61 +237,57 @@ sub I2C_PCA9685_Attr(@) { #
|
|||||||
}
|
}
|
||||||
#############################################################################
|
#############################################################################
|
||||||
sub I2C_PCA9685_Set($@) { #
|
sub I2C_PCA9685_Set($@) { #
|
||||||
my ($hash, @a) = @_;
|
my ($hash, $name, @a) = @_;
|
||||||
my $name = $a[0];
|
my $port = $a[0];
|
||||||
my $port = $a[1];
|
my $val = $a[1];
|
||||||
my $val = $a[2];
|
|
||||||
unless (@a == 3) {
|
|
||||||
|
|
||||||
}
|
|
||||||
my $msg;
|
|
||||||
my $dimstep = AttrVal($name, "dimstep", "1");
|
my $dimstep = AttrVal($name, "dimstep", "1");
|
||||||
my $dimcount = AttrVal($name, "dimcount", "4095");
|
my $dimcount = AttrVal($name, "dimcount", "4095");
|
||||||
|
my $msg;
|
||||||
|
|
||||||
|
#my $str = join(" ",@a);
|
||||||
|
#if ($str $$ $str =~ m/^(P(ort|)((0|)[0-9]|1[0-5])) $/i) { # mehrere Port (unfertig)
|
||||||
|
#
|
||||||
|
# if (index($str, ',') != -1) { # wenn mehrere Kanaele gesetzt werden sollen
|
||||||
|
# my @einzel = split(',', $str);
|
||||||
|
# my (undef, $tval, $tdval) = split(' ', $einzel[$#einzel]); # Dimmwerte von letztem Eintrag sichern
|
||||||
|
# Log3 $hash, 1, "Tempval: $tval | $tdval";
|
||||||
|
# foreach (reverse @einzel) {
|
||||||
|
# my @cmd = split(' ', $_);
|
||||||
|
# my ($dim, $delay);
|
||||||
|
# my $port = $cmd[0];
|
||||||
|
# $port =~ tr/P(ort|)//d;
|
||||||
|
# if (defined($cmd[1])) {
|
||||||
|
# $dim = $cmd[1];
|
||||||
|
# $delay = $cmd[2];
|
||||||
|
# } else {
|
||||||
|
# $dim = $tval;
|
||||||
|
# $delay = $tdval;
|
||||||
|
# }
|
||||||
|
# Log3 $hash, 1, "Werte fuer $port: $dim | $delay";
|
||||||
|
# #hier
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
#}
|
||||||
|
|
||||||
if ( $port && $port =~ m/^(Port((0|)[0-9]|1[0-5]))|(All)$/i) { #wenn ein Port oder alle
|
if ( $port && $port =~ m/^(P(ort|)((0|)[0-9]|1[0-5]))|(All)$/i) { # wenn ein Port oder alle
|
||||||
return "wrong value: $val for \"set $name $port\" use one of: " .
|
return "wrong value: $val for \"set $name $port\" use one of: " .
|
||||||
join(',', (sort { $setsP{ $a } <=> $setsP{ $b } } keys %setsP) ) .
|
join(',', (sort { $setsP{ $a } <=> $setsP{ $b } } keys %setsP) ) .
|
||||||
" 0..$dimcount"
|
" 0..$dimcount"
|
||||||
unless(exists($setsP{$val}) || ($val >= 0 && $val <= $dimcount));
|
unless(exists($setsP{$val}) || ($val >= 0 && $val <= $dimcount));
|
||||||
($port =~ m/^All$/i) ? $port = 61 : substr($port,0,4,""); #Portnummer extrahieren oder 61 für All setzen
|
($port =~ m/^All$/i) ? $port = 61 : $port =~ tr/P(ort|)//d; # Portnummer extrahieren oder 61 für All setzen (All Startreg ist 250)
|
||||||
my $reg = 6 + 4 * $port; #Nummer des entspechenden LEDx_ON_L Registers (LED0_ON_L = 0x06) jede LED hat 4 Register
|
my $reg = 6 + 4 * $port; # Nummer des entspechenden LEDx_ON_L Registers (LED0_ON_L = 0x06) jede LED hat 4 Register
|
||||||
my $data;
|
my $data = I2C_PCA9685_CalcRegs($hash, $port, $val, $a[2]); # Registerinhalte berechnen
|
||||||
if ($val eq "on") {
|
$msg = I2C_PCA9685_i2cwrite($hash,$reg, $data); # Rausschicken
|
||||||
$data = "0 16 0 0";
|
|
||||||
} elsif ($val eq "off") {
|
|
||||||
$data = "0 0 0 16";
|
|
||||||
} else {
|
|
||||||
my $delaytime = 0;
|
|
||||||
if ($dimcount < 4095) { #DimmWert anpassen bei anderem Faktor
|
|
||||||
$val = int($val * 4095 / $dimcount);
|
|
||||||
}
|
|
||||||
if (defined $a[3]) { #Delaytime angegeben?
|
|
||||||
return "wrong delay value: $a[3] for \"set $name Port$port $val $a[3]\" use value between 0 and $dimcount"
|
|
||||||
unless ($a[3] >= 0 && $a[3] <= $dimcount);
|
|
||||||
if ($dimcount < 4095) { #DelayWert anpassen bei anderem Faktor
|
|
||||||
$a[3] = int($a[3] * 4095 / $dimcount);
|
|
||||||
}
|
|
||||||
$delaytime = $a[3]
|
|
||||||
} else { #...wenn nicht aus Reading holen (für all kommt immer 0 raus)
|
|
||||||
$delaytime = ReadingsVal($name,'Port_d'.sprintf ('%02d', $port),"0");
|
|
||||||
}
|
|
||||||
my $LEDx_OFF = $delaytime + $val - (( $val + $delaytime < 4096 ) ? 0 : 4096);
|
|
||||||
if ($LEDx_OFF == $delaytime) { #beide Register dürfen nicht gleichen Inhalt haben, das entpricht "aus"
|
|
||||||
$data = "0 0 0 16";
|
|
||||||
} else {
|
|
||||||
my @LEDx = unpack("C*", pack("S", $delaytime));
|
|
||||||
push @LEDx, unpack("C*", pack("S", $LEDx_OFF)); #Array $LEDx[0] = LEDx_ON_L, $LEDx[1] = LEDx_ON_H, $LEDx[2] = LEDx_OFF_L, $LEDx[3] = LEDx_OFF_H
|
|
||||||
$data = sprintf "%01d " x 4, @LEDx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$msg = I2C_PCA9685_I2CSet($hash,$data,$reg);
|
|
||||||
} else {
|
} else {
|
||||||
my $list = undef;
|
my $list = undef;
|
||||||
foreach (0..15) {
|
foreach (0..15) {
|
||||||
$list .= "Port" . sprintf ('%02d', $_) . ":slider,0,$dimstep,$dimcount ";
|
$list .= "Port" . sprintf ('%02d', $_) . ":slider,0,$dimstep,$dimcount ";
|
||||||
}
|
}
|
||||||
$list .= "all:slider,0,$dimstep,$dimcount";
|
$list .= "all:slider,0,$dimstep,$dimcount";
|
||||||
$msg = "Unknown argument $a[1], choose one of " . $list;
|
$msg = "Unknown argument $a[0], choose one of " . $list;
|
||||||
}
|
}
|
||||||
return defined $msg ? $msg : undef
|
return defined $msg ? $msg : undef
|
||||||
}
|
}
|
||||||
@@ -313,34 +306,93 @@ sub I2C_PCA9685_Set($@) { #
|
|||||||
#sprintf "%02X " x 4 . "\n", @octets;
|
#sprintf "%02X " x 4 . "\n", @octets;
|
||||||
# prints: 00 00 07 D1
|
# prints: 00 00 07 D1
|
||||||
#############################################################################
|
#############################################################################
|
||||||
sub I2C_PCA9685_I2CSet { # I2CWrtFn vom IODev aufrufen !!!!!wieder auf IODev umleiten!!!
|
sub I2C_PCA9685_CalcRegs($$$$) { # Registerinhalte berechnen
|
||||||
my ($hash, $data, $reg) = @_;
|
my ($hash, $port, $val, $del) = @_;
|
||||||
|
my $dimcount = AttrVal($hash->{NAME}, "dimcount", "4095");
|
||||||
if (defined (my $iodev = $hash->{IODev})) {
|
my $data;
|
||||||
CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, {
|
if ($val eq "on") {
|
||||||
direction => "i2cwrite",
|
$data = "0 16 0 0";
|
||||||
i2caddress => $hash->{I2C_Address},
|
} elsif ($val eq "off") {
|
||||||
reg => $reg,
|
$data = "0 0 0 16";
|
||||||
data => $data,
|
|
||||||
}) if (defined $hash->{I2C_Address});
|
|
||||||
} else {
|
} else {
|
||||||
I2C_PCA9685_UpdReadings($hash, $reg, $data); # Zeile zum testen (Werte werden direkt zu I2CRec umgeleitet)
|
my $delaytime = 0;
|
||||||
#return "no IODev assigned to '$hash->{NAME}'";
|
if ($dimcount < 4095) { #DimmWert anpassen bei anderem Faktor
|
||||||
|
$val = int($val * 4095 / $dimcount);
|
||||||
|
}
|
||||||
|
if (defined $del) { #Delaytime angegeben?
|
||||||
|
return "wrong delay value: $del for \"set $hash->{NAME} Port$port $val $del\" use value between 0 and $dimcount"
|
||||||
|
unless ($del >= 0 && $del <= $dimcount);
|
||||||
|
if ($dimcount < 4095) { #DelayWert anpassen bei anderem Faktor
|
||||||
|
$del = int($del * 4095 / $dimcount);
|
||||||
|
}
|
||||||
|
$delaytime = $del
|
||||||
|
} else { #...wenn nicht aus Reading holen (für all kommt immer 0 raus)
|
||||||
|
$delaytime = ReadingsVal($hash->{NAME},'Port_d'.sprintf ('%02d', $port),"0");
|
||||||
|
}
|
||||||
|
my $LEDx_OFF = $delaytime + $val - (( $val + $delaytime < 4096 ) ? 0 : 4096);
|
||||||
|
if ($LEDx_OFF == $delaytime) { #beide Register dürfen nicht gleichen Inhalt haben, das entpricht "aus"
|
||||||
|
$data = "0 0 0 16";
|
||||||
|
} else {
|
||||||
|
my @LEDx = unpack("C*", pack("S", $delaytime));
|
||||||
|
push @LEDx, unpack("C*", pack("S", $LEDx_OFF)); #Array $LEDx[0] = LEDx_ON_L, $LEDx[1] = LEDx_ON_H, $LEDx[2] = LEDx_OFF_L, $LEDx[3] = LEDx_OFF_H
|
||||||
|
$data = sprintf "%01d " x 4, @LEDx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
#############################################################################
|
#############################################################################
|
||||||
sub I2C_PCA9685_Get($@) { # ---- wie beim reload der Detailseite ausführen
|
sub I2C_PCA9685_Get($@) { # Portwerte bei laden der Datailseite aktualisieren
|
||||||
my ($hash, @a) = @_;
|
my ($hash, @a) = @_;
|
||||||
my $name =$a[0];
|
|
||||||
|
|
||||||
my %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread" );
|
|
||||||
$sendpackage{reg} = 0x6; #startadresse zum lesen
|
I2C_PCA9685_i2cread($hash, 0x6, 64);
|
||||||
$sendpackage{nbyte} = 63;
|
return;
|
||||||
return "$name: no IO device defined" unless ($hash->{IODev});
|
|
||||||
my $phash = $hash->{IODev};
|
|
||||||
my $pname = $phash->{NAME};
|
|
||||||
CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
|
|
||||||
|
|
||||||
|
#my $name =$a[0];
|
||||||
|
#my %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread" );
|
||||||
|
#$sendpackage{reg} = 0x6; #startadresse zum lesen
|
||||||
|
#$sendpackage{nbyte} = 64;
|
||||||
|
#return "$name: no IO device defined" unless ($hash->{IODev});
|
||||||
|
#my $phash = $hash->{IODev};
|
||||||
|
#my $pname = $phash->{NAME};
|
||||||
|
#CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
|
||||||
|
|
||||||
|
}
|
||||||
|
#############################################################################
|
||||||
|
sub I2C_PCA9685_i2cread($$$) { # Lesebefehl an Hardware absetzen (antwort kommt in I2C_*****_I2CRec an)
|
||||||
|
my ($hash, $reg, $nbyte) = @_;
|
||||||
|
if (defined (my $iodev = $hash->{IODev})) {
|
||||||
|
Log3 $hash, 5, "$hash->{NAME}: $hash->{I2C_Address} read $nbyte Byte from Register $reg";
|
||||||
|
CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, {
|
||||||
|
direction => "i2cread",
|
||||||
|
i2caddress => $hash->{I2C_Address},
|
||||||
|
reg => $reg,
|
||||||
|
nbyte => $nbyte
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (AttrVal($hash->{NAME}, "dummy", 0) == 1) {
|
||||||
|
Log3 $hash, 1, "attr dummy -> kann nix lesen";
|
||||||
|
} else {
|
||||||
|
return "no IODev assigned to '$hash->{NAME}'";
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
#############################################################################
|
||||||
|
sub I2C_PCA9685_i2cwrite($$$) { # Schreibbefehl an Hardware absetzen
|
||||||
|
my ($hash, $reg, @data) = @_;
|
||||||
|
if (defined (my $iodev = $hash->{IODev})) {
|
||||||
|
Log3 $hash, 5, "$hash->{NAME}: $hash->{I2C_Address} write join (' ',@data) to Register $reg";
|
||||||
|
CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, {
|
||||||
|
direction => "i2cwrite",
|
||||||
|
i2caddress => $hash->{I2C_Address},
|
||||||
|
reg => $reg,
|
||||||
|
data => join (' ',@data),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (AttrVal($hash->{NAME}, "dummy", 0) == 1) {
|
||||||
|
I2C_PCA9685_UpdReadings($hash, $reg, @data); # Zeile zum testen (Werte werden direkt zu I2CRec umgeleitet)
|
||||||
|
} else {
|
||||||
|
return "no IODev assigned to '$hash->{NAME}'";
|
||||||
|
} }
|
||||||
}
|
}
|
||||||
#############################################################################
|
#############################################################################
|
||||||
sub I2C_PCA9685_I2CRec($@) { # vom IODev aufgerufen
|
sub I2C_PCA9685_I2CRec($@) { # vom IODev aufgerufen
|
||||||
@@ -353,11 +405,7 @@ sub I2C_PCA9685_I2CRec($@) { # vom IODev aufgerufen
|
|||||||
}
|
}
|
||||||
if ($clientmsg->{direction} && defined($clientmsg->{reg}) && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") {
|
if ($clientmsg->{direction} && defined($clientmsg->{reg}) && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") {
|
||||||
if ( $clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received}) ) {
|
if ( $clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received}) ) {
|
||||||
my @rec = split(" ",$clientmsg->{received});
|
I2C_PCA9685_UpdReadings($hash, $clientmsg->{reg} , $clientmsg->{received});
|
||||||
Log3 $hash, 3, "$name: wrong amount of registers transmitted from $pname" unless (@rec == $clientmsg->{nbyte});
|
|
||||||
foreach (reverse 0..$#rec) { #reverse, damit Inputs (Register 0 und 1 als letztes geschrieben werden)
|
|
||||||
I2C_PCA9685_UpdReadings($hash, $_ + $clientmsg->{reg} , $rec[$_]);
|
|
||||||
}
|
|
||||||
readingsSingleUpdate($hash,"state", "Ok", 1);
|
readingsSingleUpdate($hash,"state", "Ok", 1);
|
||||||
} elsif ( $clientmsg->{direction} eq "i2cwrite" && defined($clientmsg->{data}) ) { #readings aktualisieren wenn uebertragung ok
|
} elsif ( $clientmsg->{direction} eq "i2cwrite" && defined($clientmsg->{data}) ) { #readings aktualisieren wenn uebertragung ok
|
||||||
I2C_PCA9685_UpdReadings($hash, $clientmsg->{reg} , $clientmsg->{data});
|
I2C_PCA9685_UpdReadings($hash, $clientmsg->{reg} , $clientmsg->{data});
|
||||||
@@ -403,10 +451,9 @@ sub I2C_PCA9685_CalcVal($@) { # Readings aus Registerwerten berechnen
|
|||||||
return $dimval, $delay;
|
return $dimval, $delay;
|
||||||
}
|
}
|
||||||
#############################################################################
|
#############################################################################
|
||||||
sub I2C_PCA9685_UpdReadings($$$) { # vom IODev gesendete Werte in Readings/Internals schreiben ---- WAS IST WENN MEHRERE PORTS AM STÜCK ABGEFRAGT WERDEN??? (evtl mit einzelabfrage zusammen)
|
sub I2C_PCA9685_UpdReadings($$$) { # vom IODev gesendete Werte in Readings/Internals schreiben
|
||||||
my ($hash, $reg, $inh) = @_;
|
my ($hash, $reg, $inh) = @_;
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
#$inh = hex($inh);
|
|
||||||
#Log3 $hash, 1, "$name UpdReadings Start Register: " .sprintf("0x%.2X", $reg).", Inhalt: $inh";
|
#Log3 $hash, 1, "$name UpdReadings Start Register: " .sprintf("0x%.2X", $reg).", Inhalt: $inh";
|
||||||
my @reginh = split(" ", $inh);
|
my @reginh = split(" ", $inh);
|
||||||
my $dimstep = AttrVal($name, "dimstep", "1");
|
my $dimstep = AttrVal($name, "dimstep", "1");
|
||||||
@@ -425,17 +472,17 @@ sub I2C_PCA9685_UpdReadings($$$) { # vom IODev gesendete Werte in Read
|
|||||||
($dimval, $delay) = I2C_PCA9685_CalcVal($dimcount, @reginh);
|
($dimval, $delay) = I2C_PCA9685_CalcVal($dimcount, @reginh);
|
||||||
readingsBulkUpdate($hash, 'Port'.$port , $dimval) if (ReadingsVal($name, 'Port'.$port, "failure") ne $dimval); #nur wenn Wert geaendert
|
readingsBulkUpdate($hash, 'Port'.$port , $dimval) if (ReadingsVal($name, 'Port'.$port, "failure") ne $dimval); #nur wenn Wert geaendert
|
||||||
readingsBulkUpdate($hash, 'Port_d'.$port , $delay) if (defined $delay && ReadingsVal($name, 'Port_d'.$port, "failure") ne $delay); #nur wenn Wert geaendert
|
readingsBulkUpdate($hash, 'Port_d'.$port , $delay) if (defined $delay && ReadingsVal($name, 'Port_d'.$port, "failure") ne $delay); #nur wenn Wert geaendert
|
||||||
|
Log3 $hash, 5, "$name: lese einen Port - Reg: $reg ; Inh: @reginh";
|
||||||
|
|
||||||
# WAS IST WENN MEHRERE PORTS AM STÜCK ABGEFRAGT WERDEN???
|
} elsif ( $reg < 70 && $reg > 5 && @reginh > 4 ) { #Wenn alle Ports abgefragt werden
|
||||||
} elsif ( $reg < 70 && $reg > 5 && @reginh > 4 ) {
|
|
||||||
for (my $i = 0; $i < @reginh; $i++) {
|
for (my $i = 0; $i < @reginh; $i++) {
|
||||||
next unless ( ($reg + $i - 2) / 4 =~ m/^\d+$/ );
|
next unless ( ($reg + $i - 2) / 4 =~ m/^\d+$/ );
|
||||||
my @regpart = [ $reginh[$i], $reginh[$i + 1], $reginh[$i + 2], $reginh[$i + 3] ];
|
my @regpart = ( $reginh[$i], $reginh[$i + 1], $reginh[$i + 2], $reginh[$i + 3] );
|
||||||
my $port = sprintf ('%02d', ($reg + $i - 6) / 4);
|
my $port = sprintf ('%02d', ($reg + $i - 6) / 4);
|
||||||
($dimval, $delay) = I2C_PCA9685_CalcVal($dimcount, @regpart);
|
($dimval, $delay) = I2C_PCA9685_CalcVal($dimcount, @regpart);
|
||||||
readingsBulkUpdate($hash, 'Port'.$port , $dimval) if (ReadingsVal($name, 'Port'.$port, "failure") ne $dimval); #nur wenn Wert geaendert
|
readingsBulkUpdate($hash, 'Port'.$port , $dimval) if (ReadingsVal($name, 'Port'.$port, "failure") ne $dimval); #nur wenn Wert geaendert
|
||||||
readingsBulkUpdate($hash, 'Port_d'.$port , $delay) if (defined $delay && ReadingsVal($name, 'Port_d'.$port, "failure") ne $delay); #nur wenn Wert geaendert
|
readingsBulkUpdate($hash, 'Port_d'.$port , $delay) if (defined $delay && ReadingsVal($name, 'Port_d'.$port, "failure") ne $delay); #nur wenn Wert geaendert
|
||||||
Log3 $hash, 5, "$name: lese mehrere Ports - Reg: $reg ; i: $i; |$regpart[0]|$regpart[1]|$regpart[2]|$regpart[3]|";
|
Log3 $hash, 5, "$name: lese mehrere Ports - Reg: $reg ; i: $i; Inh: @regpart";
|
||||||
$i += 3;
|
$i += 3;
|
||||||
}
|
}
|
||||||
} elsif ($reg == 254) { #wenn Frequenz Register
|
} elsif ($reg == 254) { #wenn Frequenz Register
|
||||||
@@ -444,12 +491,12 @@ sub I2C_PCA9685_UpdReadings($$$) { # vom IODev gesendete Werte in Read
|
|||||||
} elsif ( $reg >= 0 && $reg < 6 ) { #Konfigurations Register
|
} elsif ( $reg >= 0 && $reg < 6 ) { #Konfigurations Register
|
||||||
$hash->{confregs}{$reg} = $inh;
|
$hash->{confregs}{$reg} = $inh;
|
||||||
#folgendes evtl noch weg
|
#folgendes evtl noch weg
|
||||||
$hash->{CONF} = (defined $hash->{confregs}{0} ? sprintf('0x%.2X ', $hash->{confregs}{0}) : "0x__ ") .
|
#$hash->{CONF} = (defined $hash->{confregs}{0} ? sprintf('0x%.2X ', $hash->{confregs}{0}) : "0x__ ") .
|
||||||
(defined $hash->{confregs}{1} ? sprintf('0x%.2X ', $hash->{confregs}{1}) : "0x__ ") .
|
# (defined $hash->{confregs}{1} ? sprintf('0x%.2X ', $hash->{confregs}{1}) : "0x__ ") .
|
||||||
(defined $hash->{confregs}{2} ? sprintf('0x%.2X ', $hash->{confregs}{2}) : "0x__ ") .
|
# (defined $hash->{confregs}{2} ? sprintf('0x%.2X ', $hash->{confregs}{2}) : "0x__ ") .
|
||||||
(defined $hash->{confregs}{3} ? sprintf('0x%.2X ', $hash->{confregs}{3}) : "0x__ ") .
|
# (defined $hash->{confregs}{3} ? sprintf('0x%.2X ', $hash->{confregs}{3}) : "0x__ ") .
|
||||||
(defined $hash->{confregs}{4} ? sprintf('0x%.2X ', $hash->{confregs}{4}) : "0x__ ") .
|
# (defined $hash->{confregs}{4} ? sprintf('0x%.2X ', $hash->{confregs}{4}) : "0x__ ") .
|
||||||
(defined $hash->{confregs}{5} ? sprintf('0x%.2X ', $hash->{confregs}{5}) : "0x__ ");
|
# (defined $hash->{confregs}{5} ? sprintf('0x%.2X ', $hash->{confregs}{5}) : "0x__ ");
|
||||||
}
|
}
|
||||||
readingsEndUpdate($hash, 1);
|
readingsEndUpdate($hash, 1);
|
||||||
return;
|
return;
|
||||||
@@ -509,6 +556,7 @@ sub I2C_PCA9685_UpdReadings($$$) { # vom IODev gesendete Werte in Read
|
|||||||
refreshes all readings
|
refreshes all readings
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
|
|
||||||
<a name="I2C_PCA9685Attr"></a>
|
<a name="I2C_PCA9685Attr"></a>
|
||||||
<b>Attributes</b>
|
<b>Attributes</b>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -635,6 +683,7 @@ sub I2C_PCA9685_UpdReadings($$$) { # vom IODev gesendete Werte in Read
|
|||||||
Aktualisierung aller Werte
|
Aktualisierung aller Werte
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
|
|
||||||
<a name="I2C_PCA9685Attr"></a>
|
<a name="I2C_PCA9685Attr"></a>
|
||||||
<b>Attribute</b>
|
<b>Attribute</b>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user