Jump to content
PLC Forum


Problemi comunicazione Modbus RTU


Recommended Posts

Mykola
Posted

 Buongiorno a tutti. Scusate se faccio qualche errore grammaticale, non sono madrelingua italiano. Sono nuovo nel settore della programmazione PLC e sto lavorando al mio primo progetto che riguarda l’automazione di 7 pompe tramite il protocollo Modbus RTU.
Ho scritto in modo semplice la lettura e scrittura dei registri di ogni softstarter delle pompe, creando una catena di richieste: cioè, utilizzando l’uscita del blocco funzione ModRtuMast relativo all’ultimo dispositivo con la condizione NOT Busy OR Done per attivare l’ingresso Execute della prima richiesta di lettura dei registri a 16 bit; successivamente, con la stessa condizione, attivavo il blocco ModRtuMast per la scrittura di 32 coil dello stesso softstarter. Poi ripetevo la lettura e scrittura per il softstarter successivo, e così via. 

Quando facevo delle prove avevo soltanto un softstarter e tutto sembrava funzionare correttamente, ma quando ho provato nell’impianto reale con 7 softstarter ho iniziato a ricevere degli errori di comunicazione.
Il PLC e i softstarter sono della marca ABB: il PLC modello PM5052-T-ETH e i softstarter della serie PSTX.
L’errore che compare è ‘P1 E00’ — Errore di comunicazione Fieldbus. Il bus non è lungo: tutti i dispositivi si trovano nella stessa stanza e sono collegati in serie. Alla fine del bus ho inserito anche una resistenza da 120 Ohm. La schermatura del cavo è presente.
Devo tornare sull’impianto tra qualche giorno per riprovare e, nel frattempo, ho pensato di chiedere aiuto qui per capire dove potrei aver sbagliato.
Ora sto cercando di riscrivere la logica di comunicazione inserendo una pausa tra una richiesta e l’altra, sperando che questo risolva il problema. 


Posted

Attenzione al tempo di attesa tra un comando e un altro, quindi anche tra uno slave e l'altro. Normalmente, dipende dalla velocità di trasmissione, bisogna attendere un carattere e mezzo prima di mandare il comando successivo. Questo per garantire che la linea sia elettricamente libera e stabile dopo l'ultima risposta.

Non conosco l'ABB, ma spesso questo parametro è impostabile, in ms, direttamente nei parametri della porta di comunicazione modbus.

NoNickName
Posted

Naturalmente i softstarter devono avere indirizzi diversi l'uno dall'altro. Scusa per l'ovvietà, ma meglio accertarsene.

 

Posted
Il 02/07/2025 alle 17:40 , Ctec ha scritto:

Attenzione al tempo di attesa tra un comando e un altro, quindi anche tra uno slave e l'altro. Normalmente, dipende dalla velocità di trasmissione, bisogna attendere un carattere e mezzo prima di mandare il comando successivo. Questo per garantire che la linea sia elettricamente libera e stabile dopo l'ultima risposta.

Non conosco l'ABB, ma spesso questo parametro è impostabile, in ms, direttamente nei parametri della porta di comunicazione modbus.

Grazie mille per la risposta. Non ho molta esperienza e non sapevo bene come impostare correttamente una comunicazione tramite Modbus RTU. Facendo alcune prove con un SoftStarter ABB della serie PSTX, anche cambiando varie impostazioni, ottenevo sempre lo stesso errore: ‘P1 E00’ – Errore di comunicazione Fieldbus.

Alla fine, l’errore spariva solo impostando il parametro "Fieldbus Failure Operation" su OFF, ma in quel caso la comunicazione non funzionava correttamente. Infatti, il blocco di funzione ModRTUMast richiede un fronte di salita sull'ingresso Execute per iniziare la comunicazione, e dopo che l’uscita Done o Error si attiva, è necessario resettare Execute a FALSE per preparare la richiesta successiva.

