Vai al contenuto
PLC Forum


S7-SCL: Problema If


hellf

Messaggi consigliati

Salve a tutti,

premetto che sono neofita quindi probabilmente sto sbagliando io qualcosa, ma non riesco a cavarne piede perciò mi affido alla vostra competenza.

Stavo provando un semplice codice SCL con delle Function Call

Anzitutto ho creato due FC (una chiamata GUADAGNO che moltiplica una variabile in ingresso per una costante, e l'altra CONV_REAL che, data una variabile di tipo TIME la converte in un'altra di tipo REAL)

Ho poi creato l'OB1 che le richiami e in fase di simulazione (con s7-PLCSIM) ottenevo i risultati corretti.

Il problema è giunto non appena ho creato un semplice IF nell'OB1 del tipo:

IF out1 <= 250 THEN
    IF Ts <= 25 THEN
        err := 0;
    ELSE
        err := 2;
    END_IF;
ELSE
    IF Ts <= 25 THEN
        err := 1;
    ELSE
        err := 3;
    END_IF;
END_IF;

Dove Ts è la variabile REAL ottenuta tramite conversione della VAR_TIME tempo

Mentre out1 è semplicemente un INT ottenuto tramite la funzione guadagno descritta poche righe fa..

In simulazione non ottengo il valore corretto di Ts e non capisco perché!

Spero di essere stato chiaro, se qualcuno mi può dire dove sto sbagliando mi farebbe un grossissimo favore!

Link al commento
Condividi su altri siti


Posta l'intero codice, perchè così non è affatto chiaro.

In simulazione non ottengo il valore corretto di Ts

Nel codice postato, Ts non viene mai scritto, ma, sempre e solo letto. Dove è il problema?

Se Ts è un REAL, il confronto dovrebbe essere , come minimo:

IF Ts <= 25.0 THEN //

Sicuro di non avere avuto errori di compilazione e semplicemente, hai provato il blocco senza le modifiche caricate?

Link al commento
Condividi su altri siti

Posta l'intero codice, perchè così non è affatto chiaro.

ok allora questo è l'OB1:

ORGANIZATION_BLOCK CICLO
VAR_TEMP
dati_sistema : ARRAY[0..20] OF INT; 
END_VAR

BEGIN
out1 := GUADAGNO(in1);  // out1 = 5*in1
Ts := conv_real(Ta);         // TIME_TO_REAL 

IF out1 <= 250 THEN
    IF Ts <= 25.0 THEN
        err := 0;
    ELSE
        err := 2;
    END_IF;
ELSE
    IF Ts <= 25.0 THEN
        err := 1;
    ELSE
        err := 3;
    END_IF;
END_IF;

END_ORGANIZATION_BLOCK

Con PLCSIM vedo questo:

stampplc.th.png

Come vedi il valore di Ts è sbagliato...ma se elimino l'IF mi restituisce il valore corretto!

e non capisco il perché

Sicuro di non avere avuto errori di compilazione e semplicemente, hai provato il blocco senza le modifiche caricate?

Nono non mi da alcun errore ne alcun avviso!

Poi te l'ho detto, se elimino l'IF è tutto ok..non mi ci raccapezzo...

Che poi la cosa strana è che ho anche provato a fare una cosa, cioè ho creato un'altra variabile out2 di tipo REAL

e se faccio:

out2 := Ts;

mi restituisce il valore corretto :blink:

Link al commento
Condividi su altri siti

Scusa, ma se quello è l'intero OB1:

- dove sono le dichiarazioni di out1, Ts, in1 ed err ??? Sono forse delle variabili dell'area M?

- cosa è GUADAGNO()?? Una funzione tua ?

- non ho mai visto conv_real(). E' di SCL od una funzione tua ?

Per la conversione da REAL ad INT o DINT, io conosco: REAL_TO_INT() e REAL_TO_DINT().

Questo è un estrtto di codice mio, che funziona benone:

  IF P > 32767.0 THEN
    P := 32767.0;
  ELSIF P < -32767.0 THEN
    P := -32767.0;
  END_IF;

Dubito che il problema sia lo statement IF. Prima di tutto, dichiara le variabili allinterno del blocco, così che sia più facile capire cosa stai facendo.

Poi, non fare funzioni in OB1, falle dentro degli FC od FB, ed usa OB1 solo per il loro richiamo. (Non è qui il problema, è solo per chiarezza).

Link al commento
Condividi su altri siti

Scusa, ma se quello è l'intero OB1:

- dove sono le dichiarazioni di out1, Ts, in1 ed err ??? Sono forse delle variabili dell'area M?

- cosa è GUADAGNO()?? Una funzione tua ?

- non ho mai visto conv_real(). E' di SCL od una funzione tua ?

Beh, ora, e correggimi se sbaglio, ma nell'OB1 non si possono dichiarare le variabili In e Out, ma solo var_temp, per questo motivo ho dichiarato il tipo nella lista dei simboli!

la funzione GUADAGNO() E CONV_REAL() sono due semplici FC che ho creato io per provare a programmare in SCL e fare function call, nulla di impegnativo...

Poi, non fare funzioni in OB1, falle dentro degli FC od FB, ed usa OB1 solo per il loro richiamo. (Non è qui il problema, è solo per chiarezza).

Ok provo a fare l'IF in una FC e faccio il richiamo da OB1 e poi ti faccio sapere

Comunque la cosa strana è che comunque se assegno Ts (che è il valore REAL del tempo) ad un'altra variabile ritorna tutto giusto!

Link al commento
Condividi su altri siti

Beh, ora, e correggimi se sbaglio, ma nell'OB1 non si possono dichiarare le variabili In e Out, ma solo var_temp, per questo motivo ho dichiarato il tipo nella lista dei simboli!

