Markisensteuerung mit Slider (geht auch für Rolladen)

Begonnen von Elektrolurch, 22 Juni 2014, 13:33:39

Vorheriges Thema - Nächstes Thema

Elektrolurch

Hallo,

gestern habe ich meine Bastelarbeit abgeschlossen und eine Markisensteuerung in Betrieb genommen. Im Grunde genommen, könnte mit der Lösung auch ein Rolladen gesteuert werden.

Funktion:
Die Markise kann sowohl über einen FS20 Sender, als auch über fhem in eine beliebige Position gefahren werden.

set Markise ausfahren
setMarkise einfahren
set Markise Pos <Wert>
Wert = 0...100

Wird die Markise ein- oder ausgefahren, kann durch erneutes Drücken des Schalters gestoppt werden.
Beim Ausfahren werden zwei gespeicherte Zwischenpositionen angefahren, die man wie folgt definiert:
setreading >Markise Pos1 40
setreading Markise Pos2 70

Um die exakte Position (0...100) bestimmen zu können, muss einmal die Zeit für jeweils vollständiges Ein- und Ausfahren gemessen werden. Die wird dann in zwei readings hinterlegt:

setreading Markise Ausfahrzeit 24.6
setreading Markise Einfahrzeit 25.3

Hardware
Der Markisenmotor hat vier Anschlüsse: Erde, Null und jeweils Spannung für Ein- und Ausfahren. Die Spannungsanschlüsse sind mit einem Kipptaster mit Mittelstellung verbunden und wurden nun zusätzlich mit zwei Relais verbunden. Die Ansteuerung der 4 - Kanal Relaiskarte erfolgt über einen FS20 SM8 Funkempfänger (Markise_einfahren, Markise_ausfahren). Damit während der Steuerung durch fhem nicht versehentlich über den Kipptaster der Motor in die andere Richtung gefahren werden kann (bringt den Motor um!), wird über ein weiteres Relais der Kipptaster unterbrochen (Markise_unterbrechen).
Das 4. Relais steuert noch die Terrassenbeleuchtung, die verbleibenden 4 Kanäle des FS20 SM8 schalten mit ihren Open Kollektor Ausgängen jeweils über einen 1 KOhm - Vorwiderstand diverse LEDs und einen Piezopiepser.
Relasikarte, Funkempfänger und Netzteilmodul (9V) wurden auf eine 160 x 100 mm Lochrasterkarte montiert.

Software:
Das Anfahren der Markisenposition erfolgt zeitgesteuert. Da auch während des Verfahrens die Markise gestoppt werden kann, erfolgt die Berechnung der tatsächlichen Position erst nach dem Stoppen der Markise auf Grund der  Zeitdifferenz, zwischen dem Ein- und Ausschalten des Motors. Gesteuert wird dies über den internen Timer von fhem.
Das Einschalten des Markisenmotors wird zwar mit on-for-timer 32 gestartet, ist aber nur eine Obergrenze, damit bei Störungen des Funkverkehrs der Motor nicht dauerhaft unter Strom bleibt (on-for-timer wird im FS20 abgearbeitet).
on-for-timer kann jedoch nicht für die Steuerung verwendet werden, da nicht alle Zeitwerte damit realisiert werden können. (Liegt an dem internen Aufbau des FS20 timers)

Code:

# Markise
define Markise_unterbrechen FS20 21114322 1232
attr Markise_unterbrechen IODev CUL_0
attr Markise_unterbrechen event-on-change-reading .*
attr Markise_unterbrechen eventMap /on:ein/off:aus/
attr Markise_unterbrechen follow-on-for-timer 1
attr Markise_unterbrechen verbose 3

define Markise_ausfahren FS20 21114322 1233
attr Markise_ausfahren IODev CUL_0
attr Markise_ausfahren event-on-change-reading .*
attr Markise_ausfahren eventMap /on:ein/off:aus/
attr Markise_ausfahren follow-on-for-timer 1
attr Markise_ausfahren verbose 3


define Markise_einfahren FS20 21114322 1234
attr Markise_einfahren IODev CUL_0
attr Markise_einfahren event-on-change-reading .*
attr Markise_einfahren eventMap /on:ein/off:aus/
attr Markise_einfahren follow-on-for-timer 1
attr Markise_einfahren verbose 3

# Der Schalter
define Ga_Schalter2 FS20 21114322 1412
attr Ga_Schalter2 IODev CUL_0
attr Ga_Schalter2 eventMap /on:ausfahren/off:einfahren/
attr Ga_Schalter2 verbose 3

# notify für Schalter und dummy der Steuerung
define Ga_Schalter2_not notify (Ga_Schalter2|Markise):.* {Ga_Schalter2_not($NAME,$EVENT);;}

# der dummy mit slider für die Steuerung
define Markise dummy
attr Markise alias Markise
attr Markise group Markise
attr Markise room Garten
attr Markise setList Pos:slider,0,1,100
attr Markise verbose 3
attr Markise webCmd einfahren:Pos:ausfahren

Code für die 99_myUtils oder 99_myUtilsMarkise

# zum Unterdrücken von Events, wenn zwei Funkempfänger installiert sind

sub LastEvent($)
{
my ($d) = @_;
my $rhash = $defs{$d}{READINGS};
my ($s, $ms) = gettimeofday();

my $t = $s + ($ms / 1000000); # 10 msec
my $t1 = 0;
$t1 = $rhash->{'LastEvent'}{VAL} if(exists($rhash->{'LastEvent'} ));
$rhash->{'LastEvent'}{VAL}  = $t;
my $dt = sprintf("%.2f",$t - $t1);
Log(3,"Lastevent: d: $d diff $dt");
return $dt;
} # end sub LastEvent
##########################


sub Markise_Stop($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $mup = Value('Markise_einfahren');
my $mdown = Value('Markise_ausfahren');
my $dt = 0;
my $aktpos = ReadingsVal('Markise','Pos',0);
my $newpos;
Log3($name,3,"mup $mup down $mdown");
if($mup =~m/(ein|on).*/)
{
$dt = time() - time_str2num(ReadingsTimestamp('Markise_einfahren','state',0));
fhem("set Markise_einfahren aus");
$newpos = $aktpos - (100 * $dt / ReadingsVal('Markise','Einfahrzeit',0));
} # Die Markiese fährt bereis
elsif($mdown =~m/(ein|on).*/)
{
$dt = time() - time_str2num(ReadingsTimestamp('Markise_ausfahren','state',0));
fhem("set Markise_ausfahren aus");
$newpos = $aktpos + (100 * $dt / ReadingsVal('Markise','Ausfahrzeit',0));
} # Die Markiese fährt bereis
fhem("set Markise_unterbrechen aus");
$newpos = sprintf("%d",$newpos); # runden
$newpos = 0 if($newpos < 0);
$newpos = 100 if($newpos > 100);
Log3($name,3,"$name _stop: dt $dt newpos $newpos");
readingsSingleUpdate($hash,'Pos',$newpos,0);
readingsSingleUpdate($hash,'state',"Pos $newpos",0);
# alle timer löschen
RemoveInternalTimer($hash);   
return undef;
} # end sub Markise_Stop
##########################



