Operational Amplifier Inserito: 6 novembre 2016 Segnala Share Inserito: 6 novembre 2016 Attualmente mi connetto al Plc tramite la classe Sharp7 in C# quando vengono inizializzati gli oggetti grafici della FormMain, se stacco il cavo di rete simulando un guasto il Pc si sconnette e giustamente non riesco a leggere/scrivere le variabili, come posso monitorare la comunicazione e di conseguenza effettuare dei tentativi anche ogni 5 secondi per riagganciarla? public partial class FormMain : Form { private S7Client Client; public FormMain() { InitializeComponent(); this.WindowState = FormWindowState.Maximized; ToolStripLblNomePagina.Text = "Main"; Client = new S7Client(); int Result; int Rack = 0; int Slot = 1; Result = Client.ConnectTo("192.168.216.2", Rack, Slot); if (Result == 0) TextError.Text = "Online (" + Client.ExecutionTime.ToString() + " ms)" + " PDU : " + Client.PduSizeNegotiated.ToString(); else TextError.Text = Client.ErrorText(Result); } Il mio obbiettivo sarebbe quello di riprodurre una connessione tipo quella di Wincc, mi spiego meglio, se sono collegato al Plc con il Pc (Wincc Advanced) le variabili vengono visualizzate tramite i campi I/O della pagina, quando sconnetto il cavo si presentano dei cancelletti, una volta ripristinato la comunicazione il tutto si riaggancia. Consigli bene accetti...... Link al commento Condividi su altri siti More sharing options...
dan64100 Inserita: 7 novembre 2016 Segnala Share Inserita: 7 novembre 2016 Ogni client (non solo Sharp7) non è continuamente cosciente della connessione, se il server (in questo caso il PLC) si spegne, si stacca il cavo ecc.. Si può attivare il keep alive ma non è un metodo realtime e se si riduce il tempo di verifica si aggiunge overhead nelle comunicazioni. Il metodo migliore è verificare il canale durante il suo funzionamento, almeno io faccio così. Ho messo su un demo perchè molta altra gente mi ha fatto la stessa domanda, posto il codice, hai bisogno di qualche bottone, Textox ecc. ma il funzionamento credo che sia chiaro. Il loop principale, per motivi di semplicità è rappresentato da un timer, in un programma reale sarebbe molto meglio usare un thread e separare la parte comunicazione da quella visuale. Se hai problemi mandami un m.p. che ti invio tutto il progetto, era destinato alla prossima release. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using Sharp7; namespace LoopClient { public partial class Form1 : Form { private S7Client Client; private byte[] Buffer = new byte[65536]; private String IP; private int Rack; private int Slot; enum ClientStatus {cStopped, cRunning, cChannelError, cDataError}; ClientStatus Status; public Form1() { InitializeComponent(); Client = new S7Client(); EditMode(); Status = ClientStatus.cStopped; } private void RunMode() { StopBtn.Enabled = true; StartBtn.Enabled = false; TxtIP.Enabled = false; TxtRack.Enabled = false; TxtSlot.Enabled = false; TxtDB.Enabled = false; TxtSize.Enabled = false; ScanTim.Enabled = true; } private void EditMode() { ScanTim.Enabled = false; StopBtn.Enabled = false; StartBtn.Enabled = true; TxtIP.Enabled = true; TxtRack.Enabled = true; TxtSlot.Enabled = true; TxtDB.Enabled = true; TxtSize.Enabled = true; Status = ClientStatus.cStopped; } private void Start() { Rack = System.Convert.ToInt32(TxtRack.Text); Slot = System.Convert.ToInt32(TxtSlot.Text); IP = TxtIP.Text; Connect(); } private void ShowResult(int Result) { // This function returns a textual explaination of the error code TextError.Text = Client.ErrorText(Result); if (Result == 0) TextError.Text = TextError.Text + " (" + Client.ExecutionTime.ToString() + " ms)"; switch (Status) { case ClientStatus.cChannelError: { StatusPnl.BackColor = System.Drawing.Color.Red; break; } case ClientStatus.cDataError: { StatusPnl.BackColor = System.Drawing.Color.Orange; break; } case ClientStatus.cStopped: { StatusPnl.BackColor = System.Drawing.Color.Gray; break; } case ClientStatus.cRunning: { StatusPnl.BackColor = System.Drawing.Color.LimeGreen; break; } } } private bool Connect() { int Result = Client.ConnectTo(IP, Rack, Slot); if (Result == 0) Status = ClientStatus.cRunning; else Status = ClientStatus.cChannelError; ShowResult(Result); return Result == 0; } private bool CheckConnection() { if (Status == ClientStatus.cChannelError) { Client.Disconnect(); return Connect(); } else return true; } private void Execute() { int Result = Client.DBRead(Convert.ToInt32(TxtDB.Text), 0, Convert.ToInt32(TxtSize.Text), Buffer); ShowResult(Result); if (Result!=0) { if ((Result & 0x000FFFFF) != 0) Status = ClientStatus.cChannelError; else Status = ClientStatus.cDataError; } else Status=ClientStatus.cRunning; } private void ScanTim_Tick(object sender, EventArgs e) { if (CheckConnection()) Execute(); } private void StopBtn_Click(object sender, EventArgs e) { Status = ClientStatus.cStopped; ShowResult(Client.Disconnect()); EditMode(); } private void StartBtn_Click(object sender, EventArgs e) { Start(); RunMode(); } } } Link al commento Condividi su altri siti More sharing options...
dan64100 Inserita: 7 novembre 2016 Segnala Share Inserita: 7 novembre 2016 Aggiungo qualche nota: Io in genere divido gli errori logici (mancanza DB, indirizzi oltre il limite ...) da quelli di canale generati dalla comunicazione TCP/IP. Nel secondo caso disconnetto e riconnetto il client, la disconnessione puoi chiamarla tranquillamente anche se il client non è connesso. WinCC disconnette/riconnette il canale anche in presenza di errori logici. Credo che dipenda da un vecchio retaggio di firmware, a volte nelle CPU vecchie era consigliabile reinizializzare la comunicazione. Decidi tu cosa vuoi fare, è solo un particolare. Link al commento Condividi su altri siti More sharing options...
Operational Amplifier Inserita: 7 novembre 2016 Autore Segnala Share Inserita: 7 novembre 2016 Ciao Davide, Prima di tutto Grazie, provo a mandarti un m.p. in modo da avere un tuo progetto guida.... Link al commento Condividi su altri siti More sharing options...
Operational Amplifier Inserita: 18 novembre 2016 Autore Segnala Share Inserita: 18 novembre 2016 Sempre in riferimento a questo test. Ho inserito un Textbox semplicissimo e vorrei utilizzarlo come Campo I/O , che svolga la funzione di lettura e scrittura di una variabile per esempio come in Wincc Advanced, insomma per farla breve con un textbox leggere e nel frattempo scrivere una variabile. Avevo pensato di continuare a passare la variabile letta al controllo "MyTextbox.Text" (attualmente con timer ogni 100ms, più avanti vedrò di mettere un thread dedicato), una volta che è abilitato rilevato con l'evento "Enter" smetto di leggere, una volta confermato rilevato con l'Evento "Validated" scrivo il valore poi ricomincio a leggere. Secondo la vostra esperienza potrebbe andare....? Link al commento Condividi su altri siti More sharing options...
dan64100 Inserita: 20 novembre 2016 Segnala Share Inserita: 20 novembre 2016 Provalo Se non funziona lo analizziamo. Link al commento Condividi su altri siti More sharing options...
Operational Amplifier Inserita: 20 novembre 2016 Autore Segnala Share Inserita: 20 novembre 2016 Ciao Davide, Ti confermo che il tuo codice funziona, ho messo come si intuiva qualche textbox, button ed il timer ed voilà. Nell'ultimo post forse non sono stato chiaro, vediamo di chiarire, attualmente utilizzo due textbox una per leggere ed una per scrivere la stessa variabile e fino a quì tutto ok utilizzo i metodi S7.GetIntAt() e S7.SetIntAt() perchè è un Int. Stavo effettuando delle prove per averne solamente una di textbox che quindi abbia la funzione di lettura e scrittura come in Wincc il Campo I/O questo non centra con la tua parte di codice sarebbe una raffinatezza che mi piacerebbe fare. TextBox Lettura/Scrittura: Pensavo quindi di richiamare il metodo S7.GetIntAt() con tempo del timer, una volta che l'utente mi attiva il textbox (rilevato con l'evento "Enter") non richiamo più quel metodo, in modo di dare all'utente la possibilità di scrittura del valore desiderato, una volta confermato (rilevato con l'Evento "Validated") scrivo il valore con il metodo S7.SetIntAt() poi richiamo ancora il metodo il metodo S7.GetIntAt(). Dovrebbe essere più chiaro adesso..... Link al commento Condividi su altri siti More sharing options...
dan64100 Inserita: 20 novembre 2016 Segnala Share Inserita: 20 novembre 2016 Era chiaro anche prima Ci metti più tempo a scrivere quello che vuoi fare che a provarlo direttamente, ecco perché dicevo provalo e vediamo. Attento però, le funzioni S7.Get/Set non leggono/scrivono i dati dal PLC ma li estraggono formattati da un buffer che devi comunque leggere o scrivere con una delle funzioni disponibili Read/Write area o DBRead/Write ecc.. Link al commento Condividi su altri siti More sharing options...
Operational Amplifier Inserita: 21 novembre 2016 Autore Segnala Share Inserita: 21 novembre 2016 Hai ragione Davide...in questi giorni sono fuori, appena rientro preparo qualcosa poi ci aggiorniamo..... Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora