Beiträge anzeigen

Diese Sektion erlaubt es ihnen alle Beiträge dieses Mitglieds zu sehen. Beachten sie, dass sie nur solche Beiträge sehen können, zu denen sie auch Zugriffsrechte haben.


Nachrichten - mattsches

Seiten: 1 ... 13 14 [15] 16 17 18
211
Modulentwicklung / Module Development / Re: EHZ Zähler auslesen
« am: 14. Januar 2015, 22:36:11 »
Hallo Ralf,

ich mache das mit meinem EMH (EnBW) und meiner Beckhoff mit einem Schmalspur-(nur die beiden Zähler 1.8.0 und 2.8.0 sowie die aktuelle Leistung werden ausgelesen) Baustein so:

FUNCTION_BLOCK EMH_Meter
VAR_INPUT
bTrigger : BOOL; (* externer Trigger für Ausgabe der aktuellen Zählerdaten *)
END_VAR
VAR_OUTPUT
rIncomingEnergy : REAL; (* Bezugszähler in kWh *)
rOutgoingEnergy : REAL; (* Einspeisezähler in MWh *)
rAvailablePower : REAL; (* aktuell verfügbare Leistung in W; positiv: Einspeisung, negativ: Bezug *)
bNewDataReceived : BOOL; (* new data received from meter *)
END_VAR
VAR
KL6Control_COM2 : SerialLineControl;
bError_COM2 : BOOL;
udErrorId_COM2 : UDINT;

fbReceiveData : ReceiveData;

aPrefix : ARRAY[0..7] OF BYTE := 16#1B, 16#1B, 16#1B, 16#1B, 16#01, 16#01, 16#01, 16#01;
aSuffix : ARRAY[0..5] OF BYTE := 16#1B, 16#1B, 16#1B, 16#1B, 16#1A, 16#01;
aReceiveData : ARRAY[0..511] OF BYTE := 256(0);

pValueFromMeter : POINTER TO DINT;
aValueFromMeter : ARRAY[0..3] OF BYTE;

rBufIncomingEnergy : REAL; (* Puffer für Bezugszähler in kWh *)
rBufOutgoingEnergy : REAL; (* Puffer für Einspeisezähler in MWh *)
rBufAvailablePower : REAL; (* Puffer für aktuell verfügbare Leistung in W; positiv: Einspeisung, negativ: Bezug *)

END_VAR

(* COM2-Schnittstelle ansteuern *)
KL6Control_COM2(
Mode := SERIALLINEMODE_PC_COM_PORT,
pComIn := ADR(Com2InData),
pComOut := ADR(Com2OutData),
SizeComIn := SIZEOF(Com2InData),
TxBuffer := TxBuffer_COM2,
RxBuffer := RxBuffer_COM2,
Error => bError_COM2,
ErrorID => udErrorId_COM2);

(* Telegramm aus Empfangspuffer holen, Erkennung mittels Präfix und Suffix *)
fbReceiveData(
pPrefix:= ADR(aPrefix),
LenPrefix:= 8,
pSuffix:= ADR(aSuffix),
LenSuffix:= 6,
pReceiveData:= ADR(aReceiveData),
SizeReceiveData:= SIZEOF(aReceiveData),
Timeout:= t#700ms,
Reset:= ,
RXbuffer:= RxBuffer_COM2,
DataReceived=> ,
busy=> ,
Error=> ,
RxTimeout=> ,
LenReceiveData=> );

bNewDataReceived := FALSE;

(* Daten aufbereiten, wenn empfangen *)
IF fbReceiveData.DataReceived THEN
bNewDataReceived := TRUE;

(* aktuelle Werte aus empfangenem Byte-String auslesen *)
(* Byte-Reihenfolge ist gegenüber Codesys gedreht! *)
pValueFromMeter := ADR(aValueFromMeter); (* Zeiger auf Zwischenspeicher vorbereiten *)

(* Bezugszähler: Bytes 156-159 *)
aValueFromMeter[0] := aReceiveData[159]; (* Bezugszähler in 0,1 Wh *)
aValueFromMeter[1] := aReceiveData[158];
aValueFromMeter[2] := aReceiveData[157];
aValueFromMeter[3] := aReceiveData[156];
rBufIncomingEnergy := DINT_TO_REAL(pValueFromMeter^)/10000; (* skaliert auf kWh *)

(* Einspeisezähler: Bytes 180-183 *)
aValueFromMeter[0] := aReceiveData[183]; (* Bezugszähler in 0,1 Wh *)
aValueFromMeter[1] := aReceiveData[182];
aValueFromMeter[2] := aReceiveData[181];
aValueFromMeter[3] := aReceiveData[180];
rBufOutgoingEnergy := DINT_TO_REAL(pValueFromMeter^)/10000000; (* skaliert auf MWh *)

