nutellahase
Level-2
- Beiträge
- 180
- Reaktionspunkte
- 28
Ich denke, es kann jeder verstehen. Man muß sich halt ein bisschen mit der Materie befassen...Bleibt nur noch die Frage ob der TE den Code auch versteht..
Verstehe ich nicht ganz. Zeig doch mal!.. Ich hätte mir die Adresse mithilfe des Schleifenindex berechnet, aber das ist dann wohl Geschmackssache..
Die ID sagt etwas über den Ursprung aus. Ich weiß auch nur daß die 16#10 für Siemens steht... Weißt du vielleicht wieso es beim ANY-Pointer diese ID gibt?..
Ja natürlich. Wenn du Lust hast, kannst du es gerne übernehmen. Ich lehne mich jetzt zurück :sm24: ...EDIT: Eventuell könnte man bei den Überprüfungen einen Fehlercode zurückgeben..
Verstehe ich nicht ganz. Zeig doch mal!
myAdresse := ((n-1)*UDT_Groesse) + Startadresse => das wäre die Adresse von myarray[n].Wochentag_Start
myAdresse := ((n* UDT_Groesse) - UDT_Groesse) + Startadresse
Hallo super gemacht.
Ich hätte noch mal eine frage dazu. Da ich nur Hobbymässig SPS Programmiere bin ich nicht so der Freund von Berechnungen der Adresse. Es gibt doch auch die Möglichkeit mit Namen zu adressieren ?
z.b Berechnest du die Adresse der Start und Endzeit. Dies müsste dich auch per Nahmen und einer For schleife funktionieren ?
Danke.Hallo super gemacht...
Nun ja, wer das Eine will muß das Andere mögen.. bin ich nicht so der Freund von Berechnungen der Adresse...
Man könnte eine Variable vom Typ UDT1 tempörär anlegen, die die man die Daten der jeweiligen Schaltzeit hinein kopiert. Dann könnte man mit dieser UDT-Variable symbolisch hantieren. Allerdings ist zum Kopieren ebenfalls eine Adressberechnung notwendig. Man gewinnt dabei nichts... Es gibt doch auch die Möglichkeit mit Namen zu adressieren ?...
BYTE_INDEX := WORD_TO_INT(DWORD_TO_WORD(SHR(IN:=SZP.ZEIGER, N:=3)) AND 16#FFFF); // korrigiert, 29.12.2012
// Überprüfung Datenbereich
IF SHR(IN:=SZP.ZEIGER, N:=24) <> 2#10000100 OR // kein DB ????
SZP.TYP <> 16#02 OR // Typ nicht Byte ?????
SZP.ANZAHL_TYP MOD 10 <> 0 // Länge Datenbereich nicht plausibel ?????
THEN RETURN;
END_IF;
Hallo
Kannst du mir diesen Teil mal genauer erklären ?
Code:// Überprüfung Datenbereich IF SHR(IN:=SZP.ZEIGER, N:=24) <> 2#10000100 OR // kein DB ???? SZP.TYP <> 16#02 OR // Typ nicht Byte ????? SZP.ANZAHL_TYP MOD 10 <> 0 // Länge Datenbereich nicht plausibel ????? THEN RETURN; END_IF;
00000000_00000yyy_yyyyyyyy_yyyyyxxx - bereichsinterner Zeiger (der Vollständigkeit halber)
10000zzz_00000yyy_yyyyyyyy_yyyyyxxx - bereichsübergreifender Zeiger
10000zzz_00000yyy_yyyyyyyy_yyyyy
00010000_10000000_yyyyyyyy_yyyyyyyy
00000000_00000000_11111111_11111111
Hallo
kannst du mir sagen wie ich eine TOD in diese Adresse schreiben?
ZEIT ist eine TOD VAR.
ZEIT : TOD;
WORD_TO_BLOCK_DB(SZP.DB_NR).DD[BYTE_INDEX] :=DWORD_TO_WORD(DINT_TO_DWORD(TOD_TO_DINT ZEIT));
Da kommt immer ein fehler ?
// Aktuelle Systemzeit
TEMP_INT := READ_CLK(CDT := AKT_DT);
// Aktuelle Tageszeit
AKT_T := DT_TOD(IN := AKT_DT);
(***********************UDT***********************************************************************************************)
TYPE SCHALTZEITEN
STRUCT
ZEIT: TOD:=TOD#0:0:0.000;
//BYTE x.1=SO x.2=MO x.3=DI x.4=MI x.5=DO x.6=FR x.7=SA
frei :BOOL;
Sonntag :BOOL;
Montag :BOOL;
Dienstag :BOOL;
Mittwoch :BOOL;
Donnerstag:BOOL;
Freitag :BOOL;
Samstag :BOOL;
EREIGNIS : BOOL; //0=AUS 1=EIN
END_STRUCT
END_TYPE
(*************************ENDE UTD***************************************************************************************)
(************************************************************************************************************************)
FUNCTION "SCHALTZEITUHR": BOOL
(************************************************************************************************************************)
VAR_INPUT
SCHALTZEITPAARE : ANY; // ANY-Pointer auf x Schaltzeitpaare
END_VAR
VAR_OUTPUT
PULS_EIN :BOOL;
PULS_AUS :BOOL;
END_VAR
VAR_TEMP
ANY_SZP : ANY;
SZP AT ANY_SZP:
STRUCT
ID : BYTE;
TYP : BYTE;
ANZAHL_TYP : INT;
DB_NR : WORD;
ZEIGER : DWORD;
END_STRUCT;
WD : INT; // Wochentag
ANZAHL_SZP : INT;
BYTE_INDEX : INT;
n : INT;
TEMP_INT : INT;
AKT_T : TOD;
AKT_DT : DT;
ADT AT AKT_DT:
STRUCT
JAHR : BYTE;
MONAT : BYTE;
TAG : BYTE;
STUNDE : BYTE;
MINUTE : BYTE;
SEKUNDE : BYTE;
MS_MSD : BYTE; // MSD (most significant decade) von ms
MS_LSD : BYTE; // LSD (least significant decade) von ms & Wochentag
END_STRUCT;
SPS_TIME_I :DINT;
END_VAR
BEGIN
// Initialisierung
SCHALTZEITUHR := false;
// Überprüfung Datenbereich
ANY_SZP := SCHALTZEITPAARE;
IF SHR(IN:=SZP.ZEIGER, N:=24) <> 2#10000100 OR // kein DB
SZP.TYP <> 16#02 OR // Typ nicht Byte
SZP.ANZAHL_TYP MOD 6 <> 0 // Länge Datenbereich nicht plausibel
THEN RETURN;
END_IF;
// Ermittlung der Anzahl der Schaltzeitpaare
ANZAHL_SZP := SZP.ANZAHL_TYP / 6;
// Startadresse ermitteln
//Nach dem Rechtsschieben steht die BYTE-Adresse rechtsbündig im Akku.
//Durch das "Verunden" mit "AND" werden die ersten beiden Bytes auf Null gesetzt. Übrig bleibt dann nur noch die BYTE-Adresse.
BYTE_INDEX := WORD_TO_INT(DWORD_TO_WORD(SHR(IN:=SZP.ZEIGER, N:=3)) AND 16#FFFF);
// Aktuelle Systemzeit
TEMP_INT := READ_CLK(CDT := AKT_DT);
// Aktuelle Tageszeit
AKT_T := DT_TOD(IN := AKT_DT);
// ZEIT ind DINT umwandeln und durch 1000 Teile um sec zu erhalten
SPS_TIME_I:=TOD_TO_DINT (AKT_T)/1000 ;
// aktueller Wochentag
WD:= DT_DAY(IN :=AKT_DT);
// Schaltzeiten abfragen
FOR n:= 1 TO ANZAHL_SZP DO
// Überprüfen ob Bit für Wochentag true ist
IF WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,WD] = TRUE THEN
// Abfrage ob Schaltuhr Zeit mit Zeit aktuell übereinstimmt
IF SPS_TIME_I = DWORD_TO_DINT(WORD_TO_BLOCK_DB(SZP.DB_NR).DD[BYTE_INDEX])/1000 AND
DWORD_TO_DINT(WORD_TO_BLOCK_DB(SZP.DB_NR).DD[BYTE_INDEX])/1000>0 THEN
// Abfrage ob EREIGNIS EIN oder AUS ist
IF WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+5,0]= TRUE THEN
PULS_EIN:=TRUE;
EXIT;
END_IF;
IF WORD_TO_BLOCK_DB (SZP.DB_NR).DX[BYTE_INDEX+5,0]= FALSE THEN
PULS_AUS:=TRUE;
EXIT;
END_IF;
ELSE
PULS_EIN:=FALSE;
PULS_AUS:=FALSE;
END_IF;
END_IF;
byte_index:=byte_index+6;
END_FOR;
END_FUNCTION;
FUNCTION_BLOCK "MUX_SCHALTZEITUHR"
(*********************************************************************************************************************************************)
VAR_IN_OUT
SCHALTZEITPAARE : ANY; // ANY-Pointer auf x Schaltzeitpaare
END_VAR
VAR_TEMP
ANY_SZP : ANY;
SZP AT ANY_SZP:
STRUCT
ID : BYTE;
TYP : BYTE;
ANZAHL_TYP : INT;
DB_NR : WORD;
ZEIGER : DWORD;
END_STRUCT;
WD : INT; // Wochentag
ANZAHL_SZP : INT;
BYTE_INDEX : INT;
n : INT;
TEMP_INT : INT;
AKT_T : TOD;
AKT_DT : DT;
ADT AT AKT_DT:
STRUCT
JAHR : BYTE;
MONAT : BYTE;
TAG : BYTE;
STUNDE : BYTE;
MINUTE : BYTE;
SEKUNDE : BYTE;
MS_MSD : BYTE; // MSD (most significant decade) von ms
MS_LSD : BYTE; // LSD (least significant decade) von ms & Wochentag
END_STRUCT;
SPS_TIME_I :DINT;
END_VAR
VAR
ZEIT :TOD;
frei :BOOL;
Sonntag :BOOL;
Montag :BOOL;
Dienstag :BOOL;
Mittwoch :BOOL;
Donnerstag :BOOL;
Freitag :BOOL;
Samstag :BOOL;
EREIGNIS :BOOL; //0=AUS 1=EIN
SPEICHERN :BOOL;
RESET :BOOL;
ANZEIGE_NR :INT;
END_VAR
BEGIN
// Ermittlung der Anzahl der Schaltzeitpaare
ANZAHL_SZP := SZP.ANZAHL_TYP / 6;
// Startadresse ermitteln
//Nach dem Rechtsschieben steht die BYTE-Adresse rechtsbündig im Akku.
//Durch das "Verunden" mit "AND" werden die ersten beiden Bytes auf Null gesetzt. Übrig bleibt dann nur noch die BYTE-Adresse.
BYTE_INDEX := WORD_TO_INT(DWORD_TO_WORD(SHR(IN:=SZP.ZEIGER, N:=3)) AND 16#FFFF);
//Anzeige NR bei Max Große SpeicherArray auf Max setzen
IF ANZEIGE_NR>=ANZAHL_SZP THEN
ANZEIGE_NR:= ANZAHL_SZP;
END_IF;
//Anzeige NR bei Min Große SpeicherArray auf 1 setzen
IF ANZEIGE_NR <=1 THEN
ANZEIGE_NR:= 1;
END_IF;
// Werte einlesen
byte_index:=byte_index+(6*(ANZEIGE_NR-1));
ZEIT := DINT_TO_TOD ((DWORD_TO_DINT(WORD_TO_BLOCK_DB(SZP.DB_NR).DD[BYTE_INDEX])));
Sonntag := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,1];
Montag := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,2];
Dienstag := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,3];
Mittwoch := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,4];
Donnerstag:= WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,5];
Freitag := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,6];
Samstag := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,7];
EREIGNIS := WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+5,0];
// Werte SPEICHERN
IF SPEICHERN = TRUE THEN
WORD_TO_BLOCK_DB(SZP.DB_NR).DD[BYTE_INDEX] :=DWORD_TO_WORD(DINT_TO_DWORD(TOD_TO_DINT ZEIT));????????????????????????????????????????????????????????????
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,1]:=Sonntag;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,2]:=Montag;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,3]:=Dienstag;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,4]:=Mittwoch ;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,5]:=Donnerstag;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,6]:=Freitag;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+4,7]:=Samstag;
WORD_TO_BLOCK_DB(SZP.DB_NR).DX[BYTE_INDEX+5,0]:=EREIGNIS;
END_IF;
END_FUNCTION_BLOCK;
WORD_TO_BLOCK_DB(SZP.DB_NR).DD[BYTE_INDEX] [COLOR=#FF0000]:=DINT_TO_DWORD(TOD_TO_DINT(ZEIT));[/COLOR]
..ich wollte eine Mux erstellen..
BIER_HOLEN : ARRAY [1 .. 1000 ] OF UDT 1; // EINTAUSEND Schaltzeiten
FUNCTION "SCHALTZEITUHR": BOOL
[COLOR=#ff0000]FUNCTION "SCHALTZEITUHR": VOID[/COLOR]
[COLOR=#ff0000]// Initialisierung
SCHALTZEITUHR := false;[/COLOR]
Das einzige was mir aufgefallen ist das dort bei der Auswahl der Schaltzeitpaare "AK_ANZEIGE" statt "ANZEIGE_NR" verwendet ist!Passt das schon soooo???
Nur der Zugriff auf den Instanz DB ist halt Geschmacksache!Ich würde das nicht machen!
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?