sub Ga_Schalter2_not($$)
{
my ($name,$event) = @_;
$name = 'Markise';
my $hash = $defs{$name};

my $t = LastEvent($name);
Log3($name,3,$name."_not: event $event lastevent $t");
return undef if($t < 1);
my ($rd,$newpos) = split(' ',$event);
($rd) = split(':',$rd);
my $ausfahrzeit = ReadingsVal('Markise','Ausfahrzeit',23.6);
my $einfahrzeit = ReadingsVal('Markise','Einfahrzeit',24.7);
my $aktpos = ReadingsVal('Markise','Pos',0);
my $fahrzeit = 0;

my $mup = Value('Markise_einfahren');
my $mdown = Value('Markise_ausfahren');
if(($mup =~m/(ein|on).*/) || ($mdown =~m/(ein|on).*/))
{
Markise_Stop($hash);
Log3($name,3,"Markisenfahrt ein/aus fahren gestoppt über Schalter");
return undef;
} # Die Markiese fährt bereis

# Markise fahren
if($event eq 'einfahren')
{
$newpos = 0;
$rd = 'Pos';
} # Die Markiese wird eingefahren
elsif($event eq 'ausfahren')
{
my $p1 = ReadingsVal('Markise','Pos1',40);
my $p2 = ReadingsVal('Markise','Pos2',60);

$newpos = $p1 if($aktpos < $p1);
$newpos = $p2 if(($aktpos >= $p1) && ($aktpos < $p2));
$newpos = 90 if($aktpos >= $p2);
$rd = 'Pos';
} # Die Markiese wird ausgefahren

# Sicherheitsabfragen

return "Markise: newpos nicht definiert" if(!defined($newpos));
return "Markise: Falsche Position $newpos 0...100" if(($newpos < 0) || ($newpos > 100));
return "Markise: gleiche Position $newpos" if(($aktpos > 0) && ($aktpos == $newpos));
return "Markise: $rd nicht implementiert" if($rd ne 'Pos');

if($newpos > $aktpos) # ausfahren
{
my $fz = ($newpos - $aktpos) * $ausfahrzeit / 100;
$fahrzeit = sprintf("%d",$fz);
Log3($name,3,"Markisenfahrt ausfahren gestartet Aktpos $aktpos newpos $newpos Fahrzeit: $fahrzeit");
return "Fahrtzeit 0"  if ($fahrzeit == 0);
return "Markise Fahrtzeit $fahrzeit falsch" if($fahrzeit > 25);
fhem("set Ga_Piepser on-for-timer 0.25");
fhem("set Markise_unterbrechen on-for-timer 32");
fhem("set Markise_ausfahren on-for-timer 32");
# fhem("set Ga_Piepser aus");
}
else # einfahren
{
my $fz = ($aktpos - $newpos) * $einfahrzeit / 100;
$fz = 10 if($fz == 0);
# falls Kalibirierung auf Grund von Handbetrieb nicht stimmt, trotzdem einfahren.

$fahrzeit = sprintf("%d",$fz  );
Log3($name,3,"Markisenfahrt einfahren gestartet aktpos $aktpos newpos $newpos Fahrzeit: $fahrzeit");
return "Fahrzeit 0"  if ($fahrzeit == 0);
return "Markise: Fahrzeit $fahrzeit falsch" if($fahrzeit > 25);
fhem("set Ga_Piepser on-for-timer 0.25");
fhem("set Markise_unterbrechen on-for-timer 32");
fhem("set Markise_einfahren on-for-timer 32");
# fhem("set Ga_Piepser aus");
} # end else
InternalTimer(gettimeofday()+ $fahrzeit, "Markise_Stop", $hash, 0);

# Zeit aktualisieren, um Doppelklick zu vermeiden
LastEvent($name);
return undef;
} # end sub Ga_Schalter2_not
#######################################


configDB und Windows befreite Zone!

HoTi

Hallo,

ich habe mal deinen Code versucht. Allerdings mit einem 4 Fach Schalter von Homematic.

Allerdings habe ich die Relais gegenseitig verriegelt und benutze die internen Taster des Aktors.

Ich habe deinen Code noch nicht ganz verstanden.
Als erstes weiß ich nicht so genau was die ganzen Attribute machen.

Hier mal einen Teil für Homatic

define Markise_unterbrechen CUL_HM 28A47C02
attr Markise_unterbrechen model HM-LC-SW4-BA-PCB
attr Markise_unterbrechen peerIDs 00000000,
attr Markise_unterbrechen event-on-change-reading .*
attr Markise_unterbrechen eventMap /on:ein/off:aus/
#attr Markise_unterbrechen follow-on-for-timer 1
attr Markise_unterbrechen verbose 3


