Vai al contenuto
PLC Forum


Libreria Snap7


Messaggi consigliati

Ciao a tutti!

Premetto di essere nuovo del forum e del mondo Siemens, quindi perdonate l'ignoranza :smile:

In passato ho sviluppato uno SCADA interfacciato a PLC Siemens con OPC Server. Funziona, ma non mi ha esaltato particolarmente, in particolare l'esigenza di definire tutte le variabili ( indirizzi di memoria ) in lettura e scrittura all'avvio del programma, senza che ci fosse un sistema "comodo" per aggiungere variabili run-time.

comunque, ora devo sviluppare un'altro SCADA per Siemens che deve essere installato su 5 PC e, per risparmiare sulle licenze, sto valutando alternative: Snap7

Ho fatto alcune prove e mi sembra un ottimo prodotto, i miei complimenti all'autore :smile:

Però evidentemente c'è qualcosa che sto sbagliando perchè le performance che ho in lettura sono davvero scarse:

2 byte in circa 30 ms

10000 byte in circa 2800 ms

la lettura avviene con una sola chiamata alla funzione DBRead()

A questo punto ho provato ad usare la funzione ReadMultiVars() e le performance sono migliorate:

2000 byte in circa 500 ms

Il problema con questa funzione è che devo calcolare a mano i byte da trasferire + la dimensione dell'header ( che tra l'altro non ho capito quanto sia ) ed eseguire la funzione per ogni blocco da 240 byte ( PDU concordato )

Detto questo, sono riuscito ad usarla, ma dopo un certo numero di chiamate ( circa 500 ) non legge più nulla e non restituisce nessun codice di errore :(

Per contestualizzare meglio la mia situazione, sto usando:

- Visual Studio 2010, C#

- PLC Siemens S7-300 con Simatic NET

Saluti e grazie per l'aiuto,

Davide.

Link al commento
Condividi su altri siti


Sono tempi biblici :o

Ho in linea un 1500 ed ho fatto una prova con una DB da 65000 bytes.

Per conoscere il tempo ho modificato nel demo C# (per rimanere nelle tue stesse condizioni) la funzione ShowResult()

private void ShowResult(int Result)
{
  // This function returns a textual explaination of the error code
  TextError.Text = Client.ErrorText(Result) + " (" + Client.ExecTime().ToString() + " ms)";
}

Ed i tempi sono sempre nell'ordine dei 320 ms per 65000 bytes e 3 ms se il pacchetto rimane nel PDU size.

08901db3c8d48f8eef5f2a5e0c53e072.jpg

Sospetto che hai qualche problema di rete....

Raccontami meglio la tua configurazione figliuolo :)

Modificato: da dan64100
Link al commento
Condividi su altri siti

Il PC che sto usando per i test ha Windows 8.1 e c'è installato l'ambiente di sviluppo Beckhoff ( sia la versione 2, sia la 3 )

Sono collegato con il cavo ethernet direttamente al PLC

Ho modificato il programma di esempio in C#, una lettura ( DBRead ) di 10000 byte in circa 2700 ms

C'è qualche impostazione lato PLC che dovrei controllare ?

Link al commento
Condividi su altri siti

Ho appena provato con una CPU IM151-8 (PDU=240) ed ho

272 ms per 10000 bytes

751 ms per 32768 bytes (la più grande possibile per questa CPU).

Non ho windows 8 ma ho provato a suo tempo Windows 10 (technical preview) senza alcuna differenza apprezzabile.

Non credo che sia un problema di sistema operativo, i tempi di cui sopra li ho rilevati da NT 4 (in VM) fino a Windows 7.

Il ping che tempo ti da ?

Prova clientdemo.exe (su qualunque altro PC, non richiede il framework .net, basta snap7.dll) lo trovi nella cartella rich-demos/i386.

Che CPU usi ?

Sono tempi troppo alti anche per una CPU313+CP343-Lean a carbonella.

Link al commento
Condividi su altri siti

- PLC Siemens S7-300

Dovresti essere più preciso. Dai il codice completo.

Dico questo perché, anche utilizzando Step 7, si nota una differenza enorme nella velocità di comunicazione tra CPU vecchie e nuove.

Link al commento
Condividi su altri siti

CPU313C-2 DP... Pensavo fosse questo il codice completo

Domani guardo meglio

comunque è sicuramente una cpu vecchia, il mio cliente la usa da tempo per test

Quella che si dovrà usare sull'impianto sarà un plc software (ora non ho sotto mano il suo codice)

Link al commento
Condividi su altri siti

Se il SoftPLC e' Siemens allora è WinAC, 480 bytes di PDU e usa la velocità dell'adattatore di sistema a 1Gb/s.

Viaggi a 2 ms max per telegramma.

Purtroppo la CPU più piccola che ho è la IM151-8, non è un fulmine di guerra ma ha Ethernet integrata, quindi abbastanza veloce almeno per le comunicazioni.

Non ho modo di confermarti il problema della 313. Su quelle recenti o di tipo PN però ti posso assicurare i tempi di sopra ;)

Link al commento
Condividi su altri siti

Ho appena provato con il SoftPLC modello IPC477 e le prestazioni sono decisamente migliori :)

10000byte in circa 50 ms

Ora però ho un altra domanda, sempre inerente alle librerie Snap7

Prima devo spiegare brevemente cosa sto cercando di fare:

Vorrei creare un sistema di notifiche ( eventi ) al variare di alcune locazioni di memoria ( variabili )

Tralasciando l'implementazione della classe che gestisce la lista delle variabili da monitorare, il cuore del sistema consiste in un thread che continua a leggere i valori di queste in polling

Per via della natura di queste variabili, potenzialmente sparse nei vari DB, ho deciso di usare la funzione di libreria ReadMultiVars()

Ho letto nel manuale che questa funzione non esegue automaticamente lo "split" delle chiamate a seconda della dimensione del PDU concordato, quindi dovrei farlo io a mano calcolando per ogni variabili la sua dimensione + la dimensione del suo header

E qui la prima domanda: qual'è la dimensione dell'header ?

Non conoscendo la dimensione dell'header ho deciso, solo per test, di stare dalla parte della ragione ed eseguire una lettura a blocchi di 10 variabili ( ogni variabile è un intero da 2 byte )

Il sistema sembra funzionare.

Sempre per test ho aggiunto un centinaio di variabili "in ascolto", alcune delle quali vengono incrementate dal PLC ogni secondo ed il supervisore visualizza correttamente il loro valore.

Il problema è che dopo un certo numero di letture il sistema non funziona più e ReadMutilVars() sembra non leggere lo stato aggiornato delle variabili, ritorna sempre l'ultimo valore letto e non quello attuale.

Link al commento
Condividi su altri siti

Ho fatto altri test per capire meglio

Ho semplificato al massimo il codice nel thread di lettura per cercare di isolare il problema

Ora nel thread esegue una lettura con ReadMultiVars() ed una con DBRead(), entrambe della stessa locazione di memoria ( DB5.10 x 2 byte )

l'esecuzione è condizionata da un semaforo rilasciato da un timer da 20 ms ( ho variato il valore del timer diverse volte, ma il risultato non cambia )

Ogni volta stampo una stringa del tipo:

Numero Progressivo - Valore letto con ReadMultiVars() - Valore letto con DBRead()

questo è il risultato:

1 -> RM: 0x14 0x7a - DBR: 0x14 0x7a
2 -> RM: 0x14 0x7a - DBR: 0x14 0x7a
3 -> RM: 0x14 0x7a - DBR: 0x14 0x7a
4 -> RM: 0x14 0x7a - DBR: 0x14 0x7a
...
38 -> RM: 0x14 0x7b - DBR: 0x14 0x7b
39 -> RM: 0x14 0x7b - DBR: 0x14 0x7b
...
200 -> RM: 0x14 0x7e - DBR: 0x14 0x7e
201 -> RM: 0x14 0x7e - DBR: 0x14 0x7e
...
2960 -> RM: 0x14 0xb4 - DBR: 0x14 0xb4
2961 -> RM: 0x14 0xb4 - DBR: 0x14 0xb4
...
3008 -> RM: 0x14 0xb4 - DBR: 0x14 0xb5 Da qui in poi la ReadMultiVars() non funziona più correttamente
3009 -> RM: 0x14 0xb4 - DBR: 0x14 0xb5
...
7498 -> RM: 0x14 0xb4 - DBR: 0x15 0x0c
7499 -> RM: 0x14 0xb4 - DBR: 0x15 0x0c
Dopo un certo numero di operazioni di lettura, la funzione ReadMultiVars() restituisce sempre lo stesso valore, mentre la funzione DBRead() continua a leggere correttamente
Link al commento
Condividi su altri siti

MultiRead/Write è una funzione nativa di S7Protocol, è stata pensata da Siemens per acquisire molte variabili con indirizzi eterogenei sfruttando un solo telegramma.

In caso di variabili grandi non ha alcun senso splittarle, in ogni caso vanno a saturare il PDU quindi tante variabili grandi in parallelo ci mettono lo stesso tempo di tante variabili grandi in serie, anzi di più perché per ogni variabile devi aggiungere un header nel telegramma.

I payload sono

Lettura : PDULength-(12+12*NumItems)

Scrittura : PDULength-(12+16*NumItems)

Dove PDULength è il PDU negoziato (non assumerlo di 240, nella tua nuova CPU è senz'altro 480) e NumItems è max 20.

----------

Sono arrivato a circa 35000 cicli in ambiente e 10000 nel compilato, ed ancora ottengo valori diversi.

La funzione nella libreria è certo che funziona, la uso da sempre per acquisire in parallelo i triggers delle stazioni all'interno di un PLC e non ha mai perso un colpo.

Il grosso punto interrogativo è come al solito il Garbage collector di .NET (secondo come utilità solo alla scabbia).

Mi sono messo nell'ipotesi credo peggiore, chiamo ciclicamente una funzione di lettura ed al suo interno creo il reader.

Ora provo ad usare un'istanza globale (ho inserito apposta il metodo clear() ) e vediamo cosa accade...

P.S.

Stai usando snap7 1.4.0 e la nuova classe S7MultiVar giusto ?

Modificato: da dan64100
Link al commento
Condividi su altri siti

Effettivamente stavo usando la versione 1.3 delle librerie

Ho scaricato la nuova versione ( 1.4 ) ed ho visto la classe S7MultiVar, ho visto che ora salvi tutti i GCHandle associati ai buffer di lettura. Effettivamente non ci avevo fatto caso, il Garbage collector potrebbe essere la causa del malfunzionamento che vedo

Ora non ho il PLC sotto mano, ma domani mattina provo con la nuova versione...

Grazie ancora per l'aiuto ;)

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