Durante i test in impianto, avevo dimenticato dell’importanza del parametro "Fieldbus Failure Operation", ma ho scoperto che i SoftStarter ABB PSTX hanno un timeout di comunicazione predefinito di 600 ms. L’errore ‘P1 E00’ compare quando il dispositivo non riceve nessuna richiesta Modbus (né lettura né scrittura) entro questo intervallo.

Disattivando "Fieldbus Failure Operation", l’errore non compariva, e tutti e 7 i SoftStarter sulla linea Modbus comunicavano normalmente.

Successivamente, ho capito che era necessario modificare l’approccio alla comunicazione e ho sviluppato una piccola macchina a stati. Questa sequenza funziona così:

  1. Effettuo una richiesta di lettura di 12 registri (16 bit) per il primo SoftStarter.

  2. Dopo aver ricevuto Done o Error, attendo 2 ms.

  3. Invio una richiesta di scrittura di 32 coil per lo stesso dispositivo.

  4. Dopo Done o Error, attendo di nuovo, incremento l’indice, e passo al secondo SoftStarter.

  5. Ripeto la stessa logica per tutti e 7 i dispositivi, poi riporto l’indice a 1 e ricomincio il ciclo.

Con un tempo di attesa tra le richieste fino a 4–5 ms, tutto funziona anche con il parametro "Fieldbus Failure Operation" attivato. Tuttavia, se imposto un’attesa superiore a 10 ms, ricompare l’errore ‘P1 E00’.

Vorrei sapere:

  • Come si struttura normalmente una comunicazione Modbus RTU in ambiente PLC?

  • E, secondo Lei, la soluzione che ho adottato è corretta o ci sono miglioramenti che potrei fare?

Le ringrazio molto per l’aiuto!

Marco Fornaciari
Posted

Premetto che anch'io non conosco le apparecchiature che stai utilizzando.

Il cadenzamento che hai fatto è quello corretto (di fatto il solo che funziona in ogni comunicazione seriale), eventualmente cambianao i tempi di ritardo e clock.

Se ho inteso bene l'errore è nel softstarter, mi pare strano che richieda una comunicazione continua entro 600 mS, con solo due apparecchi in rete ci può anche stare, ma oltre no.

Pertanto quel parametro deve essere modificabile, a meno che non si riferisca ad altro, es. una stinga ben precisa che deve ricevere, oppure che devi impostare una maggiore volocitè di comunicazione.

 

Ma scusa.

Dando un guardata in rete prendo atto che quel PLC e quei softstarter gestiscono la Profinet: quindi la domanda è, perché nel 2025 complicarsi la vita non usandola?

 

 

 

 

 

Posted
10 ore fa, Marco Fornaciari ha scritto:

Premetto che anch'io non conosco le apparecchiature che stai utilizzando.

Il cadenzamento che hai fatto è quello corretto (di fatto il solo che funziona in ogni comunicazione seriale), eventualmente cambianao i tempi di ritardo e clock.

Se ho inteso bene l'errore è nel softstarter, mi pare strano che richieda una comunicazione continua entro 600 mS, con solo due apparecchi in rete ci può anche stare, ma oltre no.

Pertanto quel parametro deve essere modificabile, a meno che non si riferisca ad altro, es. una stinga ben precisa che deve ricevere, oppure che devi impostare una maggiore volocitè di comunicazione.

 

Ma scusa.

Dando un guardata in rete prendo atto che quel PLC e quei softstarter gestiscono la Profinet: quindi la domanda è, perché nel 2025 complicarsi la vita non usandola?

 

 

 

 

 

Grazie mille per la risposta.

Il progetto inizialmente era stato concepito per un funzionamento diverso: non era prevista la presenza di un PLC. Le pompe dovevano essere avviate in modalità manuale tramite un semplice galleggiante, che chiudeva un contatto.

Successivamente, poiché il SoftStarter dispone dell’interfaccia RS485, si è deciso di utilizzare la comunicazione tramite protocollo Modbus RTU. È proprio in questa fase che ho iniziato a riscontrare dei problemi.

