Vai al contenuto
PLC Forum


Puntare I Bit Di Una Var Di Tipo "word" In Un Fb/fc?


marcob1984

Messaggi consigliati

Buongiorno a tutti,

ho sempre trovato le risposte che cercavo ma questa volta richiedo il vostro aiuto perchè non sono a riuscito a trovare una soluzione al mio "problema". In parte è spiegata qui http://www.plcforum....li-locali-fc/#1,manon del tutto.

Mi spiego: ho un impianto da automatizzare composto da 6 motori con inverter ABB e scheda RPBA01 (profibusDP) tutti uguali. Ho la necessità quindi, di creare un FB univoco per tutti i motori e ad ogni motore associo una DB di istanza diversa. La logica di comando in profibus per questi motori necessita di 2 word di lettura (che chiameremo: StatusWord e RD_SpdRef) e 2 word di scrittura (che chiameremo ControlWord e WR_SpdRef) che opportunamente lette/scritte mi fanno lo start/stop/riferimento velocità.

Il mio "problema" è che se nell'FB dichiaro così le variabili:

IN: StatusWord TYPE: Word

OUT: ControlWord TYPE: Word

quando devo scrivere il codice non riesco a puntare i singoli bits che mi servono.

Per fare funzionare il tutto, devo dichiarare le variabili splittate (quindi bit per bit).

Qualcuno sa aiutarmi?

PS: appoggiando tali word in variabili TEMP

(es: L #StatusWord

T LW0

L LW2

T #ControlWord)

non posso richiamare simultaneamente 2 o più blocchi FB altrimenti le variabili locali vengono sovrascritte e succede un casino

Grazie

.

Modificato: da Giuseppe Signorella
Completata discussione con parte del testo mancante
Link al commento
Condividi su altri siti


L #StatusWord

T LW0

L LW2

T #ControlWord)

non posso richiamare simultaneamente 2 o più blocchi FB altrimenti le variabili locali vengono sovrascritte e succede un casino

Non è vero che succede un casino

Bisogna avere qualche accortezza:

L #StatusWord

T LW0

L ControlWord

T LW2

Queste sopra devono essere le prime istruzioni dell'FB

Dopodichè puoi interrogare i bit L0.0 - L1.7 ed è come se interrogassi i bit della #StatusWord

Nei vari segmenti dell'FB puoi settare o resettare i bit di LW2

Alla fine dell'FB riscrivi la controlword:

L LW2

T #ControlWord

Devo dire però che non amo molto questo sistema perchè basta poco per far casini... devi essere sicuro che non sposti le Word locali perchè poi le vai a interrogare a bit in maniera assoluta. Però ammetto che qualche volta non ho avuto il tempo di far fiorellini e l'ho usato (tra l'altro credo proprio in una circostanza simile)

==========================================================================================================================

Un altro modo è quello di interrogare direttamente i bit della DB d'istanza, la apri nell'editor, controlli l'indirizzo della #StatusWord e della #ControlWord, supponiamo siano 10.0 e 20.0, nell'FB interrogherai i bits DIX10.0-11.7 per la status e scriverai nei bits DIX20.0-21.7 per la control.

Ma questo sistema mi piace ancora meno !

==========================================================================================================================