Vor allem sind mir die Attribute unklar

attr Markise_unterbrechen event-on-change-reading .*
#attr Markise_unterbrechen follow-on-for-timer 1



Das zweite musste ich auch raus nehmen weil das nicht funktioniert hat.

Kann mir da jemand ein wenig helfen?!

Viele Grüße
Tim
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Elektrolurch

Hallo,

zu den Attributen:
attr Markise_unterbrechen event-on-change-reading .*
#attr Markise_unterbrechen follow-on-for-timer 1

event-on-change-reading hat hier keine Bedeutung, da der Taster ja nur sendet. Ich habe dass einfach für fast alle devices bei mir im Haus als Standard gesetzt, da ich zwei CULs im Einsatz habe und somit alle Events auch zweimal bekomme, aber ja nur einmal - und das bei Änderungen - sie bearbeiten möchte.

Das folllow-on-timer hat folgende Bedeutung (FS20):

Da kann man  einen set Befehl senden, der den FS20 - Aktor nur für eine Zeitspanne einschaltet und sich danach ohne fhem wieder ausschaltet. Damit fhem aber den Statuswechsel mitbekommt, wird es über das Attribut veranlasst,  selbst einen internen Timer zu starten.

Das Attribut habe ich aber jetzt auskommentiert, da ich die Zeitspanne über fhem setze und zwar genauer als 1 Sekunde. Daher funktioniert meine Lösung nur für FS20 Aktoren. Für Homematic müsste man da wohl einige Anpassungen machen.

Gruß

Elektrolurch

configDB und Windows befreite Zone!

Pfriemler

#3
Hallo Tim, BTW: hast Du mal die Sig des Themenerstellers gelesen?

Ergänzend zu Elektrolurch: HomeMatic-Aktoren liefern ihren Status retour, so dass man in FHEM dafür keine Klimmzüge machen muss. Die entsprechende Funktion können wir weglassen.
An der Umsetzung des Codes auf Homematic bin ich teilweise interessiert, könnte ich doch so mein Garagentor etwas intelligenter steuern ... im Moment fehlt die Zeit.
Den Rest hätte ich schöner nicht sagen können ...

@Elektrolurch:
Wirklich schönes Ding. Hast Du die beiden Aktorenausgänge noch gegeneinander gesichert gegen Doppelauslösung (z.B. bei Programmfehlern; mit den NC-Kontakten der Relais müsste das einfach gehen)?
"Änd're nie in fhem.cfg, denn das tut hier allen weh!" *** Wheezy@Raspi(3), HMWLAN+HMUART, CUL868(SlowRF) für FHT+KS+FS20, miniCUL433, Rademacher DuoFern *** "... kaum macht man es richtig, funktioniert es ..."

Elektrolurch

Hallo,

das ist das "Markise_unterbrechen". Der Kontakt unterbricht die Stromzufuhr zum manuellen Wandschalter.
Programmfehler? Gibt es nicht, zumindest keine, die die beiden Richtungen des Motors gleichzeitig einschalten :-)
Zur Absicherung sende ich zusätzlich nur on-for-timer an den FS20, wobei die Zeit etwas größer ist, als von fhem das "off" Signal käme. Sollte aus irgendeinem Grund mal kein "off" beim Erreichen der gewünschten Position beim Aktor ankommen, schaltet der wenigsten von selbst nach einer Zeitspanne ab oder fährt auf den Endkontakt der Markise.

Die internen Zeiten, die die FS20 im timer-Betrieb können, sind immer irgendwas mit x**2, so dass man für eine Positionierung das nicht sinnvoll verwenden kann. Zeitweilig hatte ich erhebliche Reaktionszeiten, bis nach Aktivierung von fhem aus die Relais tatsächlich anzogen.
Das liegt daran, das fhem beim set-Befehl durch den ganzen Objektbaum durchäuft... usw.

Daher hatte ich da eine Abkürzung genommen mit dem DoCommandSet (?)
...
Ich habe die SW gerade nicht hier, muss mal sehen, was tatsächlich für Homematik anzupassen wäre.