Dopo una lunga ricerca, ho capito che per una semplice lettura dei registri si poteva evitare il problema della comunicazione senza attivare la funzione Fieldbus Control. Tuttavia, senza questa funzione attivata, non è possibile scrivere nei registri Coil (per inviare comandi).

Per evitare modifiche complesse al cablaggio, si è deciso di utilizzare un'uscita digitale (DO) del PLC per chiudere il contatto che originariamente veniva attivato dal galleggiante. Tuttavia, è rimasta la necessità di scrivere nei registri, ad esempio per poter gestire il reset degli eventi direttamente dall’HMI, senza dover intervenire manualmente sull’interfaccia del SoftStarter.

A tal proposito, ho trovato un parametro utile nella lista delle protezioni: “Fieldbus Failure Operation”, che ha permesso di gestire meglio queste condizioni.

Inoltre, per comunicare con l’HMI (sempre ABB) sono costretto a utilizzare il protocollo Modbus TCP. Questo richiede che ogni variabile abbia un indirizzo preciso nella memoria del PLC. Per me non è semplice, perché devo calcolare attentamente questi indirizzi per evitare sovrascritture di altre variabili, e tutto ciò diventa complesso da gestire.

Mi trovo da solo in azienda, senza un vero supporto tecnico, e non sono un programmatore esperto. I corsi base forniscono una panoramica molto distante dalla realtà pratica, e mi rendo conto ogni giorno di quanto ci sia ancora da imparare.

Per questo motivo, mi rivolgo a voi programmatori con più esperienza per ricevere qualche consiglio pratico. Grazie ancora per il supporto!

Marco Fornaciari
Posted

Il protocollo Modbus è di fatto semplice e pure gratis (che poi cambia poco dal CAN che la base ti tutti gli altri, ma non gratis), ma per gestirlo bene e con facilità bisogna progettare prima tutta la gestione delle variabili.

In questi casi di aggiunta dopo normalmente non perdo tempo e rimappo tutte le variabili riscrivendo il SW, sfruttando il cambio in automatico magari in due passaggi, so da dove e parto e dove arrivo, e risolvo in tempi certi e brevi: spesso bisogna osare e rifare un SW, in fin dei conti è tutto lavoro a tavolino e l'originale è sempre lì pronto all'uso.

Sono decenni che progetto tutte le variabili prima, anche dello schema, con excel.

I corsi ti insegnano le cose principali e descrivono le funzioni più usate, ma non possono insegnare tutti contesti: ci vuole fantasia e poi osare.

 

 

Posted

image.thumb.png.3e5f51dd9fefe79f5e604ce3c2ed3566.png

 

Volevo chiedervi un’altra cosa: nello screenshot ci sono i parametri di default dell’interfaccia RS485.

Se ho capito bene, quando si imposta nessuna parità, è necessario impostare 2 bit di stop per ottenere il famoso "carattere e mezzo" tra le richieste Modbus RTU.

Se è così, allora le impostazioni di default (se ad esempio sono parità: None e 1 stop bit) possono causare errori di comunicazione Modbus RTU, giusto?

Posted

No, per esempio io imposto sempre 8N1, 8bit, nessuna parità, 1 stop. La pausa deve proprio essere un carattere e mezzo. Considera però che un carattere (byte) in trasmissione equivale a 10bit (con 8N1, oppure 11 con 8N2), per cui devi attendere 15bit (o 16), che vanno poi rapportati al baud rate.

Se per esempio lavori a 19200, un bit dura 1/19200"=>52us circa, per cui l'attesa deve essere almeno 15*52=781us=0,781ms.

Le impostazioni devono essere identiche per tutti i partecipanti (baud e composizione), altrimenti avrai errori di comunicazione e/o dati sballati

Posted
2 ore fa, Ctec ha scritto:

