Vai al contenuto
PLC Forum


Comunicazione Sharp7


Operational Amplifier

Messaggi consigliati

Operational Amplifier

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


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

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

  • 2 weeks later...
Operational Amplifier

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

Operational Amplifier

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

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

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