(* aktuelle Leistung: Bytes 284-287 *)
(* positiver Wert=Bezug, negativer Wert=Einspeisung *)
aValueFromMeter[0] := aReceiveData[287]; (* aktuelle Leistung in 0,1 W *)
aValueFromMeter[1] := aReceiveData[286];
aValueFromMeter[2] := aReceiveData[285];
aValueFromMeter[3] := aReceiveData[284];
rBufAvailablePower := DINT_TO_REAL(pValueFromMeter^)/10*-1;
END_IF

(* Daten ausgeben, wenn angefordert *)
IF bTrigger THEN
rIncomingEnergy := rBufIncomingEnergy;
rOutgoingEnergy := rBufOutgoingEnergy;
rAvailablePower := rBufAvailablePower;
END_IF

Kann aber gut sein, dass das für deinen Zähler nicht passt.

Die Werte übernehme ich mit einem externen Trigger (=Daten vom Wechselrichter erhalten); einfach die Abfrage "IF bTrigger..." rausschmeißen, wenn nicht gewünscht bzw. den ganzen Block löschen und direkt in die Ausgangsvariablen schreiben.

Zum Auslesen benutzte ich eine super simple Schaltung aus je einem Fototransistor und Widerstand, angelehnt an die Infos von armin63 hier: http://www.photovoltaikforum.com/datenlogger-f5/hager-ehz-auslesen-t57405.html. Kostet 'n Appel. Nicht mal mit Ei.

Gruß,
mattsches

212
Servus,

du liegst mit deiner Beobachtung richtig, der BLIND_INPUT hat diesbezüglich eine Lücke. Sollte sich aber recht einfach schließen lassen, siehe hier:
http://www.oscat.de/community/index.php/topic,2297.0.html

Gruß,
mattsches

213
oscat.lib fuer TwinCAT/CoDeSys / Re: Blind_Input mit Single Click
« am: 14. Januar 2015, 22:11:55 »
Hallo Tobias,

du hast vergessen zu erwähnen, dass du den BLIND_INPUT mit SINGLE_SWITCH=TRUE betreibst. Da hat er tatsächlich eine Lücke, POS wird nicht ausgewertet, um die von dir gewünschte Richtungsumkehr automatisch zu machen, wenn der Laden z. B. durch den BLIND_NIGHT geschlossen wurde. Dazu könnte man in den BLIND_INPUT eine Flankenerkennung auf POS <= 0 einbauen, die dann dir := TRUE setzt.

Damit der Laden morgens automatisch hochfährt, muss am BLIND_INPUT MASTER_MODE = TRUE sein.

Gruß,
mattsches

214
Das geht schon so. Bis auf einen Tippfehler, es müsste heißen

IF OTHER_NIGHT_POS_AKTIV = TRUE

oder einfach nur

IF OTHER_NIGHT_POS_AKTIV

":=" ist eine Wertzuweisung; an dieser Stelle führt das zu einem Übersetzungsfehler. Und du musst das Ganze natürlich vor der Zuweisung an PO packen.

Folgende Anregungen noch:

- SPEZ_NIGHT_POS würde ich in den VAR_INPUT CONSTANT-Block reinpacken. Dann verschwindet das Beinchen in CFC, und du kannst den gewünschten Wert zusammen mit den anderen Einstellungen per Doppelklick auf den Block einstellen.

- NIGHT_POSITION ist ein Eingangsparameter, den du intern bedingt überschreibst. Funktioniert, ist aber nicht so richtig guter Stil. Ich würde es wohl so machen:

(* shade at night only in auto mode and enable = true *)
IF UP AND DN AND night THEN
status := 141;
IF ENABLE_VENTINGPOS AND NOT WINDOW_SWITCH THEN (* open shade slightly if venting position is enabled and window is opened *)
po := venting_position;
ao := venting_angle;
ELSIF OTHER_NIGHT_POS_AKTIV THEN (* use special night position *)
po := SPEZ_NIGHT_POS;
ao := night_angle;
ELSE (* set standard night position when not venting *)
po := night_position;
ao := night_angle;
END_IF
ELSE
po := pi;
ao := ai;
status := s_in;
END_IF;
QU := UP;
QD := DN;

Viel Spaß,
mattsches

215
Ja, genau. Klassischer Tippfehler.

Dass der BLIND_NIGHT nach Ablauf des Timeouts für den Handbetrieb wieder seine Position aktiviert, liegt tatsächlich an der deaktivierten ersten IF-Abfrage. Die bewirkt nämlich, dass sich der BLIND_NIGHT bei einem nächtlichen Handeingriff bis zum nächsten Abend abschaltet. Dann bleibt der Laden auch nach Ablauf des Timeouts oben. Aber er fährt morgens eben nicht automatisch hoch, wenn er nachts manuell geöffnet und wieder geschlossen wurde. Die beiden Anforderungen wirdersprechen sich also.