Gruß

Elektrolurch
configDB und Windows befreite Zone!

HoTi

Das wäre super Elektrolurch,

mit meinem umgebauten Code stürzt FHEM ab und ich muss es über die Konsole neu Reseten.

Vg
Tim
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

igami

Hi Zusmamen,

wenn ich demnächst mal etwas Zeit finde werde ich mich auch dem Thema widmen.
Allerdings haben wir bei uns Jalousien im EIB, auch mit "Devices" angelegt, einmal hoch/runter, bis in die Endlage, das andere nur ein tippen.
Was ich mir dabei noch vorstelle ist, dass man zusätzlich zur Position noch den Öffnungswinkel angeben kann. Sodass ich sagen kann, Jalousie komplett geschlossen, die Lamellen stehen aber waagerecht, sodass trotzdem Licht einfällt.

Aber wie gesagt, erst wenn  Zeit ist, funktioniert ja momentan auch manuell :)

Grüße
Igami
Pi3 mit fhem.cfg + DbLog/logProxy
Komm vorbei zum FHEM Treffen im Kreis Gütersloh! Das nächste Mal im April 2020.

MAINTAINER: archetype, LuftdatenInfo, monitoring, msgDialog, Nmap, powerMap
ToDo: AVScene, FluxLED

Pfriemler

Zitat von: Elektrolurch am 10 September 2014, 10:46:26
das ist das "Markise_unterbrechen". Der Kontakt unterbricht die Stromzufuhr zum manuellen Wandschalter.
Programmfehler? Gibt es nicht, zumindest keine, die die beiden Richtungen des Motors gleichzeitig einschalten :-)

Das meinte ich nicht - für die Abtrennung des Wandschalters hatte ich spontan auch keine Idee. Ich meine wirklich eine Absicherung der beiden steuernden Aktorkanäle gegen gleichzeitiges Auslösen. Und sei's, dass ein Dummy mal dran rumfingert - oder das Relaismodul einen Spinner kriegt. In Worten beschrieben: Beide Relais als Umschaltkontakt. Ausgänge zum Markisenmodul auf den NO (normally open). Statt nun die Steuerplus auf die Commons der Umschalter zu legen, einfach zweimal Steuerplus am NC (normally closed) und beide Commons miteinander verbinden. Ein aktiver Aktor liefert dann an das Markisenmodul Saft über den Ruhestromkontakt des inaktiven Aktors. Sollten zufällig mal doch beide anziehen, ist das Plus weg. Zwar werden dann die Steuereingänge des Markisenmoduls miteinander verbunden, aber das sollte unschädlich sein.
"Änd're nie in fhem.cfg, denn das tut hier allen weh!" *** Wheezy@Raspi(3), HMWLAN+HMUART, CUL868(SlowRF) für FHT+KS+FS20, miniCUL433, Rademacher DuoFern *** "... kaum macht man es richtig, funktioniert es ..."

HoTi

Ich bekomme es nicht hin.

Bei mir blinken die Ausgänge nur und FHEM stürzt ab.

Hat jemand eine Idee woran das liegen kann. bzw. wie ich gutes Logfile machen kann?!

Vg
Tim
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Elektrolurch

Es werden zusätzliche Informationen benötigt oder ich würde empfehlen, das Orakel von Delphi zu befragen.
configDB und Windows befreite Zone!

HoTi

hihi das Orakel ist gut.

Aber das war auch meine Frage. Welche Informationen brauchst du und wo bekomme ich die.
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Elektrolurch

Na, die Softwarelösung von mir betreibt eine Relaiskarte über einen FS20 SM8 Empfänger. Das muss natürlich  in irgendeiner Form an Deine Lösung angepasst werden.
Und wenn Du schreibst, dass es nur blinkt....
Bei meiner Nachbarin blinkt es auch, wenn die die Wäsche auf die Leine hängt.

Elektrolurch
configDB und Windows befreite Zone!

