Vai al contenuto
PLC Forum


Estrazione primo allarme intervenuto


gianma9

Messaggi consigliati

Signori,

mi trovo di fronte al seguente problema:

Ho 4 word di allarmi.

Devo andare a "beccare" il  primo bit di allarme che si alza e in base a questo generare un numero, ovviamente diverso ad ogni allarme.

i miei allarmi vanno da 1 a 64, chiaramente il numero generato deve essere uguale al numero dell'allarme.

 

Grazie a tutti.

 

 

 

 

Link al commento
Condividi su altri siti


Non dici nulla su come vengono memorizzati gli allarmi.

Avere 4 word non significa nulla. Se all'evento allarme non associ un indice o la lettura dell'orologio del sistema non puoi sapere con quale ordine sono arrivati.

Potresti, ad esempio, crearti un FiFo in cui memorizzi gli allarmi man mano che accadono, così sapresti esattamente in quale ordine si sonoscatebati.

 

Spendi qualche parola in più, tanto il forum è gratis, e descrivi meglio il tuo problema.

Link al commento
Condividi su altri siti

Bisogna capire anche come si deve comportare il programma quando si alzano altri bit, deve rimanere memorizzato sempre il primo e gli altri ignorati? Oppure devi avere un registro cronologico del tipo, quando sparisce il primo visualizzo il secondo e così via?

Link al commento
Condividi su altri siti

Ci provo.

Il problema principale credo non stia nel capire il primo che si alza.. senza allarmi tutte  4 le Word avranno valore = 0.

Al sopraggiungere di un allarme una di queste cambierà il suo valore in diverso da 0. quindi.. all accadere di questo evento, 4 confronti, 1 per word e un fronte positivo pensavo di trasferire tutti i dati della DB relativa agli allarmi in una di appoggio così da memorizzare il quadro completo della situazione e teoricamente avere 1 solo bit alto su 4 word.

Ogni Bit di questa DB è un allarme numerato che va  da 1 a 64. Come posso quindi fare per risalire a quale bit è quello alto all interno delle 4 word? e fare in modo di trasformare il mio bit in un numero che corrisponde esattamente al numero dell'allarme.

Provo a fare un esempio 

sopraggiunge il primo allarme, DB6.DBX0.0

quindi la W0 della DB6 <> 0, muovo la DB6 nella DB di appoggio. 

in quella DB, chiamiamola DB7 mi troverò DB7.DBX0.0 a 1 e tutto il resto a zero.

 

Il mio problema ora è nel trasformare quel BIT in un numero intero da trasmettere come allarme scatenante di fermo macchina.

Nel mio esempio il valore che dovrò ricavare da quel bit sarà 1.

 

Se il primo allarme fosse il DB6.DBX0.4 il numero da ricavare sarebbe 5.

 

Magari mi sto semplicemente complicando la vita, ma lo scopo che ho è quello di rilevare e "congelare" il primo allarme che causa un fermo macchina assegnandogli un numero univoco.

 

 

 

 

 

 

 

Link al commento
Condividi su altri siti

Un'idea:  

1) Confronta il valore attuale delle word con la loro copia (valore precedente), poi scorri il risultato ed estrai il numero dell'ennesimo bit che trovi variato. Scritto in c

int err_ora;
int err_precedente;
int err_nuovo;
int generatore;

int numero;

err_nuovo = err_ora & (~err_precedente); // and tra l'attuale valore ed il complemento ad 1 del precedente,
err_precedente = err_ora;

//err_nuovo contiene solo i bit che sono stati cambiati
//Scorro la posizione del bit oer ricavare il numero
for (i=0,generatore=1;i++;i<16)
{
	if ((generatore & err_nuovo) && generatore)
    {
    	numero=i; //scovato l'ennesimo bit alzato, prendo il suo numero di posizione
      	break;
    }
	generatore << 1;  //La direzione di scorrimento (>> o << ) dipende dalle caratteristiche del processore
}

 

Link al commento
Condividi su altri siti

Se devo essere sincero avevo un po' di dimestichezza con FPmicro di Matsushita. Ma sono anni che non lo uso.

 

Cx Programmer non lo conosco... ho usato Cx drive, per configurare un inverter, ma di Omron è l'unica cosa che abbia visto.

 

Non saprei come implementare una cosa simile su Omron, volevo darti in idea di massima...

Però credo che le operazioni booleane di base ed i cicli di controllo ci siano anche su Omron.

 

Su fpMicro in c'erano funzioni per il confronto, per lo shift dei bit, per il complemento... quindi penso che valga lo stesso per omron.

 

P.S.

Ma cosa centra Omron con Siemes S7?? :smile:

Link al commento
Condividi su altri siti

Epoch ... io e C siamo una cosa diversa :wacko:

 

Ho poca dimestichezza con Omron... e ho CX... ma non so come possa aiutarmi qui!!:smile:

 

ho provato a capire cosa dici di fare tu, ma a me non serve un reale confronto... mi serve solo pescare il bit alto nelle 4word e assegnargli un valore numerico.

Io sono il tuo cliente, voglio che mi comunichi quale dei 64 allarmi mi causa la fermata macchina. L allarme scatenante si alza, di sicuro in quella scansione del ciclo gli altri 63 sono a zero. facendo quindi un "immagine" del momento in cui 1 delle 4 word diventa diversa da 0 e copiandolo da un altra parte me lo memorizzo.

Il bit è li nel mezzo, ma come capiamo qual'è esattamente quel bit e come gli assegniamo un valore numerico? 

servirebbe come una tabella di riferimento ad ogni bit delle 4 word corrisponde un solo valore numerico.

 

 

Link al commento
Condividi su altri siti

se guardi bene quello che ho scritto, nel ciclo for, quando finisce, ti trovi con numero corrispondente all'errore che è uscito.

da 1 a 15.

Un errore c'è. come limite per il ciclo invece che i<16, bisognava usare <=16, ma comunque il "numero" del bit esce...

 

Link al commento
Condividi su altri siti

senti, io non mastico il PLC da un po di tempo quindi lo prendo come esercizio e ti consiglio di verificare come funziona: ci sono inoltre virtuosi del codice come Batta che avranno soluzioni migliori..... chiedo venia. I bit sono nella DB6 primi 8 bytes, una word di codice numerico e un antiripetizione di fase booleano.

      L     DB6.DBD    0
      L     DB6.DBD    2
      +D   
      L     0
      >D   
      UN    M      0.0
      S     M      0.0                  // antiripetizione di fase
      SPB   alla
      SPA   rme
alla: L     0
      T     MW   100                    // codice di allarme
rito: L     MW   100
      L     1
      +I   
      T     MW   100
      L     DB6.DBD    0                // controlla la prima DWORD
      L     0
      ==D  
      SPB   w2
      L     1
      L     DB6.DBD    0                // controlla la prima DWORD
      RRD  
      SPP   next                        // salta se bit shiftato = 1
      SPA   rito                        // torna indietro se bit = 0
next: BEA  
w2:   L     32
      T     MW   100                    // codice di allarme
rit2: L     MW   100
      L     1
      +I   
      T     MW   100
      L     DB6.DBD    2                // controlla la seconda DWORD
      L     0
      ==D  
      SPB   w3
      L     1
      L     DB6.DBD    2                // controlla la seconda DWORD
      RRD  
      SPP   nex2                        // salta se bit shiftato = 1
      SPA   rit2                        // torna indietro se bit = 0
nex2: BEA  
w3:   BEA                               // qui si potrebbe gestire un altro codice di allarme
rme:  NOP   0

      L     DB6.DBD    0
      L     DB6.DBD    2
      +D   
      L     0
      ==D  
      R     M      0.0                  // resetta l'antiripetizione quando non ci sono + allarmi
      SPB   rese
      SPA   t
rese: L     0
      T     MW   100                    // codice di allarme
t:    NOP   0

Link al commento
Condividi su altri siti

mi sono accorto che bisogna incrementare il puntatore della rotazione oppure memorizzare la DWORD dopo che è ruotata

Non dispongo del PLC e non ci ho perso molto tempo..... fallo tu!

 

Link al commento
Condividi su altri siti

