Vai al contenuto
PLC Forum


Comando Di Un Uscita Da Più Bit


UR65

Messaggi consigliati

buongiorno a tutti,

ho la necessità di comandare un'uscita con l'intervento di uno qualunque dei tanti bit di una db.

per evitare che uno imposti a 0 e l'altro a 1, e fare fallire il comando, ho pensato di interrogare il fronte di salita.

mi chiedevo: esiste un comando o un blocco che controlla tutti i bit di una data area di byte?

questo per evitare di scrivere un'istruzione lunga sia a bit che a word.

grazie per l'aiuto.

buona domenica!

ma rispondetemi

Link al commento
Condividi su altri siti


Come l'hai impostata la domanda non è chiara.

Comunque se ti limiti a settare o resettare l'uscita in funzione dello stato dei bits l'uscita prenderà lo stato dell'ultimo bit testato; questo avverrà solo alla fine del ciclo quando la tabella immagine viene copiata sulle uscite fisiche.

Se invece vuoi che l'uscita vada alta se anche uno solo dei bits interessati sia alto, alla fine del ciclo di programma fai un or tra i vari bits ed al primo "1" alzi l'uscita.

Link al commento
Condividi su altri siti

Ciao,

se non ho capito male vuoi sapere se, data una DB, almeno uno dei suoi bit è alto.

Io ho scritto tempo fa questa FC, lavora su un'intera DB (che gli passi come parametro), in output hai un booleano (FOUND) che ti dice se almeno un bit è alto e un intero (INDEX) che ti dice quale bit è alto.

Adattamenti:

Se ti interessa lavorare con un area di memoria arbitraria devi modificare il parametro d'ingresso DATA facendolo diventare ANY ed estraendo all'interno dell'FC il numero della DB, start e la lunghezza.

Se non ti interessa conoscere l'indice del bit puoi cancellare il segmento 2 (tranne la label e le istruzioni SET e = #FOUND) e il segmento 3.

FUNCTION "TEST_ZERO" : VOID
TITLE =
//Cerca il primo Bit alto in una DB
//IN
//  DATA  : DB sorgente
//OUT
//  FOUND : True se esiste un bit alto, False se la DB è tutta a zero 
//  INDEX : Indice del primo bit alto 
//          NOTA:
//            Primo bit   DBX0.0 -> Indice=1
//            Secondo bit DBX0.1 -> Indice=2 ecc..
//  Se FOUND=FALSE -> INDEX=0         
AUTHOR : Nardella
FAMILY : UTILS
NAME : Z_TEST
VERSION : 0.1


VAR_INPUT
  DATA : BLOCK_DB ;	//DB Sorgente
END_VAR
VAR_OUTPUT
  FOUND : BOOL ;	//=True se esiste un bit a 1
  INDEX : INT ;	//Indice del bit alto (primo bit=1)
END_VAR
VAR_TEMP
  AUX_LOOP : INT ;	
  BIT_IDX : INT ;	
  BYTE_IDX : INT ;	
  AUX_BYTE : BYTE ;	
END_VAR
BEGIN
NETWORK
TITLE =
//Ricerca del primo Byte <> 0
// Calcolo lunghezza DB
      OPN   #DATA; 
      L     DBLG; 
      T     #AUX_LOOP; 

// Azzeramento indici
      L     0; 
      T     #BYTE_IDX; 
      T     #BIT_IDX; 

// Setup puntatore e contatore loop
      L     P#DBX 0.0; 
      LAR1  ; 

      L     #AUX_LOOP; 
LOOP: T     #AUX_LOOP; 

// Test Byte
      L     B [AR1,P#0.0]; 
      T     #AUX_BYTE; 
      L     0; 
      <>I   ; 
      JC    FND; 

// Incremento puntatore e indice byte
      +AR1  P#1.0; 
      L     #BYTE_IDX; 
      L     1; 
      +I    ; 
      T     #BYTE_IDX; 

// test and loop
      L     #AUX_LOOP; 
      LOOP  LOOP; 

// Nessun Byte <>0
      L     0; 
      T     #INDEX; 
      CLR   ; 
      =     #FOUND; 
      JU    END; 
NETWORK
TITLE =
//Ricerca del bit all'interno del byte
FND:  SET   ; 
      =     #FOUND; 

      L     #AUX_BYTE; 
      L     W#16#1; 
      AW    ; 
      JZ    BIT1; 
      L     1; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT1: L     #AUX_BYTE; 
      L     W#16#2; 
      AW    ; 
      JZ    BIT2; 
      L     2; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT2: L     #AUX_BYTE; 
      L     W#16#4; 
      AW    ; 
      JZ    BIT3; 
      L     3; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT3: L     #AUX_BYTE; 
      L     W#16#8; 
      AW    ; 
      JZ    BIT4; 
      L     4; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT4: L     #AUX_BYTE; 
      L     W#16#10; 
      AW    ; 
      JZ    BIT5; 
      L     5; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT5: L     #AUX_BYTE; 
      L     W#16#20; 
      AW    ; 
      JZ    BIT6; 
      L     6; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT6: L     #AUX_BYTE; 
      L     W#16#40; 
      AW    ; 
      JZ    BIT7; 
      L     7; 
      T     #BIT_IDX; 
      JU    CALC; 

BIT7: L     8; 
      T     #BIT_IDX; 

NETWORK
TITLE =Calcolo indice


CALC: L     #BYTE_IDX; 
      SLD   3; 
      L     #BIT_IDX; 
      +I    ; 
      T     #INDEX; 
NETWORK
TITLE =ENO

END:  SET   ; 
      SAVE  ; 

END_FUNCTION

Buona domenica anche a te

Davide

Link al commento
Condividi su altri siti

se i bit che attivano l'uscita che ti interessa sono contigui puoi valutare se la o le word in questione sono maggiori di zero .

Se invece i bit sono sparpagliati a caso in giro per il DB allora li metti in OR logico

Modificato: da walterword
Link al commento
Condividi su altri siti

grazie, molto gentili, soprattutto perché ieri era domenica........

comunque risolverò con sicurezza grazie alle vostre indicazioni e visto che i bits sono contigui e non ho necessità di individuare il bit in particolare, farò come mi ha indicato Walterword.

grazie a tutti

Link al commento
Condividi su altri siti

per correttezza , devi valutare se la o le words sono diverse da zero , non uguali .....il discorso del bit di segno ect ect ....;)