Il modo più elegante, più sicuro e corretto è quello di usare i puntatori:
      L     P##StatusWord
      LAR1  
      U     DIX [AR1,P#1.0]             // interroga il 1° bit (quello meno significativo) della status word


      L     P##ControlWord
      LAR1  
      =     DIX [AR1,P#0.7]             // Imposta il 16° bit (quello più significativo) della status word

Modificato: da JumpMan
Link al commento
Condividi su altri siti

Batta: hai ragione, ero di fretta ed è ho dimenticato di formulare esplicitamente la domanda. Comuque la risposta di JumpMan ha centrato l'obiettivo. Scusatemi ancora. Adesso provo e poi vi faccio sapere.

Grazie mille.

Link al commento
Condividi su altri siti

Jumpman ma con l' offset P#1.0 dell' istruzione:

U DIX[AR1,P#1.0]

vado ad interrogare il bit 0 del byte più significativo, quindi l'ottavo bit e non quello meno significativo.

giusto?

Modificato: da STEU
Link al commento
Condividi su altri siti

La domanda l'ho intuita dal titolo...

vado ad interrogare il bit 0 del byte più significativo, quindi l'ottavo bit e non quello meno significativo.

giusto?

No, nel Siemens i bytes sono swappati.

Se hai dubbi fai questa prova, vai in stato variabili:

nella riga 1 scrivi MW100 con visualizzazione intera

nella riga 2 scrivi MW100 con visualizzazione binaria

nella riga 3 metti M100.0
nella riga 4 metti M101.0
Ora attiva lo stato e forza MW100 = 1 (intero) nella prima riga
Modificato: da JumpMan
Link al commento
Condividi su altri siti

Lo so che sono "swappati" infatti esistono le istruzioni TAW e TAD proprio per questo.

Se però carichi il valore del puntatore L ##StatusWord

e StatusWord è il primo parametro di ingresso dell' FB

in AR1 carici il "valore" DI 0.0

quindi U DIX[AR1, P#1.0] è rindondante

bastava scrivere U [AR1, P1.0]

però se nel puntatore AR1 carichi il valore DI 0.0 (praticamente

Link al commento
Condividi su altri siti

C'è anche un sistema che richiede un piccolo lavoro in più ma che, a mio avviso, rende il codice molto più comprensibile, perché permette di assegnare un nome ad ogni singolo bit della status word e della control word.

Esempio:

FUNCTION "ProvaPuntatori" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  StatusWord : WORD ;	
END_VAR
VAR_OUTPUT
  CtrlWord : WORD ;	
END_VAR
VAR_TEMP
  tmpSTW : STRUCT 	
   bit_08 : BOOL ;	
   bit_09 : BOOL ;	
   bit_10 : BOOL ;	
   bit_11 : BOOL ;	
   bit_12 : BOOL ;	
   bit_13 : BOOL ;	
   bit_14 : BOOL ;	
   bit_15 : BOOL ;	
   bit_00 : BOOL ;	
   bit_01 : BOOL ;	
   bit_02 : BOOL ;	
   bit_03 : BOOL ;	
   bit_04 : BOOL ;	
   bit_05 : BOOL ;	
   bit_06 : BOOL ;	
   bit_07 : BOOL ;	
  END_STRUCT ;	
  tmpCTW : STRUCT 	
   bit_08 : BOOL ;	
   bit_09 : BOOL ;	
   bit_10 : BOOL ;	
   bit_11 : BOOL ;	
   bit_12 : BOOL ;	
   bit_13 : BOOL ;	
   bit_14 : BOOL ;	
   bit_15 : BOOL ;	
   bit_00 : BOOL ;	
   bit_01 : BOOL ;	
   bit_02 : BOOL ;	
   bit_03 : BOOL ;	
   bit_04 : BOOL ;	
   bit_05 : BOOL ;	
   bit_06 : BOOL ;	
   bit_07 : BOOL ;	
  END_STRUCT ;	
END_VAR
BEGIN
NETWORK
TITLE =

//Appoggio valore della Status Word su variabile locale
      LAR1  P##tmpSTW; 
      L     #StatusWord; 
      T     LW [AR1,P#0.0]; 

//Qui puoi interrogare i singoli bit dichiarati nella struttura "tmpSTW"



//Puoi assegnare lo stato desiderato ai singoli bit della struttura "tmpCTW"


//Scrittura dello stato dei singoli bit nella Control Word

      LAR1  P##tmpCTW; 
      L     LW [AR1,P#0.0]; 
      T     #CtrlWord; 

END_FUNCTION


Link al commento
Condividi su altri siti

Lo so che sono "swappati" infatti esistono le istruzioni TAW e TAD proprio per questo.

Se però carichi il valore del puntatore L ##StatusWord

e StatusWord è il primo parametro di ingresso dell' FB

in AR1 carici il "valore" DI 0.0

quindi U DIX[AR1, P#1.0] è rindondante

bastava scrivere U [AR1, P#1.0]

Inoltre prova il sorgente qui sotto e vedrai che l'uscita A0.0 va a 1 quando forzi a 1 M1.0

FUNCTION_BLOCK FB 1

TITLE =

VERSION : 0.1

VAR_INPUT

statusword : WORD ;

END_VAR

VAR_OUTPUT

controlword : WORD ;

END_VAR

BEGIN

NETWORK

TITLE =

L P##statusword;

LAR1 ;

U [AR1,P#1.0];

= A 0.0;

END_FUNCTION_BLOCK

DATA_BLOCK DB 1

TITLE =

VERSION : 0.0

FB 1

BEGIN

statusword := W#16#0;

controlword := W#16#0;

END_DATA_BLOCK

ORGANIZATION_BLOCK OB 1

TITLE = "Main Program Sweep (Cycle)"

VERSION : 0.1

VAR_TEMP

OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)

OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)

OB1_PRIORITY : BYTE ; //Priority of OB Execution

OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)

OB1_RESERVED_1 : BYTE ; //Reserved for system

OB1_RESERVED_2 : BYTE ; //Reserved for system

OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)

OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)

OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)

OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started

END_VAR

BEGIN

NETWORK

TITLE =

CALL FB 1 , DB 1 (

statusword := MW 0,

controlword := MW 50);

END_ORGANIZATION_BLOCK

Link al commento
Condividi su altri siti

Batta, come sempre hai azzeccato alla grande e mi hai risolto il problema. Ho provato e funziona. Ed è proprio un lavoro pulito pulito, come volevo io, perchè si riesce ad nominare bit per bit.

Io di solito programmo l'800xA di ABB ed ha già in libreria una funzione che splitta la word in bit singoli. L'idea del tuo codice ce l'avevo in testa, ma non riuscivo a buttarla giù, perchè mi mancava il passaggio di dichiarazione delle 2 word come strutture. Alla fine la soluzione alternativa l'avevo trovata (evitare le word locali nell'FB, e dichiarare tutti i parametri d'ingresso e uscita booleani che mi servivano), ma tua soluzione è di gran lunga più elegante e pulita.

Grazie mille a tutti voi, siete sempre un libro aperto, perchè ho imparato di più leggendo le vostre discussioni che non i manuali dell'S7 300.

Link al commento
Condividi su altri siti

quindi U DIX[AR1, P#1.0] è rindondante

bastava scrivere U [AR1, P#1.0]

Hai ragione, mi è sfuggito, funziona lo stesso ma è meglio senza DIX

e anche

L P##StatusWord

LAR1

Si possono ridurre a:

LAR1 P##StatusWord

Inoltre prova il sorgente qui sotto e vedrai che l'uscita A0.0 va a 1 quando forzi a 1 M1.0

è ovvio che l'offset ,P#1.0 riferito a MW0 va a puntare sul bit M1.0 ci mancherebbe altrimenti diventeremmo scemi

ma.....

DIX [AR1,P#1.0] // interroga il 1° bit (quello meno significativo) della status word

.... la status Word è composta da 16 bit e ribadisco che P#1.0 punta al 1° bit (quello meno significativo) della status word

Se la status Word la visualizzi in esadecimale e la imposti = W#16#0001 quel bit andrà a 1 !

Comunque il codice di Batta è elegante e leggibile, è il miglior modo per risolvere il problema ;)

Modificato: da JumpMan
Link al commento
Condividi su altri siti

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 account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...