No, per esempio io imposto sempre 8N1, 8bit, nessuna parità, 1 stop. La pausa deve proprio essere un carattere e mezzo. Considera però che un carattere (byte) in trasmissione equivale a 10bit (con 8N1, oppure 11 con 8N2), per cui devi attendere 15bit (o 16), che vanno poi rapportati al baud rate.

Se per esempio lavori a 19200, un bit dura 1/19200"=>52us circa, per cui l'attesa deve essere almeno 15*52=781us=0,781ms.

Le impostazioni devono essere identiche per tutti i partecipanti (baud e composizione), altrimenti avrai errori di comunicazione e/o dati sballati

PROGRAM ModBusRTU_ST
VAR
    i    :    INT:= 1;
    fb_ModBusRead        :     ModRtuMast;
    fb_ModBusWrite        :     ModRtuMast;
        
    Stato             :     INT :=0;
    Fase            :    BOOL; //False - lettura, TRUE - scrittura
    TimerAttesa        :    TON;
    TempoAttesa: TIME :=T#2MS;
    
    DoneR, BusyR, ErrorR : BOOL;
    DoneW, BusyW, ErrorW : BOOL;
    R_trigR: R_TRIG;
    R_trigW: R_TRIG;
    ExecuteRead, ExecuteWrite : BOOL;
    ContaRead: INT;
    
    ContaWrite: INT;
    ContaDoneRead: INT;
    ContaError: INT;

END_VAR

R_trigR(CLK:=((Stato=0) AND NOT Fase) , Q=> );
R_trigW(CLK:= ((Stato=0) AND  Fase), Q=> );

ExecuteRead := R_trigR.Q;
ExecuteWrite := R_trigW.Q;

TimerAttesa(IN:= , PT:=TempoAttesa, Q=> , ET=> );
CASE Stato OF
    //Avvio comando lettura o scrittura 
    0:    
        IF NOT Fase THEN 
            // BLOCCO LETTURA
    fb_ModBusRead(
        Execute:= ExecuteRead , 
        Done=> DoneR, 
        Busy=> BusyR, 
        Error=> ErrorR, 
        Endian:= , 
        Serv:= Pump[i].ModBusRTU.PumpAddress, 
        Fct:= Pump[i].ModBusRTU.FunRead,     //4
        Timeout:= Pump[i].ModBusRTU.Timeout, //T#100ms
        Addr:= 511, 
        Nb:= 12, 
        Data:= ADR(PumpModbusData[i].AnalogInputs), 
        ErrorID=> , 
        Com:= Pump[i].ModBusRTU.ComPort );
        Pump[i].Status.DoneRead := DoneR;
        Pump[i].Status.ErrorRead := ErrorR;
        IF     DoneR OR ErrorR THEN
            ExecuteRead := FALSE;
            Stato := 10;
        END_IF
        
    ELSE 
        // BLOCCO SCRITTURA
    fb_ModBusWrite(
        Execute:= ExecuteWrite , 
        Done=> DoneW, 
        Busy=> BusyW, 
        Error=> ErrorW, 
        Endian:= , 
        Serv:=  Pump[i].ModBusRTU.PumpAddress, 
        Fct:=Pump[i].ModBusRTU.FunWrite , //15
        Timeout:= Pump[i].ModBusRTU.Timeout, //T#100ms
        Addr:= 256, 
        Nb:= 32, 
        Data:= ADR(PumpModbusData[i].CoilOutputs), 
        ErrorID=> , 
        Com:= Pump[i].ModBusRTU.ComPort );
        Pump[i].Status.DoneWrite:= DoneW;
        Pump[i].Status.ErrorWrite:= ErrorW;
        IF DoneW OR ErrorW THEN
            ExecuteWrite := FALSE;
            Stato := 20;
        END_IF    
    END_IF
    //pausa dopo la Lettura
    10: 
    TimerAttesa.IN := TRUE;
    IF TimerAttesa.Q THEN
        TimerAttesa.IN := FALSE;
        Fase := TRUE;
        Stato := 0;
    END_IF
    
        //pausa dopo scrittura 
    20:    
        TimerAttesa.IN := TRUE;
    IF TimerAttesa.Q THEN
       TimerAttesa.IN := FALSE;
       Fase :=FALSE;
       i:= i +1;
       Stato := 0;
        IF i>7 THEN
            i :=1;
            Stato:= 0;
        END_IF
    END_IF
    
