Vai al contenuto
PLC Forum

Partecipa anche tu alla Live su Youtube martedì 28/01/2025 per festeggiare i 24 anni di PLC Forum

Per ulteriori informazioni leggi questa discussione: https://www.plcforum.it/f/topic/326513-28012025




Comando Di Un Uscita Da Più Bit


Messaggi consigliati

Inserito:

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


Inserita:

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.

Inserita:

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

Inserita: (modificato)

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
Inserita:

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

Inserita:

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 :)

Inserita:

dan.....in scl due righe :smile:

e levarmi il gusto di giocherellare con AR1 ??? :lol:

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

Inserita:

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

Inserita: (modificato)

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
Inserita:

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

Inserita:

salve a tutti, ho provato il suggerimento di Walter e naturalmente ha funzionato bene. proverò quella di Jump.......veramente snella.

grazie

saluti!

Inserita:

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.

Inserita:

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

Inserita:

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

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