Savino Inserito: 25 gennaio 2008 Segnala Share Inserito: 25 gennaio 2008 FUNCTION_BLOCK FBxxNAME:xx_xx.. VAR_TEMP ... .. STEP_LEVEL : REAL; ... .. AUX1 : WORD; AUX2 : WORD; LENGTH1 : INT; DB_N : WORD; INDEX: INT; OFFSET: INT; .. . END_VAR ... .. BEGIN .. LENGTH1 :=0; OFFSET :=0; INDEX :=0; .. . OFFSET:= (LENGTH1 * 4) - 2 ; .. AUX1:=WORD_TO_BLOCK_DB(DB_N).DW[iNDEX]; INDEX:=INDEX+ 2; AUX2:=WORD_TO_BLOCK_DB(DB_N).DW[iNDEX]; MW18:= AUX1; MW20:= AUX2; STEP_LEVEL :=DWORD_TO_REAL (MD18); .. .END_FUNCTION_BLOCK----------------------------------------------------DATA_BLOCK "xxxx"TITLE = TANK13STRUCT CALIBRATION : ARRAY [1 .. 2, 1 .. 31 ] OF REAL ; END_STRUCT ; BEGIN CALIBRATION[1, 1] := 0.000000e+000; CALIBRATION[1, 2] := 4.200000e+000; CALIBRATION[1, 3] := 7.800000e+000; CALIBRATION[1, 4] := 1.050000e+001; CALIBRATION[1, 5] := 1.490000e+001; .. . CALIBRATION[2, 29] := 1.100000e+005; CALIBRATION[2, 30] := 1.200000e+005; CALIBRATION[2, 31] := 1.260000e+005; END_DATA_BLOCKCiao,Ieri all'improvisso, mi e' capitato di dover fare una implementazione in SCL alla veloce.. in prattica dovevo leggere dei DB con lunghezza variabile , tipo come sopra , 2 dimensioni REAL data type array, pilotando l'offset a secondo la richiesta imposta dagli algoritmi...Diciamo che alla fine la soluzione adottata e' stata molto soddisfacente.. il codice implementato dopo essere validato, ha performato bene.Come potete apprezzare , per leggere una data REAL ho usato la forma : AUX1:=WORD_TO_BLOCK_DB(DB_N).DW[INDEX]; INDEX:=INDEX+ 2; AUX2:=WORD_TO_BLOCK_DB(DB_N).DW[INDEX]; MW18:= AUX1; MW20:= AUX2; STEP_LEVEL :=DWORD_TO_REAL (MD18); appogiandomi sulla data PLC per formatare la variabile di 4 BYTES o 2 WORD per ottenere finalmente la FLOAT (MD).Mi domandavo si c'era un'altra strada senza dovere usare la data PLC, benche' una struttura SCL propia...Ringrazio in anticipo per any comment. Link al commento Condividi su altri siti More sharing options...
Beatrice_Ru Inserita: 27 gennaio 2008 Segnala Share Inserita: 27 gennaio 2008 ti costruisci un UDT con la struttura che tu intendi usare,poi passi questa struttura al FB10 (e' un esempio) come dato In_Out Type UDT10 Struct // Struttura Calibration CALIBRATION : ARRAY [1 .. 2, 1 .. 31 ] OF REAL ; end_StructEND_TYPE Function_Block FB10Title = 'Read Real'// SubRoutine for read real value from Structur of Array////Version : '1.0'Author : xxxx Name : yyyyFamily : zzzzzVar_Input Index1: INT: Index2: INT:End_VarVar_in_out Calibration : UDT10; // Struttura Array che gia' avevi definito End_VarVar_Output Step_level : REAL;End_VarBegin Step_Level := Calibration[index1,index2]end_Function_Block Link al commento Condividi su altri siti More sharing options...
Savino Inserita: 27 gennaio 2008 Autore Segnala Share Inserita: 27 gennaio 2008 (modificato) Dear Beatrice_Ru,Grazie mille per la tua risposta..Dunque, diciamo che in una Process Cell ho 100 Units (tanks), ad ogni tank viene associato una DB quale forma non posso cambiare.DATA_BLOCK "TANK13" // DB13 TITLE = TANK13 .. STRUCT CALIBRATION : ARRAY [1 .. 2, 1 .. 31 ] OF REAL; END_STRUCT; BEGIN CALIBRATION[1, 1] := 0.000000e+000; .. CALIBRATION[1, 31] := 1.036500e+003; CALIBRATION[2, 1] := 0.000000e+000; .. CALIBRATION[2, 31] := 1.260000e+005; END_DATA_BLOCK DATA_BLOCK "TANK15" // DB15 TITLE = TANK15 .. STRUCT CALIBRATION : ARRAY [1 .. 2, 1 .. 28 ] OF REAL; END_STRUCT; BEGIN CALIBRATION[1, 1] := 0.000000e+000; .. CALIBRATION[1, 28] := 1.016400e+003; CALIBRATION[2, 1] := 0.000000e+000; .. CALIBRATION[2, 28] := 1.160000e+005; END_DATA_BLOCK Come tu hai gia' intuito, devo leggere indirettamente delle data REAL a secondo un indice dato, da una determinata DB.. (DB_N = input) Diciamo che mi sarebbe bastato un mnemonic del tipo : DAUX1 : DWORD; DAUX1:=DWORD_TO_BLOCK_DB (DB_N). DD[INDEX]; STEP_LEVEL :=DWORD_TO_REAL (DAUX1); Cioe' leggere la DB nel modo DAUX1 := DB[DB_NUM][DWORD]; Ma purtroppo non esiste. Infatti cercavo per una soluzione del genere, senza dovere appoggiarmi sulla data PLC, sia questa del tipo Flag, DB, UDT..cioe', definire un data type come VAR_TEMP (ma non UDT o DB o Flag) da utilizzare temporaneamente dentro l'FB. In C++ avrei dichiarato una union per utilizzare come maschera per formatare 4 bytes in una DWord o float.. union reg_32bits { float mw_32; char mb_32[4]; }; union reg_32bits m_FloatingValue[1].mw_32 oppure union reg_32bits { signed long int RegDWord_32; char DW_32[4]; }; m_FloatingValue[0].mw_32; // indirizzamento DWord m_FloatingValue[0].mb_32[3]; // \ m_FloatingValue[0].mb_32[2]; // | indirizzamento byte m_FloatingValue[0].mb_32[1]; // | m_FloatingValue[0].mb_32[0]; // / Oppure un'accesso in lettura con una forma che ancora non mi viene in mente.. Comunque la suluzione da te suggerita :Step_Level := Calibration[index1,index2]; Non e' accettata dal compilatore..invalid variable...Number of array dimensions exceeded (max. 6) Saluti Modificato: 27 gennaio 2008 da Savino Link al commento Condividi su altri siti More sharing options...
Beatrice_Ru Inserita: 27 gennaio 2008 Segnala Share Inserita: 27 gennaio 2008 Scusami Savino, pensavo di eserti stata utile, inveceho sbagliato qualche sintassi.Eccomi allora.Ho capito che hai 100 processi da controllare ognuno con un suo pacchetto di dati.Io per vacilitarti il compito ho creato una sola DB (DB10).nel Suo interno questa DB10, ha 100 elementi Cell[1..10] ogni elemento Cell e diviso in una Struttura CALIBRATION : ARRAY [1 .. 2, 1 .. 31 ]con questa prima sorgente SCL ti crei due UDT 10, e UDT11 e poi la DB10 appunto:Type UDT10Struct// Struttura CalibrationCalibration : ARRAY [1 .. 2, 1 .. 31 ] OF REAL ; end_StructEND_TYPEType UDT11Struct// Struttura Process CellCell : ARRAY [1 .. 100] OF UDT10; end_StructEND_TYPE// Creazione DB10 DATA_BLOCK DB10 UDT11BEGINEND_DATA_BLOCKBene ora ecco FB10 Corretta (ho fatto sia il Parametro di Input_Output = Struttura UDT11, che accesso diretto sulla DB10)Function_Block FB10Title = 'Read Real'// SubRoutine for read real value from Structur of Array////Version : '1.0'Author : xxxx Name : yyyyFamily : zzzzzVAR_INPUTIndexCell: INT; Index1: INT;Index2: INT;END_VARVar_in_outProcess : UDT11; // Struttura Array che gia' avevi definito End_VarVar_OutputStep_level : REAL;Step_lev : REAL;END_VARVARPX,PY,PZ: INT; // Puntatori con limite per IndexCell, Index1,Index2 END_VARBEGIN PX:= IndexCell; PY:= Index1; PZ:= Index2; IF PX <1 THEN PX :=1; END_IF; IF PX >100 THEN PX :=100; END_IF; // Limite 1..10 IF PY <1 THEN PY :=1; END_IF; IF PY >2 THEN PY :=2; END_IF; // Limite 1..2 IF PZ <1 THEN PZ :=1; END_IF; IF PZ >31 THEN PZ :=31; END_IF; // Limite 1..31Step_Level := Process.Cell[PX].Calibration[PY,PZ]; // puoi puntatare un Struttura a tuo piacimentoStep_Lev := db10.Cell[PX].Calibration[PY,PZ]; // viene puntato il Data Block DB10end_Function_Block Spero che cosi vada bene. Link al commento Condividi su altri siti More sharing options...
Savino Inserita: 27 gennaio 2008 Autore Segnala Share Inserita: 27 gennaio 2008 (modificato) Gentile Beatrice,Scusami Savino, pensavo di eserti stata utile, inveceho sbagliato qualche sintassi. ma figurati.. ti ringazio per il tuo interessamento. In tanto ti dico che quando compilo il codice mi da errore, forse c'e' un errore di sintassi :Error in a block DB10 Symbol table entry for instance DB or DB of the type UDT does not match the called FB or UDT DATA_BLOCK DB10 UDT11 <- qui BEGIN END_DATA_BLOCKPoi, tieni presente che le DB col'array CALIBRATION sono a lunghezza variabile ( 1..31, 2..31) - (1..29, 2..29)- ( 1..15, 2..15); Infatti l'FB riceve anche come parametro d'ingresso la lunghezza dei DB ricavata in un FC chiamato in precedenza (DBLG), ma questo non sarebbe un problema... ma si per creare il tuo UDT 10 ?? Comunque, domani studiero' ancora il tuo metodo e vedro' se ne posso ricavare qualcosa d'utile...Per adesso ti ringrazio , sei stato super disponibile e very smart !! P.D: devo propio andare al letto che mi sono pescato l'influenza Modificato: 27 gennaio 2008 da Savino Link al commento Condividi su altri siti More sharing options...
Savino Inserita: 28 gennaio 2008 Autore Segnala Share Inserita: 28 gennaio 2008 (modificato) Gentile Beatrice,Nonostante alla fine sia riuscito a compilare l'utimo esempio di codice da te postato, la forma della soluzione non sarebbe quella da me desiderata.. e ti spiego perche... Innanzitutto, tanto mio cliente come me siamo soddisfatti della performance del codice da me consegnato, questo funziona bene e fa' quello che deve fare. La mia curiosita' era nata dal fatto che per leggere una word doppia da una DB in modo indiretto ho dovuto leggere per due volte una word e dopo creare la doppia word , formatandole sulla base di una MD del PLC, dovuto alla mancanza di una sintassi del genere:DAUX1 : DWORD;DB_N : WORD;INDEX: INT;DAUX1:=DWORD_TO_BLOCK_DB (DB_N). DD[iNDEX]; <- questa sintassi non esiste in SCLSTEP_LEVEL :=DWORD_TO_REAL (DAUX1);Piuttosto ho dovuti creare la word doppia facendo cosi:MW18:=WORD_TO_BLOCK_DB(DB_N).DW[INDEX]; // leggo la prima WORD INDEX:=INDEX+2; // incremento di 2 bytes MW20:=WORD_TO_BLOCK_DB(DB_N).DW[INDEX]; // leggo la 2nda WORD NEXT_VOLUME :=DWORD_TO_REAL (MD18); // creo la DWORD sulla maschera MD Come vedi, il metodo e' molto semplificato e meno drastico, l'unica cosa e' che mi devo appoggiare ad una MD, e non ad un costruito SCL. Infatti, Io mi domandavo.. ma come e' possibile che i progettisti cha hanno disegnato l' SCL abbiano previsto una sintassi per un'accesso indiretto impostanto come offset l'indirizzo DB + l'indirizzo WORD e non abbiano previsto fare la stessa cosa invece per indirizzare una WORD doppia. Dove sarebbe questo limite nel sistema, visto che S7300/400 ha una architettura a 32 bit.Sono stati cosi' pigri o c'e' qualcosa che Io non ho ancora afferrato, o magari la sintassi c'e' ma riesco tovarla( magari c'e' in una release successiva a quella che sto' utilizzando)Attenzione, mi sto riferendo a una sintassi, mnemonic... e non ad un metodo diverso, come potrebbe essere quello che tu hai elencato.Comunque, ti ringrazio di cuore per il tuo interessamento. Modificato: 28 gennaio 2008 da Savino Link al commento Condividi su altri siti More sharing options...
beppeconti Inserita: 28 gennaio 2008 Segnala Share Inserita: 28 gennaio 2008 (modificato) DAUX1:=DWORD_TO_BLOCK_DB (DB_N). DD[INDEX]; <- questa sintassi non esiste in SCLNon funziona perchè è errata la prima parte relativa all'identificazione del DB "DWORD_TO_BLOCK_DB"Hai provato con questa sintassi?DAUX1:=WORD_TO_BLOCK_DB (DB_N). DD[iNDEX]A me funziona.CIAoBeppe Modificato: 28 gennaio 2008 da beppeconti Link al commento Condividi su altri siti More sharing options...
Savino Inserita: 28 gennaio 2008 Autore Segnala Share Inserita: 28 gennaio 2008 DAUX1:=WORD_TO_BLOCK_DB (DB_N). DD[iNDEX]A me funziona. Grazie mille beppeconti.. aspettavo un tuo riscontro , infatti non poteva non esistere.! Ti ringrazio ancora e anche a Beatrice. Link al commento Condividi su altri siti More sharing options...
beppeconti Inserita: 28 gennaio 2008 Segnala Share Inserita: 28 gennaio 2008 Prego e buona guarigione CIAoBeppe Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora