Beckhoff KL3403 Arbeit und Leistung gleichzeitig messen

zwuebbl

Level-1
Beiträge
11
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Kann ich Arbeit und Leistung gleichzeitig messen, oder muss explizit eins eingestellt sein. Leistungswerte hab ich schon aus der Klemme gelesen aber das mit dem kWh Zähler hab ich noch nicht hinbekommen.

Gruß

zwuebbl
 
Moin zwuebbl,

bau dir mal einen FB und zwei Datentypen aus folgendem Code. In dem Programm muss die Lib: TcPlcCoupler.lib eingebunden werden. Es gib auch einen FB für die Ausgabe in LREAL und einen für die EL3403, da diese Klemme anders arbeitet:

1. Datentyp: TYPE E_PowerMeasurementMode :
(
ePowerMeasurementMode_AutoAllValues := 0,
ePowerMeasurementMode_Current := 1,
ePowerMeasurementMode_Voltage := 2,
ePowerMeasurementMode_EffectivePower := 3,
ePowerMeasurementMode_PowerFactor := 4,
ePowerMeasurementMode_EnergyConsumption := 5,
ePowerMeasurementMode_PeakCurrentValu := 6,
ePowerMeasurementMode_PeakVoltageValue := 7,
ePowerMeasurementMode_PeakPowerValue := 8
);
END_TYPE

2: TYPE ST_PowerMeasurement : (* 30*DINT = 120 Byte*)
STRUCT
diIL1, diIL2, diIL3 : DINT;
diUL1, diUL2, diUL3 : DINT;
diPL1, diPL2, diPL3 : DINT;
diPg : DINT;
diCosPhiL1, diCosPhiL2, diCosPhiL3 : DINT;
diCosPhi : DINT;
diWL1, diWL2, diWL3 : DINT;
diWg : DINT;
diImaxL1, diImaxL2, diImaxL3 : DINT;
diUmaxL1, diUmaxL2, diUmaxL3 : DINT;
diPmaxL1, diPmaxL2, diPmaxL3 : DINT;
diSg : DINT;
diQg : DINT;
dummy : DINT;
END_STRUCT
END_TYPE


FB Kopf:
FUNCTION_BLOCK FB_PowerMeasurementKL3403
VAR_INPUT
wDataL1,wDataL2, wDataL3: WORD;
bySBL1, bySBL2, bySBL3 : BYTE;
diCurrTransFactor : DINT;
eModePowerMeasurement : E_PowerMeasurementMode;
bDelEnergyConsumption : BOOL;

END_VAR
VAR_OUTPUT
bDelEnergyMeasuredValuesBusy: BOOL;
bError :BOOL;
iErrID : UDINT; (* Fehlernummer Fehlerbeschreibung
0 kein Fehler
0x100 Timeout-Fehler. Die zulässige Ausführungszeit wurde überschritten.
0x200 Parameter Fehler (z.B. bei einer unzulässigen Registernummer).
0x300 Der gelesene Wert unterscheidet sich von dem geschriebenen Wert ( Schreibzugriff auf diesen Register möglicherweise nicht erlaubt oder fehlgeschlagen ) *)
byCBL1, byCBL2, byCBL3 : BYTE;
iDataOutL1, iDataOutL2, iDataOutL3: INT;
stQ_PowerMeasurement : ST_PowerMeasurement;

END_VAR
VAR
x1, x2: REAL;
i: INT;
j: INT;
cb: INT;
rtrigbDelEnergyConsumption: R_TRIG;
Registerzugriff : ReadWriteTerminalReg;
iStateDel: INT;
Energieverbrauch_Ueberl_L1, Energieverbrauch_Ueberl_L2, Energieverbrauch_Ueberl_L3 : DINT;
END_VAR

FB Programm: (steht in der nächsten Antwort das sonst zu groß)

Grüße
Thomas
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier der FB Code Teil 1:
(* Leistungsmessklemme KL3403)*

CB0.3 bis CB0.0 ProcDatIdx Tragen Sie hier den Index des Prozessdatums ein, das Sie mit dem Eingangsdatenwort 0 (DataIN0) auslesen wollen.
Es werden folgende Indices unterstützt:
0000bin 0dez Ieff Strom (Effektivwert) Auflösung: 0,001 A - umgerechnet in 0,1 A
0001bin 1dez Ueff Spannung (Effektivwert) Auflösung: 0,1 V
0010bin 2dez P Wirkleistung Auflösung: 0,1 W - umgerechnet in 0,1 kW
0011bin 3dez cos j Leistungsfaktor Auflösung: 0,01
0100bin 4dez W Energieverbrauch Auflösung: 0,01 kWh (default3) - umgerechnet in 1 kWh
0101bin 5dez Imax Spitzenwert des Stroms Auflösung: 0,001 A - umgerechnet in 0.1 A
0110bin 6dez Umax Spitzenwert der Spannung Resolution: 0.1 V
0111bin 7dez Pmax Spitzenwert der Wirkleistung Resolution: 0.1 kW

Sg, Qg, Wg, Pg, in 0.1 xx
weitere reserviert

R7: Kommando-Register
Kommando 0x1004: Energieverbrauch löschen (Anwender-Passwort muss gesetzt sein)
Schreiben Sie den Wert 0x1004 in das Kommandoregister um den in den Prozessdaten gespeicherten Energieverbrauch (Prozessdatenindex 0x4)
und das Überlauf-Register für den Energieverbrauch (R0) zu löschen.
*)


rtrigbDelEnergyConsumption ( clk := bDelEnergyConsumption );


IF diCurrTransFactor <1 THEN diCurrTransFactor := 1; END_IF;
IF diCurrTransFactor > 100000 THEN diCurrTransFactor := 100000; END_IF;



IF NOT rtrigbDelEnergyConsumption.Q AND NOT bDelEnergyConsumption AND iStateDel = 0 THEN