Non ti correggo; OB1, come altri OB, è un blocco organizzativo, con una funzione ben determinata. Non ammette la dichiarazione di variabili di ingresso od uscita, perché non è possibile effettuarne la chiamata volontaria. Le funzioni utente si fanno con FC ed FB.

In merito al tuo problema: le funzioni Guadagno() e conv_real() sono già testate? Se posti il codice solo in modo parziale, è evidente che viene subito da pensare che il problema sia altrove.

Link al commento
Condividi su altri siti

Non ti correggo; OB1, come altri OB, è un blocco organizzativo, con una funzione ben determinata. Non ammette la dichiarazione di variabili di ingresso od uscita, perché non è possibile effettuarne la chiamata volontaria. Le funzioni utente si fanno con FC ed FB.

Ah ok..pensavo di non aver capito proprio niente :D

In merito al tuo problema: le funzioni Guadagno() e conv_real() sono già testate? Se posti il codice solo in modo parziale, è evidente che viene subito da pensare che il problema sia altrove.

Le funzioni le ho testate singolarmente e producono il risultato corretto, comunque, ecco i codici delle FC:

GUADAGNO():

FUNCTION GUADAGNO : INT

VAR_INPUT
    valore : INT;
END_VAR

BEGIN
IF valore <= 180 THEN
    guadagno := 5 * valore; //Calcolo del valore della funzione
ELSE
    guadagno := 900; // in caso di overflow
END_IF;
END_FUNCTION
CONV_REAL():
FUNCTION CONV_REAL : REAL

VAR_INPUT
    tempo : TIME;
END_VAR

BEGIN
conv_real := 0.001*DINT_TO_REAL(TIME_TO_DINT(tempo)); //0.001 per fare in modo che 1s == 1.0 
END_FUNCTION
Mentre la lista dei simboli è questa:
CICLO    OB      1    OB      1
CONV_REAL    FC     43    FC     43
err    QW    755    INT
GUADAGNO    FC     42    FC     42
in1    IW    752    INT
out1    QW    752    INT
out2    QD    758    REAL
Ta    ID      1    TIME
Ts    QD    754    REAL

Comunque, come ti ho detto, le FC funzionano correttamente, ma quando inserisco l'IF mi si incasina il risultato finale

ps: Grazie per l'aiuto!

Modificato: da hellf
Link al commento
Condividi su altri siti

Facciamo un passo alla volta:

Gli indirizzi di alcune aree I e Q sono un poco alti. Non so come si comporta il simulatore; nella realtà avresti già molti problemi, il più delle CPU allocano 256 o 512 di IPI ed IPO.

1) Comincia col riportare gli indirizzi delle tue variabili a valori più ragionevoli, magari partendo da 100, in sù. IW100, ID102, etc.

2) Lo statement IF vedo che lo hai già usato altrove, quindi, come ti dicevo, non è questo il problema. Inutile che insisti nel guardare lì.

Link al commento
Condividi su altri siti

Facciamo un passo alla volta:

Gli indirizzi di alcune aree I e Q sono un poco alti. Non so come si comporta il simulatore; nella realtà avresti già molti problemi, il più delle CPU allocano 256 o 512 di IPI ed IPO.

1) Comincia col riportare gli indirizzi delle tue variabili a valori più ragionevoli, magari partendo da 100, in sù. IW100, ID102, etc.

2) Lo statement IF vedo che lo hai già usato altrove, quindi, come ti dicevo, non è questo il problema. Inutile che insisti nel guardare lì.

Ah io ho utilizzato quegli indirizzi perché nella configurazione hardware mi mette di default questo:

confhw.th.png

E siccome volevo provare il codice fisicamente per provare a vedere come sono le uscite e gli ingressi analogici ho pensato di usare quegli indirizzi...

ps: ti rimetto anche la tabella simboli (solo IN e OUT)..secondo te sto sbagliando qualcosa qui?

Ta    ID      1    TIME
in1    IW    752    INT
Ts    QD    754    REAL
out2    QD    758    REAL
out1    QW    752    INT
err    QW    755    INT

ps: spostando gli indirizzi a partire da 100 non funziona O_o

Link al commento
Condividi su altri siti

ok ho risolto finalmente :D

il problema era, come mi dicevi tu, su come indirizzavo i diversi simboli!!!

ho risolto dichiarando Ts come Merker (anche perché effettivamente non mi interessava visualizzarlo come un uscita!)

penso il problema sia che si accavallavano dei bit di err (che era indirizzo QW 755) con i bit di Ts (QD 754)..

visto che la D prende due indirizzi..almeno così mi sembra di aver capito!!

Secondo te può essere questo il motivo per cui entrava in conflitto???

ps: l'ho notato perché facendo alcune prove, in base al valore di err mi si modificava di un valore pari a 10e-3 il valore di Ts

Link al commento
Condividi su altri siti

Siemens, per tradizione, indirizza tutto a byte. Se allochi una word od una dword, ecc, devi fare molta attenzione a non sovrapporre gli indirizzi: esempio, una dword indirizzata a MD100, prende: MB103, MB102, MB101 e MB100.

Link al commento
Condividi su altri siti

Siemens, per tradizione, indirizza tutto a byte. Se allochi una word od una dword, ecc, devi fare molta attenzione a non sovrapporre gli indirizzi: esempio, una dword indirizzata a MD100, prende: MB103, MB102, MB101 e MB100.

ghgh me ne sono accorto a mie spese!! :)

in ogni caso davvero grazie mille per le risposte e lo stress che ti ho provocato sti giorni..mi sei stato davvero d'aiuto!!!!

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