HoTi

Hallo Elektrolurch,

ich versuche gerade dein Code zu verstehn. Leider noch mit Fragen:

Was macht "Der Schalter" (Ga_Schalter2)? Ist das ein Taster? Was ist das für eine Komponente ich habe die nicht aus deiner Beschreibung identifizieren können.

Viele Grüße
Tim
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

HoTi

Hallo nochmal,

ich habe das nun mit Dummy nachgebaut.

Wenn ich nun die Markiese runter fahre kann FHEM nicht mehr erreicht werden. (restart über Konsole notwendig)

Nach dem neustart steht folgendes im Log file:

Lastevent: d: Markise diff 1413287890.14
Markise_not: event /ausfahren lastevent 1413287890.14
Ga_Schalter2_not return value: Markise: newpos nicht definiert
Lastevent: d: Markise diff 1413287896.21
Markise_not: event aus/ lastevent 1413287896.21
Ga_Schalter2_not return value: Markise: newpos nicht definiert
Lastevent: d: Markise diff 1413287900.42
Markise_not: event Pos 18 lastevent 1413287900.42
Markisenfahrt ausfahren gestartet Aktpos 0 newpos 18 Fahrzeit: 4
Lastevent: d: Markise diff 0.02
mup aus/ down ein-for-timer 32

mein Code sieht so aus:

setreading Markise Ausfahrzeit 10.0
setreading Markise Einfahrzeit 10.0

# Markise
define Markise_unterbrechen dummy
attr Markise_unterbrechen room Garten
attr Markise_unterbrechen event-on-change-reading .*
attr Markise_unterbrechen eventMap /on:ein/off:aus/
attr Markise_unterbrechen webCmd /on:ein/off:aus/
attr Markise_unterbrechen verbose 3

define Markise_ausfahren dummy
attr Markise_ausfahren room Garten
attr Markise_ausfahren event-on-change-reading .*
attr Markise_ausfahren eventMap /on:ein/off:aus/
attr Markise_ausfahren webCmd /on:ein/off:aus/
attr Markise_ausfahren verbose 3


define Markise_einfahren dummy
attr Markise_einfahren room Garten
attr Markise_einfahren event-on-change-reading .*
attr Markise_einfahren eventMap /on:ein/off:aus/
attr Markise_einfahren webCmd /on:ein/off:aus/
attr Markise_einfahren verbose 3

# Der Schalter
define Ga_Schalter2 dummy
attr Ga_Schalter2 room Garten
attr Ga_Schalter2 eventMap /on:ausfahren/off:einfahren/
attr Ga_Schalter2 webCmd /on:ein/off:aus/
attr Ga_Schalter2 verbose 3

# notify für Schalter und dummy der Steuerung
define Ga_Schalter2_not notify (Ga_Schalter2|Markise):.* {Ga_Schalter2_not($NAME,$EVENT);;}

# der dummy mit slider für die Steuerung
define Markise dummy
attr Markise alias Markise
attr Markise group Markise
attr Markise room Garten
attr Markise setList Pos:slider,0,1,100
attr Markise verbose 3
attr Markise webCmd einfahren:Pos:ausfahren



meine 99_myUtils.pm:


# zum Unterdrücken von Events, wenn zwei Funkempfänger installiert sind

sub LastEvent($)
{
my ($d) = @_;
my $rhash = $defs{$d}{READINGS};
my ($s, $ms) = gettimeofday();

my $t = $s + ($ms / 1000000); # 10 msec
my $t1 = 0;
$t1 = $rhash->{'LastEvent'}{VAL} if(exists($rhash->{'LastEvent'} ));
$rhash->{'LastEvent'}{VAL}  = $t;
my $dt = sprintf("%.2f",$t - $t1);
Log(3,"Lastevent: d: $d diff $dt");
return $dt;
} # end sub LastEvent
##########################


