Vai al contenuto
PLC Forum


fare una tabella dati con CJ1M


MABE

Messaggi consigliati

Buongiorno

ecco il mio problema

due variabili che chiamo X, Y,

- quando la variabile X assume il valore X1, misuro il valore di Y che chiamerò Y1

- quando la variabile X assume il valore X2, misuro il valore di Y che chiamerò Y2

- quando la variabile X assume il valore Xn, misuro il valore di Y che chiamerò Yn

devo verificare che per ogni valore Y registrato questo sia compreso tra due limiti, quindi:

D1<Y1<D2

D3<Y2<D4

Dn<Yn<Dn+1

credo che dovrei realizzare una tabella dei valori registrati,

una tabella dei limiti

ed infine riuscire a fare confrontare le tabelle.

ma non riesco a capire quali sono i comandi che devo utilizzare per fare questo.

non ho mai utilizzato comandi per gestione tabelle.

Ringrazio anticipatamente chi mi può dare un consiglio, o meglio ancora un piccolo esempio da cui prendere spunto

Link al commento
Condividi su altri siti

  • 3 weeks later...

Ciao. Non sembra difficile.

In pratica hai bisogno di 3 array contenenti rispettivamente i valori Yn, quelli D inferiori e quelli D superiori, il cui indice è il valore di n.

Quindi Y[n], Dinf[n], Dsup[n]. Nel tuo discorso non è chiaro cosa deve succedere se il valore di X è tra Xn-1 e Xn...

Suppongo che sia un tempo, e che ogni tot tempo fa la lettura e incrementa l'indice Xn

 

Sul CJ non si possono usare array indicizzati da variabili, ma si possono usare liberamente i registri indice o i puntatori.

Quindi, definite le tre aree contenenti i dati Y, Dinf, Dsup e puntando all'inizio al primo elemento di ciascuna di tali aree, al cambiare di Xn andrai a leggere l'n-esimo elemento di ciascuna area, ottenendo tre valori, che confronterai per ottenere il risultato voluto, cioè per esempio 1 se Dinf[n]<Y[n]<Dsup[n], 0 altrimenti.

 

Spiega casomai un po' meglio come devi precaricare i valori nelle tabelle e come varia la X (che dovrà essere quantizzata).

Link al commento
Condividi su altri siti

Buongiorno Ctec

prima di tutto vorrei ringraziarti, per la tua attenzione.

la variabile x sono dei valori che mi arrivano da un encoder, quindi delle quote

la variabile Y sono valori di un segnale analogico (trasduttore di pressione per intenderci)

quindi:

quando arrivo alla quota X1, il trasduttore di pressione segnerà un valore Y1

quando arrivo alla quota X2, il trasduttore di pressione segnerà un valore Y2

quando arrivo alla quota Xn, il trasduttore di pressione segnerà un valore Yn

il passo tra ogni misura X, dovrebbe essere di circa 1mm (o meglio un valore che gestirò con DM).

ad esempio:

X1= 10 mm -> Y1=1000

X2= 11 mm -> Y2=1200

X3= 12 mm -> Y3=1500

limiti di accettabilità

900<Y1<1100

1150<Y2<1250

1400<Y3<1550

quindi per capire come procedere:

carico il valore di X1 in D1

carico il valore di X2 in D2

carico il valore di X3 in D3.

carico il valore di Y2 in D102

carico il valore di Y2 in D102

carico il valore di Y3 in D103

limiti inferiori

carico il valore 900 in D200

carico il valore 1150 in D201

carico il valore 1400 in D202

limiti superiori

carico il valore 1100 in D300

carico il valore 1250 in D301

carico il valore 1550 in D300

per fare questa operazione di carico valori nelle variabili, posso usare il comando MOV per farlo, oppure si usa un altro comando?

a questo punto devo dire al PLC quali sono le aree occupate dai vari dati: che comando si utilizza?

mi fermo qui, perché sono già in difficoltà.

Grazie

 

Link al commento
Condividi su altri siti

ifachsoftware

Cerco di tradurre :

 

Hai una serie di posizioni di un encoder (0....xxx [mm])

per ogni posizione devi controllare che la pressione letta coincida con un range min/max di valori legati alla posizione dell'encoder , immagino per dare un allarme nel caso i cui non rientri.

E' corretto ?

 

Link al commento
Condividi su altri siti

ifachsoftware

Personalmente ti consiglio di realizzare il tutto in ST

 

Definirei un tipo di dato 

 

TYPE STRU_DATA :
   STRUCT
      POS      : INT;
      PRESSURE : REAL;
   END_STRUCT