END_CASE


IF  Pump[2].Status.DoneRead THEN
    ContaDoneRead := ContaDoneRead +1 ;
END_IF
IF Pump[2].Status.ErrorRead THEN
    ContaError := ContaError +1 ;
END_IF

In teoria, considerando una richiesta di lettura di 12 registri a 16 bit (che occupa 8 byte), e una risposta del dispositivo composta da: 

- 1 byte per l'indirizzo;

- 1 byte per il codice funzione;

- 1 byte per il numero di byte da leggere;

- 12 registri × 2 byte = 24 byte;

-2 byte per il CRC

otteniamo una risposta di 28 byte. Sommando i 28 byte della risposta agli 8 byte della richiesta, il totale è di 36 byte, ovvero 288 bit.

288 bit / 19200 bit/s = 0,015 s = 15 ms

allora 1.5 parametro corrisponde 22.5 ms?

Vorrei profondire questo argumetro, scusate mi tanto per la mia ignoranza

 

 

Posted
7 minuti fa, Mykola ha scritto:

allora 1.5 parametro corrisponde 22.5 ms?

No, un byte e mezzo, più start/stop/parità. La pausa va messa alla fine della ricezione del messaggio di risposta e prima di inviare il prossimo.

Quindi: messaggio-attesa risposta-risposta-pausa 1.5ch e via andare. Considera che lo slave, ricevuto il messaggio, automaticamente mette lui almeno un'attesa di 1.5ch prima di inviare la risposta.

Che PLC usi per tutto ciò? Per esempio, qui è come si imposta la porta seriale di un LS:

image.png.7096d97603080aa2edceb0434515d365.png

Qui vedi (CH2) ho impostato il modbus a 57600, 8N1, attesa di risposta dello slave 100ms (che è un bel po' di tempo...) delay time prima di trasmissione a 0 (in pratica tra la fine di un messaggio e il successivo io passo una scansione, pari a circa 2ms massimo) e nessun ritardo tra i caratteri (è per apparecchiature molto vecchie).

Non è campato in aria, è una macchina perfettamente funzionante con 3 inverter e 1 servo controllati in seriale.

Posted
39 minuti fa, Ctec ha scritto:

No, un byte e mezzo, più start/stop/parità. La pausa va messa alla fine della ricezione del messaggio di risposta e prima di inviare il prossimo.

Quindi: messaggio-attesa risposta-risposta-pausa 1.5ch e via andare. Considera che lo slave, ricevuto il messaggio, automaticamente mette lui almeno un'attesa di 1.5ch prima di inviare la risposta.

Che PLC usi per tutto ciò? Per esempio, qui è come si imposta la porta seriale di un LS:

image.png.7096d97603080aa2edceb0434515d365.png

Qui vedi (CH2) ho impostato il modbus a 57600, 8N1, attesa di risposta dello slave 100ms (che è un bel po' di tempo...) delay time prima di trasmissione a 0 (in pratica tra la fine di un messaggio e il successivo io passo una scansione, pari a circa 2ms massimo) e nessun ritardo tra i caratteri (è per apparecchiature molto vecchie).

Non è campato in aria, è una macchina perfettamente funzionante con 3 inverter e 1 servo controllati in seriale.

Grazie mille. Io uso un PLC ABB PM5052-T-ETH. Ho impostato PT:=T#2MS in Timer per fare la pausa tra la lettura e scrittura. La comunicazione sembra funzionare, ma volevo sapere se questo è il modo corretto di procedere.

Posted

Come detto, metti eventuale pausa dopo la risposta prima del nuovo messaggio. Altrimenti rallenti inutilmente il tutto

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...