Vai al contenuto

Comunicazione con protocollo Modbus master

Home Forum Controllori SlimLine e Netsyst (LogicLab) Comunicazione con protocollo Modbus master

  • Il topic è vuoto.
Stai visualizzando 12 post - dal 1 a 12 (di 12 totali)
  • Autore
    Post
  • #35775
    Paolo
    Partecipante

    Buonasera, ho una CPU MPS046B100, che utilizzo con ModBus 485 RTU come master; collegati ho 5 moduli che mettono a disposizione diversi registri da leggere e coils da usare. La prima domanda è: in quale task è più conveniente mettere il programma di comunicazione ?

    La seconda: conviene usare una strategia di molteplici FB ModBusMaster in cascata (come gestire gli errori di un modulo ?), come visto da vari esempi, o usarne una coppia (1 per leggere 1 per scrivere ), e gestirla via codice ST ?

    Grazie anticipatamente per i suggerimenti…

    #38888
    Sergio Bertana
    Amministratore del forum

    Tutte i FB che gestiscono stream di comunicazione (Seriale, UDP, TCP/IP) o accedono al file system devono essere eseguiti nella task di Back.

    Se le interrogazioni Modbus non sono molte puoi istanziare tante istanze della FB ModbusMaster quante sono le interrogazioni (Lettura/Scrittura) da eseguire (Questo topic spiega come mettere in cascata le varie istanze, ecco uno screenshot). In questo modo si ha uno “spreco” nell’utilizzo delle risorse in quanto ogni istanza del FB occupa memoria RAM anche se vi è una esecuzione sequenziale delle varie istanze.

    Molto più ottimizzato è l’utilizzo di una singola istanza del FB a cui vengono ciclicamente passati i parametri di configurazione, nodo del dispostivo con cui comunicare, codice funzione e range indirizzi del comando da eseguire. Il modo migliore per realizzarlo è gestire da ST una macchina a stati con l’operando CASE. Nel forum ci sono posts che trattano l’argomento ma a titolo di esempi ti allego un programma che utilizza questa tecnica (Download sorgente).

    Come vedi dalla stampa del programma, si tratta di un programma che comunica con drivers brushless, tutti i comandi mosdbus operano su registri a 32 bits (2 registri modbus) ed è eseguito anche lo swap tra MSB e LSB. Altra particolarità è la gestione di un socket TCP per permettere il dialogo con il driver “passando” tramite lo SlimLine. Aprendo una connessione con la porta 2000 è possibile da TCP/IP comicare su RS485 con i drivers (In questo topic si tratta l’argomento).

    Troverai il programma un pò più complesso (Per ogni interrogazione modbus viene utilizzata una struttura dati) perchè per velocizzare la comunicazione per i comandi di scrittura verso il driver viene mantenuta una copia del valore scritto ed il comando Modbus viene eseguito solo se il programma utente cambia i valori da scrivere.

    #38889
    Paolo
    Partecipante

    Ciao, grazie molte per i consigli sempre utilissimi; nel programma ST non ho trovato riferimenti alla gestione dell’errore ModBus; non vengono gestite retry/correzioni di qualche tipo ? Si preferisce saltare al prossimo ciclo di comunicazione ?

    Preciso che la lettura nel mio caso riguarda sensori di temperatura, quindi nulla di veloce, la scrittura di coils di comando anche queste nulla di veloce, però rimango nel dubbio se gestire gli errori su ogni singola comunicazione o ignorarli e saltare al prossimo loop con tempi tra i 2-5 sec.

    #38890
    Sergio Bertana
    Amministratore del forum

    Di solito lascio la gestione al loop successivo. Trovo il tempo da te indicato molto lungo, hai molte interrogazioni modbus o hai un baud rate molto basso per avere tempi fino a 5 Sec.

    Però mi hai meso una pulcina nell’orecchio… potrei pensare di modificare (Tempo permettendo) il FB ModbusMaster aggiungendo la gestione di retries sul comando.

    #38891
    Paolo
    Partecipante

    Ciao, in effetti i tempi li devo ancora stabilire con cura; in ogni caso la lettura riguarda dei sensori di temperatura ambiente, quindi la velocità di refresh non è fondamentale; per le coils sono attivazioni anche qui con tempi non necessariamente stretti; avevo pensato a qualche secondo per non caricare inutilmente il bus e la CPU di lavoro inutile, comunque tutto da vedere.

    In effetti se la FB ModBusMaster si occupasse di eseguire qualche retry prima di dare il fault sarebbe una bella cosa !!! Anche perchè vivendo di vita propria scaricherebbe (noi poveracci) dal compito di controllare la comunicazione a livello bus….

    Dai che lo trovi il tempo !!! 😉

    #39630
    Alessandro
    Partecipante

    Avrei bisogno di fare alcune domande riguardo al blocco funzione MasterModbus presente nell’esempio. Ho fatto alcuni test e andando avanti nelle modifiche del programma sono giunto alla conclusione che le uscite di ModbusMaster DoneOk non sono comandate in maniera sincrona. Nel programma che sto creando uso la funzione di scrittura Modbus soltanto:

    1- Alla prima scansione.
    2- Se NOT(SysTCPClient.Connected) OR ModbusMaster.Fault, quindi connessione persa oppure errore sulla connessione Modbus.
    3- Se noto un cambio nel valore Errors.
    4- Se ho una variazione del messaggio da scrivere in Modbus.

    Per capire se effettivamente ho concluso a buon fine la scrittura modbus, e quindi passare a leggere di continuo lettura, volevo utilizzare il segnale di Done combinato con il segnale di Ok.

    Solo che, inizialmente, il segnale di Ok veniva rilevato dopo qualche millisecondo che Done era stato settato. Dopo aver scritto altro programma adesso ho la condizione che prima arriva l’Ok poi il Done. E’ possibile in qualche maniera far arrivare il Donee l’Ok nelle stessa scansione del PLC, in modo che con la combinazione di entrambi possa capire se effettivamente ho concluso le operazioni Modbus correttamente oppure no.

    #39631
    Sergio Bertana
    Amministratore del forum

    Ottima soluzione la tua effettuare la scrittura solo quando serve per avere più velocità in lettura e quello che tu chiedi è già tutto previsto.

    L’uscita di Ok si attiva per un loop solo se il comando è andato a buon fine (Inviato frame di comando allo slave e ricevuto risposta), quindi con l’Ok puoi proseguire. L’uscita di Done si attiva e resta attiva al termine della intera gestione del comando (Tiene conto anche dell’eventuale tempo di Delay).

    Se le vuoi contemporanee, definisci una tua variabile BOOL che resetti sull’attivazione di Enable e setti sull’Ok, così la puoi controllare con il Done.

    Per il controllo dell’errore puoi usare l’uscita Fault che si attiva per un loop in caso di errore comunicazione.

    #45618
    Davide
    Partecipante

    In riferimento al programma esempio non riesco a capire due cose:

    1- A cosa serve l’indice FMIDx?

    2- Per quale motivo l’assegnamento della variabile MdbValue in caso di scrittura (FCode=16#10) viene effettuato solo dopo aver lanciato il comando Modbus (Done=true) e non prima?

    #45621
    Sergio Bertana
    Amministratore del forum

    In effetti l’algoritmo utilizzato nello sviluppo di questo driver di comunicazione ha alcune particolarità che lo complicano. Intanto posto l’intero progetto LogicLab con tutti i FB utilizzati pronto per essere utilizzato come dimostrativo (Download programma).

    La variabile FMIDx (* Force Modbus index *), è utilizzata per forzare il comando di scrittura Modbus, siccome per velocizzare lo scambio dati i comandi di scrittura sono eseguiti solo sulla variazione del valore da scrivere ho previsto di comunque scrivere il valore ciclicamente così se per caso ci fosse una disincronizzazione tra quello che lo SlimLine pensa di avere scritto e quello scritto nel sistema ci si risincronizza.

    Il programma è eseguito ciclicamente dall’alto verso il basso, quando ho il Done a TRUE significa che il comando Modbus è terminato e posso inviare un’altro comando. Quindi dovendo inviare un comando di scrittura devo caricare il valore da scrivere poi dare il comando Enable:=TRUE.

    Se noti il FB ModbusMaster MMdb(); (* Modbus master communication *)  è eseguito dopo avere posto Enable:=FALSE, quindi entrando in FB con Enable disabilitato inizializzo gestione e resetto Done pronto per il prossimo giro di esecuzione ad essere attivato.

    #45623
    Davide
    Partecipante

    Grazie per la risposta, ma quando intendi “Il programma è eseguito ciclicamente dall’alto verso il basso” significa che l’assegnamento di variabili viene valutato sempre alla fine del programma come avviene con le uscite fisiche?  Se ciò fosse vero, significa che ad esempio nella seguente istruzione:

    MIDx:=MIDx+1; (* Modbus index *)
    IF (MIDx >= (SIZEOF(MdbCfg)/SIZEOF(MdbCfg[0]))) THEN ….

    Il valore MIDx valutato dall’istruzione IF non è quello incrementato di 1, ma quello attuale letto all’inizio del programma…

    Inoltre se non ho interpretato male il programma, il primo comando di scrittura che il programma esegue lo lancia scrivendo un valore di MdbValue non ancora inizializzato perché all’avvio il segnale Done è ancora FALSE quindi non riesco ad assegnare il valore corretto contenuto nel buffer… o sbaglio?

    Perdona la banalità delle mie domande  🙁

    #45658
    Sergio Bertana
    Amministratore del forum

    Le domande non sono mai banali, sono un modo per capire meglio il sistema.

    Con “Eseguito ciclicamente dall’alto verso il basso” si intende l’esecuzione del programma è eseguita dall’alto verso il basso ma  ogni riga di programma viene valutata ed eseguita, quindi nelle righe che tu citi MIDx viene prima incrementato e poi sulla riga successiva viene  controllato (Quindi ha già il nuovo valore).

    Per quanto riguarda gli I/O logici invece, si parla di immagine di processo gli ingressi sono acquisiti ciclicamente prima di iniziare l’esecuzione del programma e le uscite sono gestite al termine della esecuzione del programma. Questo per avere lo stato degli ingressi che non cambia per tutto il  loop di esecuzione programma, se fossero letti nel momento in cui li controllo potrei avere in un punto l’ingresso disattivo ed in un altro l’ingresso attivo.

    Complimenti hai scoperto l’errore… in effetti se il primo comando da eseguire (Definito nella struttura MdbCfg) è un comando di scrittura, quindi alla prima esecuzione del programma, verrebbe scritto un valore non corretto, poi ai loop successivi tutto torna a funzionare. Per evitare il problema basterebbe definire come primo comando nella struttura un comando di read.

    A mia scusa (Non faccio mai errori), l’esempio l’ho ricavato da un taglia/cuci di un programma fatto per un cliente ed ho cucito male…

    #62158
    AndreaT.
    Partecipante

    Buonasera se possibile vorrei un aiuto sto cercando di far comunicare un Logo 8 come slave e uno SlimLine come master con protocollo Modbus TCP/IP ma non riesco, questi sono gli errori dalla console di spionaggio.

    [Admin]> SpyData
    Spy data active, type "Ctrl-C" to exit...
    22:46:39.289174| ModbusMaster:Tx|00 01 00 00 00 06 01 03 9E 40 00 08
    22:46:39.290056| ModbusMaster:Er|Error:10007200, On Case:201, Back:51
    22:46:49.291247| ModbusMaster:Tx|00 02 00 00 00 06 01 03 9E 40 00 08
    22:46:49.292276| ModbusMaster:Er|Error:10007200, On Case:201, Back:51
    22:46:59.293710| ModbusMaster:Tx|00 03 00 00 00 06 01 03 9E 40 00 08
    22:46:59.294570| ModbusMaster:Er|Error:10007200, On Case:201, Back:51
Stai visualizzando 12 post - dal 1 a 12 (di 12 totali)
  • Devi essere connesso per rispondere a questo topic.