Denkbar wäre ein Mechanismus, der das manuelle Schließen versucht zu erkennen und den BLIND_NIGHT wieder aktiv schaltet. Aber ganz trivial ist das nicht. Was wäre das Erkennungskriterium? NIGHT_POS wieder erreicht? Nahezu unmöglich, wenn hierfür nicht 0 sondern z. B. 15 hinterlegt ist. Man könnte auch den Status beobachten. Und wenn der Laden manuell oder per Klick-Betrieb für eine gewisse Zeit abwärts bewegt wird den BLIND_NIGHT wieder aktivieren.

Es gäbe aber auch zwei einfache Abhilfen: Timeout verlängern. Oder länger schlafen.  ;)

216
Kannst du noch einen Screenshot machen bei geöffnetem Fenster? Möglichst so, dass man die Ausgänge Status und PO des BLIND_NIGHT_SD erkennen kann. Danke!

217
@NightWatcher:
Sorry, jetzt hatte ich euch beide durcheinander gebracht und deinen Post auf den Screenshot von Sven bezogen. Mein Fehler.
Dennoch habe ich Schwierigkeiten mit Deiner Darstellung. Was meinst du mit "Ist der Zyklus z. B. 1 sek."? Verstellst du die Bearbeitungszeit der Task, in der der CFC-Plan aufgerufen wird? Das hat auf die Flankenerkennung grundsätzlich keinen Einfluss. Wichtig ist lediglich, dass der F_TRIG in derselben Task aufgerufen wird wie das Quellsignal aktualisiert wird. In deinem Screenshot hier http://www.oscat.de/community/index.php/topic,2252.msg11798.html#msg11798 ist das aber der Fall. Man sieht allerdings auch, dass die Bearbeitungsreihenfolge nicht stimmt, der F_TRIG wird vor dem Vergleicher aufgerufen. Ich würde mal Extras/Reihenfolge.../Nach Datenfluss anordnen ausführen.
Hast du meine Vorschläge hier http://www.oscat.de/community/index.php/topic,2252.msg11801.html#msg11801 denn schon ausprobiert? Brauchst du überhaupt weitere Unterstützung?

@Sven:
Bezieht sich deine Aussage von wegen Oberhand schon auf den modifizierten BLIND_NIGHT? Kaum, oder? Wichtig dazu noch, die ganze Beschaltung an IN und PI inkl. F_TRIG etc. fliegt dann raus. Nur falls das nicht schon klar war.
Ich schlage vor, du testest damit mal. Um zur vorherigen Variante hier http://www.oscat.de/community/index.php/topic,2252.msg11806.html#msg11806 und deren Verhalten etwas sagen zu können, bräuchte ich noch Infos zu meinen Fragen oben (Logik des Fensterkontaktes, verschaltete Konstante an PI).

Grüße,
mattsches

218
Servus nochmal,

ich war schon dabei, dir ein CFC-Beispiel zu bauen. Da fiel mir auf, dass der Vorschlag eigentlich Schwachsinn ist und die Lösung durch Modifikation des BLIND_NIGHT viel eleganter geht. Du hast den Baustein ja eh schon angepasst, oder? Dann bau doch mal folgendes mit dazu:

FUNCTION_BLOCK BLIND_NIGHT
VAR_INPUT
[...]
WINDOW_SWITCH : BOOL := FALSE;
END_VAR
VAR_INPUT CONSTANT
[...]
ENABLE_VENTINGPOS : BOOL := FALSE;
VENTING_POSITION : BYTE := 0;
VENTING_ANGLE : BYTE := 0;
END_VAR

[...]

(* shade at night only in auto mode and enable = true *)
IF UP AND DN AND night THEN
status := 141;
IF ENABLE_VENTINGPOS AND NOT WINDOW_SWITCH THEN (* open shade slightly if venting position is enabled and window is opened *)
po := venting_position;
ao := venting_angle;
ELSE (* set standard night position when not venting *)
po := night_position;
ao := night_angle;
END_IF
ELSE
[...]
END_IF;

Dem liegt die Annahme zu Grunde, dass der Fensterkontakt mit 1=geschlossen definiert ist. Andernfalls musst du halt die Logik in meinem Code oder an der CFC-Verschaltung negieren. Und via Setup-Variablen die Lüftungsfunktion aktivieren und die Position festlegen.

Sollte eigentlich so funktionieren. Und ist doch deutlich übersichtlicher als die Lösung außen über den CFC.

Gruß,
mattsches