IF eModePowerMeasurement >0 AND eModePowerMeasurement < 9 THEN
j := eModePowerMeasurement -1 ;
ELSE
IF ((bySBL1 AND 16#0F) = byCBL1) AND ( (bySBL2 AND 16#0F) = byCBL2) AND (( bySBL3 AND 16#0F) = byCBL3 ) AND i < 20 THEN
j:= i+1;
END_IF
END_IF


IF j<>i OR i > 19 OR eModePowerMeasurement >0 THEN

CASE i OF
0 : stQ_PowerMeasurement.diIL1:= WORD_TO_DINT (wDataL1) * diCurrTransFactor /100;
stQ_PowerMeasurement.diIL2 := WORD_TO_DINT(wDataL2 ) * diCurrTransFactor/100;
stQ_PowerMeasurement.diIL3 := WORD_TO_DINT(wDataL3 ) * diCurrTransFactor/100 ; cb:=j;
1 : stQ_PowerMeasurement.diUL1:= WORD_TO_DINT(wDataL1);
stQ_PowerMeasurement.diUL2 := WORD_TO_DINT(wDataL2) ;
stQ_PowerMeasurement.diUL3 := WORD_TO_DINT(wDataL3) ; cb:=j;
2 : stQ_PowerMeasurement.diPL1:= WORD_TO_INT( wDataL1) * diCurrTransFactor/1000 ;
stQ_PowerMeasurement.diPL2 := WORD_TO_INT( wDataL2) * diCurrTransFactor/1000 ;
stQ_PowerMeasurement.diPL3 := WORD_TO_INT( wDataL3) * diCurrTransFactor/1000 ; cb:=j;
3 : IF stQ_PowerMeasurement.diIL1 > 0 THEN
stQ_PowerMeasurement.diCosPhiL1:=WORD_TO_INT( wDataL1);
END_IF
IF stQ_PowerMeasurement.diIL2 > 0 THEN
stQ_PowerMeasurement.diCosPhiL2 :=WORD_TO_INT( wDataL2);
END_IF
IF stQ_PowerMeasurement.diIL3 > 0 THEN
stQ_PowerMeasurement.diCosPhiL3 :=WORD_TO_INT( wDataL3);
END_IF
i:=20;
20 : (*Auswertung Überlauf Energieverbrauch L1*)
Registerzugriff( STATE:=bySBL1,
DATAIN:= wDataL1,
REGNO:= 0,
READ:= TRUE,
WRITE:= FALSE,
TMOUT:= t#2s,
NEWREGVALUE:= 0,
CTRL=> byCBL1,
DATAOUT=> iDataOutL1,
CURREGVALUE=>Energieverbrauch_Ueberl_L1);

IF NOT Registerzugriff.BUSY
THEN
Registerzugriff(READ:=FALSE);
i:=21;
END_IF
IF Registerzugriff.Err THEN
i := 1000;
END_IF;

21 : (*Auswertung Überlauf Energieverbrauch L2*)
Registerzugriff( STATE:=bySBL2,
DATAIN:=wDataL2,
REGNO:=0,
READ:=TRUE,
WRITE:=FALSE,
TMOUT:=t#1s,
NEWREGVALUE:=0,
CTRL=> byCBL2,
DATAOUT=> iDataOutL2,
CURREGVALUE=>Energieverbrauch_Ueberl_L2);

IF NOT Registerzugriff.BUSY
THEN
Registerzugriff(READ:=FALSE);
i:=22;
END_IF
IF Registerzugriff.Err THEN
i := 1000;
END_IF;

22 : (*Auswertung Überlauf Energieverbrauch L3*)
Registerzugriff( STATE:=bySBL3,
DATAIN:=wDataL3,
REGNO:=0,
READ:=TRUE,
WRITE:=FALSE,
TMOUT:=t#1s,
NEWREGVALUE:=0,
CTRL=> byCBL3,
DATAOUT=> iDataOutL3,
CURREGVALUE=>Energieverbrauch_Ueberl_L3);

IF NOT Registerzugriff.BUSY
THEN
Registerzugriff(READ:=FALSE);
i := 4; cb := j;
END_IF
IF Registerzugriff.Err THEN
i := 1000;
END_IF;


4 : stQ_PowerMeasurement.diWL1:= (WORD_TO_DINT( wDataL1 ) + SHL( Energieverbrauch_Ueberl_L1,16) )* diCurrTransFactor/100 ;
stQ_PowerMeasurement.diWL2 := (WORD_TO_DINT( wDataL2 ) + SHL( Energieverbrauch_Ueberl_L2,16) )* diCurrTransFactor/100 ;
stQ_PowerMeasurement.diWL3 := (WORD_TO_DINT( wDataL3 ) + SHL( Energieverbrauch_Ueberl_L3,16) )* diCurrTransFactor/100 ; cb := j ;

5 : stQ_PowerMeasurement.diImaxL1:= WORD_TO_DINT( wDataL1 )* diCurrTransFactor /100;
stQ_PowerMeasurement.diImaxL2 := WORD_TO_DINT( wDataL2 )* diCurrTransFactor /100;
stQ_PowerMeasurement.diImaxL3 := WORD_TO_DINT( wDataL3 )* diCurrTransFactor /100; cb:=j;

6 : stQ_PowerMeasurement.diUmaxL1:= WORD_TO_DINT( wDataL1 );
stQ_PowerMeasurement.diUmaxL2 := WORD_TO_DINT( wDataL2);
stQ_PowerMeasurement.diUmaxL3 := WORD_TO_DINT( wDataL3 ); cb:=j;

7 : stQ_PowerMeasurement.diPmaxL1:= WORD_TO_INT( wDataL1 )* diCurrTransFactor / 1000;
stQ_PowerMeasurement.diPmaxL2 := WORD_TO_INT( wDataL2 )* diCurrTransFactor / 1000;
stQ_PowerMeasurement.diPmaxL3 := WORD_TO_INT( wDataL3 )* diCurrTransFactor / 1000; j:=0; cb:=j;


1000:
(* Evt. Fehlerbehandlung einfügen *)
bError:=TRUE;
iErrID := Registerzugriff.ERRID ;
i := 0;

ELSE
i:=0;
END_CASE;

END_IF
 
Hier der Code Teil2:

IF i < 20 THEN
(* Registerweiterschalten für neuen Wert im nächsten Zyklus *)
byCBL1:= INT_TO_BYTE(cb); byCBL2:= byCBL1; byCBL3:= byCBL1;
END_IF

ELSE

CASE iStateDel OF
0:
Registerzugriff(READ:=FALSE, WRITE:=FALSE);
IF rtrigbDelEnergyConsumption.Q THEN
bError:=FALSE;
iStateDel := 10;
END_IF

10: (* Erzeugen einer Flanke zum Schreiben des R7: Kommando-Register *)
bDelEnergyMeasuredValuesBusy := TRUE;
iStateDel := 20;

20: (* Schreiben von 16#1004 in R7 zum Löschen der Energiewerte *)

Registerzugriff(
STATE:= bySBL1,
DATAIN:= wDataL1,
REGNO:= 7,
READ:= FALSE,
WRITE:= TRUE,
TMOUT:= t#1s,
NEWREGVALUE:= 16#1004,
CTRL=> byCBL1,
DATAOUT=> iDataOutL1 );
IF NOT Registerzugriff.BUSY
THEN
Registerzugriff(WRITE:=FALSE);
iStateDel:=21;
END_IF
IF Registerzugriff.Err THEN
iStateDel := 1000;
END_IF;

21: Registerzugriff(
STATE:= bySBL2,
DATAIN:= wDataL2,
REGNO:= 7,
READ:= FALSE,
WRITE:= TRUE,
TMOUT:= t#1s,
NEWREGVALUE:= 16#1004,
CTRL=> byCBL2,
DATAOUT=> iDataOutL2 );
IF NOT Registerzugriff.BUSY
THEN
Registerzugriff(WRITE:=FALSE);
iStateDel:=22;
END_IF
IF Registerzugriff.Err THEN
iStateDel := 1000;
END_IF;

22: Registerzugriff(
STATE:= bySBL3,
DATAIN:= wDataL3,
REGNO:= 7,
READ:= FALSE,
WRITE:= TRUE,
TMOUT:= t#1s,
NEWREGVALUE:= 16#1004,
CTRL=> byCBL3,
DATAOUT=> iDataOutL3 );
IF NOT Registerzugriff.BUSY
THEN
Registerzugriff(WRITE:=FALSE);
iStateDel:=23;
bDelEnergyMeasuredValuesBusy := FALSE;
END_IF
IF Registerzugriff.Err THEN
iStateDel := 1000;
END_IF;

23:
IF NOT bDelEnergyConsumption THEN
iStateDel := 0;
END_IF


1000: bDelEnergyMeasuredValuesBusy := FALSE;
(* Evt. Fehlerbehandlung einfügen *)
bError:=TRUE;
iErrID := Registerzugriff.ERRID ;
iStateDel := 0;
END_CASE
END_IF

IF i < 20 THEN i:=j; END_IF

(* Berechnete Größe *)
stQ_PowerMeasurement.diSg := ( stQ_PowerMeasurement.diIL1* stQ_PowerMeasurement.diUL1 +
stQ_PowerMeasurement.diIL2 * stQ_PowerMeasurement.diUL2 +
stQ_PowerMeasurement.diIL3 * stQ_PowerMeasurement.diUL3)/10000 ; (* 1/10 A * 1/10V -> /100 um auf 0,1 kva zukommen /100 --> /10000 *)

x1 := DINT_TO_REAL(ABS(stQ_PowerMeasurement.diSg)) / 10;

stQ_PowerMeasurement.diPg := stQ_PowerMeasurement.diPL1+ stQ_PowerMeasurement.diPL2 + stQ_PowerMeasurement.diPL3 ;
x2 := DINT_TO_REAL(ABS(stQ_PowerMeasurement.diPg)) / 10;

IF x1 <> 0 THEN
stQ_PowerMeasurement.diCosPhi := REAL_TO_DINT ((x2 / x1) * 100) ;
END_IF
stQ_PowerMeasurement.diWg := stQ_PowerMeasurement.diWL1 + stQ_PowerMeasurement.diWL2 + stQ_PowerMeasurement.diWL3;

IF x1 > x2 THEN (*05.11.08*)
(*Blindleistung² =Scheinleistung² - Wirkleistung²*)
stQ_PowerMeasurement.diQg := REAL_TO_DINT ( SQRT(EXPT ( x1 ,2) - EXPT (x2 , 2)) * 10 );
ELSE
stQ_PowerMeasurement.diQg:=0;
END_IF
 
Danke für die schnelle Antwort. Für was brauch ich jetzt genau die eingebundene Bibliothek TcPlcCoupler.lib. Brauch die egal ob KL3403 oder EL3403. Kann man die TwinCat2 Bibliotheken auch bei TwinCat 3 verwenden??? Es heißt ja dass man komplette Projekte konvertieren kann. Den eigendlichen Baustein werde ich heute mal ausprobieren. Melde mich bei Erfolg oder Misserfolg.

Gruß zwuebbl
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die KL3403 benötigt zum Auslesen der Energie (für die oberen 16Bit) die Funktion ReadWriteTerminalReg. Die EL3403 benötigt stattdessen die EtherCAT.lib für alle Funktionalitäten. Eine TC2 Lib muss, wenn sie noch nicht im TC3 als konvertierte enthalten ist (siehe Online Doku TwinCAT3 Libraries converted from TwinCAT2 Libraries) über den Umweg eines TC2 Projektes, welches in TC3 geladen wird, konvertiert werden.

Gruß
Thomas
 
Zurück
Oben