Se nel DB di appoggio (DB7 per seguire l'esempio) anziché dichiarare 4 word dichiari un array di 64 bool (array [1..64] of bool), tutto diventa molto semplice se si utilizza SCL.

Esempio:

FUNCTION FC16 : VOID
VAR_OUTPUT
    nrPrimoAlm : INT;
END_VAR

VAR_TEMP
    i : INT ;
END_VAR

    nrPrimoAlm := 0;

    FOR i := 1 TO 64 DO
        IF "DB_AppAlm".alm[i] THEN
            nrPrimoAlm := i;
            EXIT;
        END_IF;
    END_FOR;

END_FUNCTION

 

Unica accortezza, se vuoi che l'allarme nr.1 corrisponda al primo bit dell'array, prima di trasferire le word al DB di appoggio devi fare uno swap dei byte.

Esempio:

L DB6.DBW0
TAW
T DB7.DBW0
L DB6.DBW2
TAW
T DB7.DBW2
L DB6.DBW4
TAW
T DB7.DBW4
L DB6.DBW6
TAW
T DB7.DBW6

 

Link al commento
Condividi su altri siti

Certamente, ma il nostro cliente vuole ricevere sul supervisore solamente il primo allarme che scatena il fermo macchina con un codice numerico.

Faccio tesoro di tutte le info ricevute ed inizio a lavorarci.

 

Batta, purtroppo da noi nessuno usa SCL. non abbiamo nemmeno il pacchetto installato. Ma.. un mio collega ti ha smascherato .. se un CIP pieno d'acqua finito a -30° ti ricorda qualcosa hai capito anche tu chi siamo noi :wallbash:

 

 

 

 

 

Link al commento
Condividi su altri siti

Scusa gianma, ma almeno ST lo usate?

non è troppo complicato da fare con ST. Ed è abbastanza semplice passare dal listato che ti ho scritto ad ST.

 

Non ho più FPwin installato da un pezzo... Altrimenti provavo a scrivertelo...

Link al commento
Condividi su altri siti

Ci sarebbe anche la funzione Enco (FC96) di libreria, ma come spesso accade è una ciofeca perchè ignora totalmente il primo bit e inizia a contare dal secondo.

Io in tanti anni non ho mai usato le funzioni di libreria perchè hanno sempre qualche limitazione.

 

Ho caricato qui un programmino di esempio fatto in AWL con il puntatore AR1

 

Qua sotto incollo solo l'FB per non appesantire la lettura

FUNCTION_BLOCK "AlarmCatch"
TITLE =Reset
VERSION : 0.1


VAR_INPUT
  Alrm_W1 : WORD ;	
  Alrm_W2 : WORD ;	
  Alrm_W3 : WORD ;	
  Alrm_W4 : WORD ;	
  Reset : BOOL ;	
END_VAR
VAR_IN_OUT
  Done : BOOL ;	
  FirstAlarmFound : INT ;	
END_VAR
VAR
  AlrmMem : ARRAY  [1 .. 64 ] OF //Memoria allarmi
  BOOL ;	
  Edge : ARRAY  [0 .. 16 ] OF //Flags per Fronti
  BOOL ;	
  LoopCtr : INT ;	//Contatore loops
END_VAR
BEGIN
NETWORK
TITLE =Reset

      U     #Reset; 
      SPBN  seg2; 

// Resetta memorie
      R     #Done; 
      L     0; 
      T     #FirstAlarmFound; 
      BEA   ; 


NETWORK
TITLE =Controlla primo allarme in arrivo

seg2: U     #Done; // Se trovato
      BEB   ; // termina qui

// Esegue OR delle WORD
      L     #Alrm_W1; 
      L     #Alrm_W2; 
      OW    ; 
      L     #Alrm_W3; 
      OW    ; 
      L     #Alrm_W4; 
      OW    ; 
      L     0; // Se = 0
      ==I   ; 
      BEB   ; // Termina qui (nessun allarme)


NETWORK
TITLE =Memorizza le dword nella DB d'istanza

      LAR1  P##AlrmMem; // Imposta AR1 per puntare all'inizio dell'array #AlrmMem

// Copia i 64 allarmi nell'array #AlrmMem (area STAT della BD d'istanza)
// swappando i byte per avere la corrispondenza con l'indice dell'array
      L     #Alrm_W1; 
      TAW   ; 
      T     DIW [AR1,P#0.0]; // Memorizza prima word allarmi

      L     #Alrm_W2; 
      TAW   ; 
      T     DIW [AR1,P#2.0]; // Memorizza seconda word allarmi

      L     #Alrm_W3; 
      TAW   ; 
      T     DIW [AR1,P#4.0]; // Memorizza terza word allarmi

      L     #Alrm_W4; 
      TAW   ; 
      T     DIW [AR1,P#6.0]; // Memorizza quarta word allarmi

NETWORK
TITLE =Scansione bit

      L     64; // Predispone contatore 
L1:   T     #LoopCtr; // per eseguire 64 loops

      U     DIX [AR1,P#0.0]; // testa il bit indicizzato da AR1
      SPB   exit; // Se TRUE salta a exit

      +AR1  P#0.1; // Incrementa puntatore per puntare al bit successivo
      L     #LoopCtr; 
      LOOP  L1; // Loop ---> L1

exit: L     65; // 65 - stato contatore loop = nr. allarme trovato
      L     #LoopCtr; 
      -I    ; 
      T     #FirstAlarmFound; 


      SET   ; 
      S     #Done; // setta bit Done




END_FUNCTION_BLOCK

 

Link al commento
Condividi su altri siti

Nicola Carlotto

4 word = 64 bit.

Interroga ogni bit e se a 1 esegui il suo move con il suo numero di allarme su una word di appoggio che chiameremo  " Allarmi".

se li metti in successione il primo bit che va a uno eseguira' il suo move segnalando l'allarme.

se gli allarmi saranno 2 in contemporanea  verra' visualizzato il secondo logicamente ,secondo la scansione plc.

quando le quattro word sono a zero avremo nessun allarme quindi eseguiremo un move zero su "Allarmi".

Ciao

 

Link al commento
Condividi su altri siti

Quote

 

4 word = 64 bit.

Interroga ogni bit e se a 1 esegui il suo move con il suo numero di allarme su una word di appoggio che chiameremo  " Allarmi".

se li metti in successione il primo bit che va a uno eseguira' il suo move segnalando l'allarme.

se gli allarmi saranno 2 in contemporanea  verra' visualizzato il secondo logicamente ,secondo la scansione plc.

quando le quattro word sono a zero avremo nessun allarme quindi eseguiremo un move zero su "Allarmi".

 

Può andar bene anche questo sistema,  ma dopo il primo move bisogna settare un bit che escluda tutto altrimenti continua a fare i move memorizzando gli allarmi successivi.

Per esempio:

      U     "Diagnostica".ResetMemorie
      SPBN  L1

// Reset memorie:
      R     "Diagnostica".AllarmeMemorizzato
      L     0
      T     "Diagnostica".NrPrimoAllarme
      SPA   end



L1:   U     "Diagnostica".AllarmeMemorizzato
      SPB   end

// Controllo allarmi:
      L     1
      U     "Diagnostica".Allarme[1]
      SPB   mem

      L     2
      U     "Diagnostica".Allarme[2]
      SPB   mem

      L     3
      U     "Diagnostica".Allarme[3]
      SPB   mem
      ..............
      ..............
      ..............
      ..............
      ..............
      ..............
      ..............
      ..............
      L     64
      U     "Diagnostica".Allarme[64]
      SPB   mem

      SPA   end

// Memorizzazione primo allarme intervenuto
mem:  S     "Diagnostica".AllarmeMemorizzato
      T     "Diagnostica".NrPrimoAllarme

end:  NOP   0

 

 

L'idea è semplice e non mi dispiace , unica pecca che il codice non è portabile come quello che ho messo prima (FB parametrizzato, che volendo si può pure migliorare inserendo un parametro di tipo ANY per puntare al primo bit di allarme e un altro parametro INT con la quantità di allarmi).

Link al commento
Condividi su altri siti

Nicola Carlotto

verra' visualizzato sempre un solo allarme tra tutti , l'ultimo della scansione, non serve bloccare niente.

pensaci bene e' un bel sistema e semplice .

Ciao

Nicola

Link al commento
Condividi su altri siti

Quote

 

verra' visualizzato sempre un solo allarme tra tutti , l'ultimo della scansione, non serve bloccare niente.

pensaci bene e' un bel sistema e semplice .

Ciao

Nicola

 

Da quello che ho capito io gianma9 vuole sapere quale è stato il primo allarme a mandare in blocco l'impianto, se successivamente subentrano ulteriori allarmi questi non devono essere considerati, quindi va considerata solo la transizione da macchina ok a macchina in blocco.

Se non metti un flag di esclusione lui continua a variare la memoria e credo non vada bene a gianma9, comunque l'idea è buona e applicare il blocco è una stupidata, un flag e un salto, il resto del codice l'ho scritto sulla base di quello che hai spiegato tu, ho solo aggiunto il blocco e di conseguenza il reset. 

Link al commento
Condividi su altri siti

Quote

Scusa gianma, ma almeno ST lo usate?

non è troppo complicato da fare con ST.

ST è quello che Siemens chiama SCL, quindi non utilizzano ST.

 

Quote

Ma.. un mio collega ti ha smascherato .. se un CIP pieno d'acqua finito a -30° ti ricorda qualcosa hai capito anche tu chi siamo noi

Parli del CIP per il quale sono ancora in attesa di una data di partenza?

 

 

Quote

Certamente, ma il nostro cliente vuole ricevere sul supervisore solamente il primo allarme che scatena il fermo macchina con un codice numerico.

Faccio tesoro di tutte le info ricevute ed inizio a lavorarci.

Ma vuole proprio un numero?

Non sarebbe meglio, molto semplicemente, visualizzare sul pannello operatore solo l'allarme che ha causato l'arresto?

In caso affermativo, la soluzione è molto semplice, ed è utilizzato in tutti i casi in cui ad un allarme ne possono seguire molti altri, ma si vuole individuare chi ha causato l'arresto.

 

Supponiamo che tu abbia in DB6 le 4 word di allarme e che il supervisore legga gli allarmi da DB7.

Ad ogni scansione trasferisci queste quattro word da DB6 a DB7.

Sul fronte di salita di un cumulativo degli allarmi imposti un bit "PrimoAllarme" che blocca il trasferimento dal DB6 al DB7.

Ecco che il PLC continua ad aggiornare le variabili di allarme in DB6, ma il supervisore visualizza solo il primo allarme.

Quando l'operatore ha individuato la causa dello stop resetta "PrimoAllarme" e sul supervisore viene nuovamente visualizzata la situazione attuale di tutti gli allarmi.

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...