END_TYPE

 

 

E poi dichiarerei un array di dati globali nel seguente modo

 

VAR MAX_POS  : INT := 9;

VAR TRESHOLD  :REAL := 1.5;

 

LSTDATA[0..MAX_POS] OF STRU_DATA;

 

in pratica in questo array lo popolerei all'inizializzazione del PLC  con un programma del tipo

 

LSTDATA[0].POS := 0;
LSTDATA[0].PRESSURE := 0.0;

LSTDATA[1].POS := 10;
LSTDATA[1].PRESSURE := 10.0;

LSTDATA[2].POS := 20;
LSTDATA[2].PRESSURE := 20.0;

LSTDATA[3].POS := 30;
LSTDATA[3].PRESSURE := 30.0;

LSTDATA[4].POS := 40;
LSTDATA[4].PRESSURE := 40.0;

LSTDATA[5].POS := 50;
LSTDATA[5].PRESSURE := 50.0;

LSTDATA[6].POS := 60;
LSTDATA[6].PRESSURE := 60.0;

LSTDATA[7].POS := 70;
LSTDATA[7].PRESSURE := 70.0;

LSTDATA[8].POS := 80;
LSTDATA[8].PRESSURE := 80.0;

LSTDATA[9].POS := 90;
LSTDATA[9].PRESSURE := 90.0;
 

 

Avendo cura di inserire i dati in ordine crescente per posizione

 

Poi realizzerei una funzione del tipo :

FUNCTION BINSEARCH : INT

VAR_INPUT
   LSTDATA : ARRAY[0..10] OF STRU_DATA;  (* Array di dati *)
   search : INT;                        (* Valore da cercare *)
END_VAR

VAR
  c : INT;
  first : INT := 0;
  last  : INT := 9;
  middle : INT;
END_VAR

 

WHILE (first <= last) DO
   IF (LSTDATA[middle].POS = search) THEN
      (* TROVATO *)
      BINSEARCH := middle;
      RETURN;
   END_IF;


   IF (LSTDATA[middle].POS < search) THEN
      IF middle + 1 <= last THEN
         IF (LSTDATA[middle + 1].POS > search) THEN
            (* TROVATO *)
            BINSEARCH := middle + 1;
            RETURN;
         END_IF;
      END_IF;
     ELSE
      IF (LSTDATA[middle - 1].POS < search) THEN
         (* TROVATO *)
         BINSEARCH := middle -1;
         RETURN;
      END_IF;
   END_IF;

  IF (LSTDATA[middle].POS < search) THEN
         first := middle + 1;
      ELSIF (LSTDATA[middle].POS = search) THEN
         (* TROVATO *)
         BINSEARCH := middle;
         RETURN;
      ELSE
         last := middle - 1;
   END_IF;

   middle := (first + last) / 2;
END_WHILE

 

A questo punto abbiamo fatto una ricerca binaria che mi trova in base alla posizione da cercare l'indice della corrispondente Pressione

 

Per usarla potremmo scrivere un programma del tipo :

VAR_GLOBAL
    SearchPos : INT := 3;
    FoundPos : INT := 0;
    FoundValue : REAL := 0.0;
END_VAR

 

FoundPos := BINSEARCH(LSTDATA := LSTDATA, search := SearchPos);

IF (FoundPos <> -1) THEN
   FoundValue := LSTDATA[FoundPos].PRESSURE;
  ELSE
   FoundValue := -1.0;
END_IF;

 

Dove avremo in FoundValue il valore di pressione trovato ; a questo punto dovresti fare una comparazione tra i vari limiti per capire se siamo in errore oppure no

 

 

(ti faccio presente che tale codice è stato scritto con SCL di CODESYS , ma non dovrebbe essere difficile riportarlo al tuo ambiente)

 

 

 

 

 

 

 

 

 

Link al commento
Condividi su altri siti

grazie ifach

ma devo farti una premessa.

non conosco il linguaggio ST

solo ladder.

si tratta di una macchina di collaudo (meccanicamente semplicissima), per alcuni nostri prodotti che ci stiamo realizzando internamente.

la complessità della macchina sta solo in questa verifica, che è un tipo di verifica che non abbiamo mai affrontato.

Link al commento
Condividi su altri siti

ifachsoftware

Ciao , nessuno ti vieta di copiare solo la parte SCL della funzione di ricerca e scrivere tutto il resto il ladder , richiamando il blocco funzione dal ladder.

 

Fare una ricerca binaria con dei cicli for in Ladder non lo ritengo fattibile.

 

 

 

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