Vai al contenuto
PLC Forum


problemi con modbus e scansione


Frank681

Messaggi consigliati

Salve

 

Ho creato un FB che richiamo piu volte , al cui interno scrivo e leggo i dati dal modbus rtu.

Fincheà uso solo un fb tuto ok  ma se ne metto piu di uno ho errore mod bus poichè tovo il bus occupato , come posso fare in modo che finche no ho finito di elaborare il primo fb  l'altro non veng apreso in considerazione.

Ho provato con un CNT appoggiato su un db e alla fine del primo fb incremento, all afine dell'ultimo fb lo resetto a 1 , poi l'abilitazione fb e fatta con un uguaglianza del contatore .

 

il mio problem ache dopo i primi 2 il contatore non mi avanza dove sbaglio

 

Grazi emille

Link al commento
Condividi su altri siti


perchè il modbus intrinsecamente instaura la comunicazione con uno slave per volta, non puoi avere due comunicazioni contemporanee sul medesimo supporto fisico, quindi come dici un solo FB in funzione e il motivo mi sembra ovvio

Link al commento
Condividi su altri siti

8 ore fa, leleviola scrisse:

perchè il modbus intrinsecamente instaura la comunicazione con uno slave per volta

 

Non è del tutto corretto perchè è possibile inviare un comando "broadcast" a tutti gli slave; ovviamente poi la risposta è di un solo slave alla volta.

Link al commento
Condividi su altri siti

6 ore fa, Livio Orsini scrisse:

 

Non è del tutto corretto perchè è possibile inviare un comando "broadcast" a tutti gli slave; ovviamente poi la risposta è di un solo slave alla volta.

si solo col comando broadcast invii un comando a tutti è che la risposta può essere da un solo dispositivo per volta ma i normali comandi sono indirizzati ogni volta a un solo dispositivo e ogni volta le tempistiche di risposta sono limitate dalla bassa velocità possibile del bus che in genere è limitato a non molti baud possibili

Link al commento
Condividi su altri siti

Salve

 

io vorrei fare si che uno volta comunicato con inverter 1 tramite FB mi apassi al 2 , poi al 3 ecc.. ecc.. logicamente gli FB hanno db di istanza diversi , devo solo capire come internamente all FB fare si che a fine ciclo di comunicazione 1 scrittura e 2 letture usando il done possa portare esternamente un contatore o simile in modo che posso passare alláltro FB, avevo pensato di usare il done dellúltima lettura dentro Fb per poter incrementare un contatore e poi a seconda del numero richiamare FB corrispondente per inv 1 ..  6 ma sto trovando dell difficolta'mi servirebbe un suggerimento.

 

Grazie mille

Link al commento
Condividi su altri siti

1 ora fa, Frank681 scrisse:

avevo pensato di usare il done dellúltima lettura dentro Fb per poter incrementare un contatore e poi a seconda del numero richiamare FB corrispondente per inv 1 ..  6 ma sto trovando dell difficolta'mi servirebbe un suggerimento.

Il principio è corretto. Quali sono le difficoltà che incontri? Cosa non ti funziona?

Link al commento
Condividi su altri siti

59 minuti fa, batta scrisse:

Il principio è corretto. Quali sono le difficoltà che incontri? Cosa non ti funziona?

ho un contatore in una variabile temporanea interna all FB che mi scansiona i 1 step di comunicazione 1 scrittura di 2 word e 2 letture di stato inverter e corrente e frequenza di funzionamento , fin qui tutto OK se ho un solo fb di richiamo , il mio problema e che quando metto anche solo 2 FB / Inverter come fare in modo che solo un FB alla volata venga valutato , ho provato mettere sullúltimo step interno all'FB un uscita con fronte in modo da poter fare avanzare un contatore nel main per diversificare FB , ma mi si blocca a 2 , non me li fa tutti e 6.

Non trovo dove e'il problema

 

Grazie

Link al commento
Condividi su altri siti

2 ore fa, Frank681 scrisse:

ho un contatore in una variabile temporanea interna all FB

Non puoi usare una variabile temporanea per fare un contatore, devi usare una variabile nell'area STAT.
La variabile temporanea, quando esci dal blocco, non esiste più e, al successivo richiamo, non trovi il valore che aveva precedentemente.
Con il 300 le variabili temporanee potevano assumere un valore qualsiasi (la stessa area di memoria poteva essere usata da un'altra funzione, e chi lo sa cosa poteva contenere?).
Con il 1200/1500 le variabili temporanee vengono reinizializzate a zero dal sistema.

Link al commento
Condividi su altri siti

2 ore fa, batta scrisse:

Non puoi usare una variabile temporanea per fare un contatore, devi usare una variabile nell'area STAT.
La variabile temporanea, quando esci dal blocco, non esiste più e, al successivo richiamo, non trovi il valore che aveva precedentemente.
Con il 300 le variabili temporanee potevano assumere un valore qualsiasi (la stessa area di memoria poteva essere usata da un'altra funzione, e chi lo sa cosa poteva contenere?).
Con il 1200/1500 le variabili temporanee vengono reinizializzate a zero dal sistema.

Ciao Batta

 

Intanto grazie per il supporto

 

Gli FB li richiamo nell'OB1 per cui non ho variabili stat, ho provvato comunque ad utilizzare una variabile int in un DB ma il pronlema persiste devo capire dove sta il problema

 

non volevo scrivere tutto in OB1 appoggiandomi a dei DB volevo provare a creare un FB riutilizzabile , unico neo per i dati da dare in pasto al MB devo per forza passare da un DB non otimizzato altrimenti ho errore non posso neanche usare struct del db di istanza del mio FB.

 

Sono testardo ma ci riuscirò.

 

Link al commento
Condividi su altri siti

Una domanda

 

per il counter interno all FB uso una variabile STAT e funziona , visto che ho 3 blocchi 1 di scrittura e 2 di lettura MB per i done/busy/erro sto usando array di variabili stat è correto?

 

il mio cnt va da 1 a 3 uno per blocco come posso fare per dare un impulso fuori dall'fb per attivare l'incremento del contatore esterno per variare l'inverter da programmare.

è corretto usare tale contatore nell'abilitazione dell FB dell'inverter.

 

Grazie

Link al commento
Condividi su altri siti

14 ore fa, Frank681 scrisse:

è corretto usare tale contatore nell'abilitazione dell FB dell'inverter.

Difficile dare un gidizio partendo dalla tua descrizione, senza vedere il codice.

Link al commento
Condividi su altri siti

10 ore fa, batta scrisse:

Difficile dare un gidizio partendo dalla tua descrizione, senza vedere il codice.

posso postare il codice se non va fuori dalle regole.

Link al commento
Condividi su altri siti

11 ore fa, Frank681 scrisse:

posso postare il codice se non va fuori dalle regole

 

E previsto addirittura un comando per inserire codice nel messaggio, quello con l'icona "<>". Premi quel tasto e poi incolli il tuo codice nella finesra che apparirà

Link al commento
Condividi su altri siti

3 ore fa, Livio Orsini scrisse:

 

E previsto addirittura un comando per inserire codice nel messaggio, quello con l'icona "<>". Premi quel tasto e poi incolli il tuo codice nella finesra che apparirà

Ecco il mio codice in SCL , inizialmente lo avevo fatto in KOP e con un solo inverter funzionava ora in SCL mi da errore 8180  come mai nel OB1 al primo scan inizializzo MB_COMM_LOAD con successo.

 

// VERIFICA MASSIMO NUMERO DI INTERROGAZIONI
IF #CNT>3 OR #CNT<1 THEN
    #CNT := 1;
END_IF;

// CALCOLO LIMITI PARTENZA
#APP_REAL[0]:=#SP_T-#IST;
#APP_REAL[1]:=#SP_T+#IST;

IF (#"REG A/M"<>TRUE )THEN
    IF (#T<#APP_REAL[0])THEN // Statement section IF
        #CMD := TRUE;
    ELSIF (#T>#APP_REAL[1])THEN
        #CMD := FALSE;
    END_IF;
END_IF;

// PREPARAZIONE PAROLA DI COMANDO PER SCRITTURA DATI MB
#W_DATA.STW.%X0 := #CMD;
#W_DATA.STW.%X1 := TRUE;
#W_DATA.STW.%X2 := TRUE;
#W_DATA.STW.%X3 := TRUE;
#W_DATA.STW.%X4 := #ENABLE;
#W_DATA.STW.%X5 := TRUE;
#W_DATA.STW.%X6 := TRUE;
#W_DATA.STW.%X7 := #ACK;
#W_DATA.STW.%X10 := TRUE;
#W_DATA.STW.%X11 := #DIRECTION;

// CALOLO FREQ RIFERIMENTO
#W_DATA.HSW:= INT_TO_WORD( REAL_TO_INT((16384/#HZ_MAX)*#REF_SPEED));
// COPIO DATI IN DB PER COMUNICAZIONE MB 
"PARK DATI MB".W_DATA := #W_DATA;

// SRITTURA WORD COMANDO E RIFERIMENTO
#APP_BOOL[0] := (#CNT = 1) AND (#STATUS_COMM_MB.BUSY[0] = FALSE);

"MB_MASTER_DB_V20"(REQ:=#APP_BOOL[0],
                 MB_ADDR:=#"MB ADDR",
                 MODE:=1,
                 DATA_ADDR:=40100,
                 DATA_LEN:=2,
                 DONE=>#STATUS_COMM_MB.DONE[0],
                 BUSY=>#STATUS_COMM_MB.BUSY[0],
                 ERROR=>#STATUS_COMM_MB.ERROR[0],
                 STATUS=>#STATUS_COMM_MB.STS[0],
                 DATA_PTR:="PARK DATI MB".W_DATA);

IF (#STATUS_COMM_MB.DONE[0]=TRUE) THEN
    #CNT:=#CNT+1;
ELSIF (#STATUS_COMM_MB.ERROR[0]) THEN
    #CNT := #CNT + 1;
END_IF;

// LETTURA STATO INVERTER E FREQUENZA EFFETTIVA
#APP_BOOL[1] := (#CNT = 2) AND (#STATUS_COMM_MB.BUSY[1] = FALSE);

"MB_MASTER_DB_V20"(REQ := #APP_BOOL[1],
                   MB_ADDR := #"MB ADDR",
                   MODE := 0,
                   DATA_ADDR := 40110,
                   DATA_LEN := 2,
                   DONE => #STATUS_COMM_MB.DONE[1],
                   BUSY => #STATUS_COMM_MB.BUSY[1],
                   ERROR => #STATUS_COMM_MB.ERROR[1],
                   STATUS => #STATUS_COMM_MB.STS[1],
                   DATA_PTR := "PARK DATI MB".R_DATA);

IF (#STATUS_COMM_MB.DONE[1] = TRUE) THEN
    #CNT := #CNT + 1;
    #R_DATA := "PARK DATI MB".R_DATA;
ELSIF (#STATUS_COMM_MB.ERROR[1] = TRUE) THEN
    #CNT := #CNT + 1;
END_IF;

// LETTURA CORRENTE E VELOCITA
#APP_BOOL[2] := (#CNT = 3) AND (#STATUS_COMM_MB.BUSY[2] = FALSE);

"MB_MASTER_DB_V20"(REQ := #APP_BOOL[2],
                   MB_ADDR := #"MB ADDR",
                   MODE := 0,
                   DATA_ADDR := 40024,
                   DATA_LEN := 3,
                   DONE => #STATUS_COMM_MB.DONE[2],
                   BUSY => #STATUS_COMM_MB.BUSY[2],
                   ERROR => #STATUS_COMM_MB.ERROR[2],
                   STATUS => #STATUS_COMM_MB.STS[2],
                   DATA_PTR := "PARK DATI MB".R_OTHER);

// SE OK COPIO VALORI LETTI
IF (#STATUS_COMM_MB.DONE[2] = TRUE) THEN
    #CNT := 1;
    #"RUN FREQ" := ((DINT_TO_REAL(WORD_TO_DINT(#R_OTHER[0])))/100.0);
    #ASSORBIMENTO := ((DINT_TO_REAL(WORD_TO_DINT(#R_OTHER[2]))) / 100.0);
    #R_DATA := "PARK DATI MB".R_DATA;
// ERRORE AVANZO    
ELSIF (#STATUS_COMM_MB.ERROR[2] = TRUE) THEN
    #CNT := 1;
    GOTO LAST_ERR;
END_IF;

// DECODIFICA STATI INVERTER
#Q_RUN := #R_DATA.ZSW.%X2;
#Q_FAULT := #R_DATA.ZSW.%X3;
#Q_READY := #R_DATA.ZSW.%X0;
#Q_READY_RUN := #R_DATA.ZSW.%X1;

LAST_ERR:
"R_TRIG_DB"(CLK:=#STATUS_COMM_MB.ERROR[2],
            Q=>#Q_NEXT);
;

 

inoltre mi piacerebbe rendere il codice riusabile in modo che alla fine del fb mi venisse portato fuori un segnale in modo da incrementare il contatore esterno per il richiamo dell'FB sucessivo.

 

Spero di essere stato chiaro

 

Grazie mille a tutti

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