dan.....in scl due righe :)

Link al commento
Condividi su altri siti

devi valutare se la o le words sono diverse da zero , non uguali ...

Walter avevi già scritto:

valutare se la o le word in questione sono maggiori di zero .

Se sono maggiori di 0 sono anche diverse da zero :smile:

e levarmi il gusto di giocherellare con AR1

A volte è divertente, è come programmare in assembler; però quando devi produrre.....

Link al commento
Condividi su altri siti

Non ho esaminato bene l'esempio di Dan, ma credo faccia più di quello che serve...

Essendo io passato per S5 tendo sempre a inserire il minimo di istruzioni possibile, se dovessi p.es. esaminare una DB con 256 bit (immagino siano gli allarmi)

per vedere se almeno uno è TRUE farei così:

L DBD 0

L DBD 4

OD

L DBD 8

OD

L DBD 12

OD

L DBD 16

OD

L DBD 20

OD

L DBD 24

OD

L DBD 28

OD

L L#0

<>D

= "PresenzaAllarme"

Poi ovvio che se devo fare un FC/FB flessibile parametrizzato e adattabile a qualsiasi DB non farei così, ci sono 1000 modi di fare la stessa cosa...

Link al commento
Condividi su altri siti

Le DB erano di dimensioni variabili, alcune di 4k, motivo per cui non ho usato SCL.

Ed era importante conoscere l'indice, altrimenti il codice si dimezza.

Modificato: da dan64100
Link al commento
Condividi su altri siti

Lavorando a doppia word anzichè a byte ne esce un codice molto snello:

      SET   
      R     #xTemp1                     // Azzera bool locale

      L     #NrDB                       // Nr DB da aprire
      T     #wTemp1
      AUF   DB [#wTemp1]                //    Apre la DB

      L     #PrimaDBW                   // Nr prima DBW
      SLW   3
      LAR1                              //    imposta puntatore


      L     #QtaDBW                     // Quantità DBW
L1:   T     #iCtr                       //    imposta contatore loops

      L     DBD [AR1,P#0.0]
      L     L#0
      <>D                               // Se trovato DBW <> 0 
      S     #xTemp1                     //    setta bit temp

      +AR1  P#4.0

      L     #iCtr
      LOOP  L1

      U     #xTemp1
      =     #Found


Richiamo in OB1:

      CALL  FC     1
       NrDB    :=2
       PrimaDBW:=0
       QtaDBW  :=8
       Found   :=M10.0

Link al commento
Condividi su altri siti

Per snellire ancor di più l'esecuzione puoi uscire dal loop appena trovi un bit:

      SET   
      R     #xTemp1                     // Azzera bool locale

      L     #NrDB                       // Nr DB da aprire
      T     #wTemp1
      AUF   DB [#wTemp1]                //    Apre la DB

      L     #PrimaDBW                   // Nr prima DBW
      SLW   3
      LAR1                              //    imposta puntatore


      L     #QtaDBW                     // Quantità DBW
L1:   T     #iCtr                       //    imposta contatore loops

      L     DBD [AR1,P#0.0]
      L     L#0
      <>D                               // Se trovato DBW <> 0 
      S     #xTemp1                     //    setta bit temp
      SPB end                           ///   ---> end

      +AR1  P#4.0

      L     #iCtr
      LOOP  L1

end:  U     #xTemp1
      =     #Found

Alla fine questo codice devo dire che risulta molto simile a quello di dan64100 (ripulito della parte che calcola l'indice del bit) solo che lavorando a doppia-word il plc esegue meno istruzioni.

Link al commento
Condividi su altri siti

La soluzione della DoubleWord è senz'altro quella più veloce ;) soprattutto se serve solo sapere se è tutto zero o meno.

Per un utilizzo generico però bisogna fare attenzione che che tutto sia allineato a DBD (o meglio che l'area da analizzare sia multipla di 4).

Link al commento
Condividi su altri siti

dan , io sono ignorante e molto limitato .Faccio sempre fatica a capire cosa vogliono o cosa devo fare .

Per questo che sono sempre cosi sintetico :D

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