sub Markise_Stop($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $mup = Value('Markise_einfahren');
my $mdown = Value('Markise_ausfahren');
my $dt = 0;
my $aktpos = ReadingsVal('Markise','Pos',0);
my $newpos;
Log3($name,3,"mup $mup down $mdown");
if($mup =~m/(ein|on).*/)
{
$dt = time() - time_str2num(ReadingsTimestamp('Markise_einfahren','state',0));
fhem("set Markise_einfahren aus");
$newpos = $aktpos - (100 * $dt / ReadingsVal('Markise','Einfahrzeit',0));
} # Die Markiese fährt bereis
elsif($mdown =~m/(ein|on).*/)
{
$dt = time() - time_str2num(ReadingsTimestamp('Markise_ausfahren','state',0));
fhem("set Markise_ausfahren aus");
$newpos = $aktpos + (100 * $dt / ReadingsVal('Markise','Ausfahrzeit',0));
} # Die Markiese fährt bereis
fhem("set Markise_unterbrechen aus");
$newpos = sprintf("%d",$newpos); # runden
$newpos = 0 if($newpos < 0);
$newpos = 100 if($newpos > 100);
Log3($name,3,"$name _stop: dt $dt newpos $newpos");
readingsSingleUpdate($hash,'Pos',$newpos,0);
readingsSingleUpdate($hash,'state',"Pos $newpos",0);
# alle timer löschen
RemoveInternalTimer($hash);   
return undef;
} # end sub Markise_Stop
##########################



sub Ga_Schalter2_not($$)
{
my ($name,$event) = @_;
$name = 'Markise';
my $hash = $defs{$name};

my $t = LastEvent($name);
Log3($name,3,$name."_not: event $event lastevent $t");
return undef if($t < 1);
my ($rd,$newpos) = split(' ',$event);
($rd) = split(':',$rd);
my $ausfahrzeit = ReadingsVal('Markise','Ausfahrzeit',23.6);
my $einfahrzeit = ReadingsVal('Markise','Einfahrzeit',24.7);
my $aktpos = ReadingsVal('Markise','Pos',0);
my $fahrzeit = 0;

my $mup = Value('Markise_einfahren');
my $mdown = Value('Markise_ausfahren');
if(($mup =~m/(ein|on).*/) || ($mdown =~m/(ein|on).*/))
{
Markise_Stop($hash);
Log3($name,3,"Markisenfahrt ein/aus fahren gestoppt über Schalter");
return undef;
} # Die Markiese fährt bereis

# Markise fahren
if($event eq 'einfahren')
{
$newpos = 0;
$rd = 'Pos';
} # Die Markiese wird eingefahren
elsif($event eq 'ausfahren')
{
my $p1 = ReadingsVal('Markise','Pos1',40);
my $p2 = ReadingsVal('Markise','Pos2',60);

$newpos = $p1 if($aktpos < $p1);
$newpos = $p2 if(($aktpos >= $p1) && ($aktpos < $p2));
$newpos = 90 if($aktpos >= $p2);
$rd = 'Pos';
} # Die Markiese wird ausgefahren

# Sicherheitsabfragen

return "Markise: newpos nicht definiert" if(!defined($newpos));
return "Markise: Falsche Position $newpos 0...100" if(($newpos < 0) || ($newpos > 100));
return "Markise: gleiche Position $newpos" if(($aktpos > 0) && ($aktpos == $newpos));
return "Markise: $rd nicht implementiert" if($rd ne 'Pos');

if($newpos > $aktpos) # ausfahren
{
my $fz = ($newpos - $aktpos) * $ausfahrzeit / 100;
$fahrzeit = sprintf("%d",$fz);
Log3($name,3,"Markisenfahrt ausfahren gestartet Aktpos $aktpos newpos $newpos Fahrzeit: $fahrzeit");
return "Fahrtzeit 0"  if ($fahrzeit == 0);
return "Markise Fahrtzeit $fahrzeit falsch" if($fahrzeit > 25);
fhem("set Markise_unterbrechen on-for-timer 32");
fhem("set Markise_ausfahren on-for-timer 32");
}
else # einfahren
{
my $fz = ($aktpos - $newpos) * $einfahrzeit / 100;
$fz = 10 if($fz == 0);
# falls Kalibirierung auf Grund von Handbetrieb nicht stimmt, trotzdem einfahren.

$fahrzeit = sprintf("%d",$fz  );
Log3($name,3,"Markisenfahrt einfahren gestartet aktpos $aktpos newpos $newpos Fahrzeit: $fahrzeit");
return "Fahrzeit 0"  if ($fahrzeit == 0);
return "Markise: Fahrzeit $fahrzeit falsch" if($fahrzeit > 25);
fhem("set Markise_unterbrechen on-for-timer 32");
fhem("set Markise_einfahren on-for-timer 32");
} # end else
InternalTimer(gettimeofday()+ $fahrzeit, "Markise_Stop", $hash, 0);

# Zeit aktualisieren, um Doppelklick zu vermeiden
LastEvent($name);
return undef;
} # end sub Ga_Schalter2_not
#######################################
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

HoTi

#14
Hallo Elektrolurch,

kannst du mir helfen? Ich teste alles mit Dummys.

Der Fehler scheint hier:
$newpos = $aktpos + (100 * $dt / ReadingsVal('Markise','Ausfahrzeit',0));
bzw.
$newpos = $aktpos - (100 * $dt / ReadingsVal('Markise','Einfahrzeit',0));

zu liegen. Aber an dieser stelle habe ich den Code nicht richtig verstanden.
Ich habe mir mal ein paar Variablen angelegt und dadurch weiß ich das (ReadingsVal('Markise','Ausfahrzeit',0)) immer 0 ergibt.
Was bedeutet das es eine Division durch 0 ist :-(

hier mal der Log, ich habe das Datum und die Uhrzeit wegen deinem Screenreader entfernt:

Cmd: >set Markise Pos 28<
Triggering Markise (1 changes)
Notify loop for Markise Pos 28
Triggering Ga_Schalter2_not
Ga_Schalter2_not exec {Ga_Schalter2_not($NAME,$EVENT);;}
Cmd: >{Ga_Schalter2_not($NAME,$EVENT);}<
Lastevent: d: Markise diff 1414057951.94
Markise_not: event Pos 28 lastevent 1414057951.94
Markisenfahrt ausfahren gestartet Aktpos 0 newpos 28 Fahrzeit: 6
Cmd: >set Markise_unterbrechen on-for-timer 32<
Triggering Markise_unterbrechen (1 changes)
Notify loop for Markise_unterbrechen ein-for-timer 32
eventTypes: dummy Markise_unterbrechen ein-for-timer 32 -> ein-for-timer .*
eventTypes: dummy Markise_unterbrechen state: on-for-timer 32 -> state: on-for-timer .*
Cmd: >set Markise_ausfahren on-for-timer 32<
Triggering Markise_ausfahren (1 changes)
Notify loop for Markise_ausfahren ein-for-timer 32
eventTypes: dummy Markise_ausfahren ein-for-timer 32 -> ein-for-timer .*
eventTypes: dummy Markise_ausfahren state: on-for-timer 32 -> state: on-for-timer .*
Lastevent: d: Markise diff 0.02
eventTypes: dummy Markise Pos 28 -> Pos .*
/fhem?cmd=set%20Markise%20Pos%2028&room=Garten&XHR=1 / RL:20 / text/plain; charset=UTF-8 / Content-Encoding: gzip
/
HTTP FHEMWEB:192.109.190.88:37793 GET /fhem/images/default/on-for-timer.png
Connection closed for FHEMWEB:192.109.190.88:37793
mup ??? down ein-for-timer 32
Cmd: >set Markise_ausfahren aus<
Triggering Markise_ausfahren (1 changes)
Notify loop for Markise_ausfahren aus
eventTypes: dummy Markise_ausfahren aus -> aus
eventTypes: dummy Markise_ausfahren state: off -> state: off

Viele Grüße aus  Oberbayern
Tim (RettungsTim)