219
Was meinst du mit "in einer zyklischen Laufzeit"? Der F_TRIG kann schon zyklisch aufgerufen und bearbeitet werden - genau dafür ist er gemacht. Er gibt bei einer positiven Flanke ein Signal heraus, das genau einen Zyklus lang ansteht. Das nennt man dann Impuls. Und der reicht, um den BLIND_INPUT via IN anzutriggern.

Aber ich hatte dich so verstanden, dass dein Beispiel (Screenshot) für die Lüftungsposition zwar funktioniert, das Schließen jedoch nicht. Oder funktioniert schon der Screenshot nicht?

Man kann leider die Konstante nicht erkennen, die an PI angebunden ist. Kannst du die noch so verschieben, dass man sieht, welchen Wert du übergibst?

220
Hallo Sven,

das stimmt schon so. Das Öffnen über IN und PI ist für den BLIND_INPUT eine einmalige Sache. Er weiß nach der Ausführung schlicht nicht mehr, wie der Laden zuvor gestanden hat. Woher auch?

Den Befehl zum Zufahren kannst du entweder über die von mir ursprünglich vorgeschlagen über IN und PI lösen. Oder du gibst bei der entsprechenden Flanke des Fensterkontakts (wie ist denn dessen Logik? deine zwei Posts widersprechen sich hier) einen Impuls auf S2, der länger als DEBOUNCE_TIME und kürzer als CLICK_TIME ist. Voraussetzung: CLICK_EN=TRUE. Nachteil: Der Rolladen ist danach für die bei MANUAL_TIMEOUT angegebene Zeit auf Handbetrieb - geht in der Zeitspanne die Sonne auf, fährt der Rolladen nicht automatisch hoch.

Du hast die Wahl...

Grüße,
mattsches

221
Ach, und falls du dich wunderst, warum die Läden so früh herunter gehen: XCAL.SUN_RISE und SUN_SET werden in UTC ausgegeben (die Sonne ging heute nicht schon um kurz vor vier unter). Dem BLIND_NIGHT übergibst du aber die lokale Zeit an DTIN. Mit XCAL.UTC funktioniert es richtig.

222
Na dann sag' das doch gleich.

Zwei Vorschläge noch:

1. IN über CFC-Verschaltung, wie oben beschrieben
2. Nach dem F_TRIG noch ein TON, um den Impuls zu verlängern

Ich glaube aber nicht, dass es das ist. Der BLIND_INPUT schaltet PI auf PO durch, sobald IN=TRUE ist, und sei es nur für einen Zyklus. Sorry, aber ich tippe immer noch auf MASTER_MODE=FALSE.

Was passiert denn, wenn du statt BLIND_SHADE.Status eine sonst ungenutzte Variable an den Vergleicher hängst? Dann die auf 141 setzen und zurück auf 0 oder was auch immer. Wenn es dann funktioniert (auch ohne Impulsverlängerung via TON), muss es am BLIND_NIGHT liegen.

Die erste Bedingung im BLIND_NIGHT hast du wie oben beschrieben rausgenommen?

223
Ja, genau. Ich hätte den Status eher über eine grafische Verschaltung gelöst, du bewegst dich ja innerhalb eines CFC-Plans. Aber das ist Geschmackssache und macht funktional keinen Unterschied.

Dann kannst du heute Nacht bzw. morgen früh ja mal testen.

224
Nochmal, du musst keinen Baustein bearbeiten. Das würde überhaupt nichts bringen. Du müsstest lediglich die Verschaltungen im CFC-Plan zufügen, dessen Screenshot du oben angehängt hattest. Und würdest die "werksseitig" (es gibt hier keinen Hersteller, lediglich eine Community) vorgesehenen Funktionen der Bausteine nutzen. Wenn ich schreibe "255 auf BLIND_INPUT/PI", dann heißt das nicht, du sollst den PI des BLIND_INPUT im Baustein selbst verbiegen. Sondern eine Konstante mit Wert 255 an den Bausteineingang übergeben. Nur falls das vielleicht missverständlich war.

225
Hallo Jürgen,

wenn ein Baustein ein Signal nur für einen Zyklus bereitstellt, dann steht das nicht nur bis Zyklusende an und wird dann automatisch zurückgesetzt.

Es ist vielmehr so, dass das Signal von einem Aufruf bis zum nächsten Aufruf der Bausteininstanz ansteht. Es bekommen also alle anderen Bausteine davon etwas mit, vorausgesetzt, sie werden in derselben Task und unbedingt aufgerufen.

Es sollte also problemlos funktionieren. Ich würde vor dem Duplizieren der Lösung selbige halt noch an einem Beispiel testen (falls du das nicht ohnehin schon gemacht hast), um einen prinzipiellen Fehler auszuschließen.

Gruß,
mattsches

Seiten: 1 ... 13 14 [15] 16 17 18