Invio di stringhe con valore variabile su socket TCP
Home › Forum › Programmazione IEC 61131 (LogicLab) › Invio di stringhe con valore variabile su socket TCP
- Questo topic ha 11 risposte, 2 partecipanti ed è stato aggiornato l'ultima volta 10 anni, 3 mesi fa da
Sergio Bertana.
-
AutorePost
-
Gennaio 14, 2015 alle 7:23 pm #35707
Giulio
PartecipanteStò facendo qualche prova di trasmissione utilzzando la Sysfopen la SysSktListen e la SysVarfPrintf in Ladder.
La connessione avviene regolarmente ma quando trasmetto i dati (una stringa di 10 caratteri) questa viene trasmessa N volte consecutive sino al raggiungimento del valore del buffer TxSize. Con il TxSize=100 la stringa viene trasmessa esattamente 10 volte… Ho provato anche con la Sysfputc e vedo trasmettere 100 caratteri…
Ho ripreso un pò di programmi di esempio (tutti in ST, per la verità), fatto qualche prova con esito del tutto “normale”. Ho notato che il FB SysSktListen è dotato di pin EN/ENO non “eliminabili”, diversamente da come appare in documentazione. Può esserci un nesso ? Qualche idea ? Cosa mi sfugge ?
Gennaio 15, 2015 alle 8:06 am #38649Sergio Bertana
Amministratore del forumPremesso che per la gestione delle comunicazioni preferisco utilizzare il linguaggio ST, in quanto più adatto e più leggibile, ma nulla vieta di utilizzare anche altri linguaggi come FBD o LD. Nel manuale infatti solitamente si riportano esempi in linguaggio ladder.
Veniamo al tuo problema ho realizzato un semplice programma LD (Stampa e Download programma), sono partito dall’esempio del manuale riferito alla FB SysSktListen ed ho aggiunto la stampa del valore della variabile SysDateTime. Come vedi però l’esecuzione della funzione SysVarfprintf viene condizionata sul fronte di attivazione della variabile SysClock1000. In questo modo si ha l’invio della stringa sul socket ogni 2 secondi.
Se esegui in modo incondizionato la SysVarfPrintf viene continuamente inviato sul socket la stringa fino al raggiungimento del numero di caratteri pari alla dimensione del buffer di socket.
Per la domanda relativa ai segnali EN/ENO ti rimando a questo topic.
Gennaio 15, 2015 alle 10:46 am #38652Giulio
PartecipanteLa mia perplessità era appunto sulla differenza di comportamento della SysVarfprintf che avevo osservato tra il linguaggio LD e ST. Considera che nelle prove che ho fatto l’esecuzione della funzione non era ‘libero’, ma condizionato alla effettiva connessione di un client (SysSktListen.Connect ) in AND ad un ingresso della CPU…
Con client connesso premevo il tasto, partiva la stringa…. in effetti alla pressione del tasto la stringa parte ma viene trasmessa N volte. Per la precisione, osservando il watch delle variabili della printf ho notato che questa non trasmette 100 caratteri (valore del buffer) ma i 10 previsti… solo che sembra venga richiamata N volte ! ….
Temo mi sfugga qualcosa di banalmente importante !
Gennaio 15, 2015 alle 1:17 pm #38653Sergio Bertana
Amministratore del forumDevi considerare il modo in cui sono eseguiti i programmi PLC, il programma viene ciclicamente eseguito nella task dove è inserito. Il programma del post precedente ad esempio è eseguito nella task di Back, essendo un programma molto semplice il tempo di esecuzione è estremamente veloce, come vedi nello screenshot, l’esecuzione del programma (Variabile SysTBackExTm) dura 15uS, il programma viene eseguito (Variabile SysTBackLpTm) ogni 372uS.
Quindi quando tu dici che condizioni l’esecuzione all’ingresso logico del modulo CPU, tieni presente se attivi l’ingresso per 1 secondo, la funzione SysVarfprintf verrà eseguita circa 2700 volte.
Se noti nel mio esempio la variabile SysClock1000 e di tipo -]P[- cioè fronte di salita, in pratica il ramo è attivo per un solo loop di programma quando la variabile passa dallo stato inattivo ad attivo.
Gennaio 15, 2015 alle 6:54 pm #38654Giulio
PartecipanteOK…chiaro ! Lo dicevo che mi sfuggiva qualcosa di banalmente fondamentale ! Ho utilizzato il contatto -|p|- e funziona tutto normalmente !
Qualcosa del genere (banali errori fondamentali) mi sta succedendo con il codice ST: le variabili collegate ad ingressi non vengono “sentite” dal programma. Nella finestra watch le vedo “muoversi” correttamente ma il programma le legge sempre “FALSE” e si comporta di conseguenza (mi ignora !).
Tra l’altro non ho visto esempi funzionanti di gestione di ingressi logici letti con programmi ST. Puoi darmi qualche spunto anche qui ?
Gennaio 16, 2015 alle 7:30 am #38655Sergio Bertana
Amministratore del forumNon capisco esattamente cosa intendi quando dici che gli I/O non vengono sentiti dal programma ST. Gli I/O logici possono essere gestiti indifferentemente da tutti e 5 i linguaggi della IEC61131. Mi viene il dubbio che tu abbia scritto il programma ma poi non lo abbia inserito in nessuna task di esecuzione.
Anche se è più logico un circuito di Marcia/Arresto gestirlo in linguaggio LD ecco lo screenshot di un programma di esempio in linguaggio ST. Come vedi tutti gli I/O sono gestiti da ST, l’esecuzione del programma trattandosi di sequenze logiche l’ho inserita nella task Slow (Download programma).
Attenzione, il programma postato precedentemente che gestiva una comunicazione su stream andava necessariamente eseguito nella task Back. Le varie tasks possono contenere più programmi da eseguire e l’esecuzione all’interno della task è effettuata in base all’elenco dall’alto verso il basso (Topic). Altro topic che tratta l’argomento.
Gennaio 16, 2015 alle 9:13 am #38657Giulio
PartecipanteNo, è lo stesso programma funzionante in LD, sempre nell’ambito di prove di comunicazione. Era nel task di background ma ho provato anche ad inserirlo in altri task. Accetta connessioni TCP su un socket diverso dal programma di prima (e funziona, si connette) e, se connesso, su pressione di un tasto invia una stringa.
Ho provato usando la stessa variabile globale usata per il programam LD, un’altra variabile, una variabile locale, un array in cui mappavo i 4 ingressi con un programma LD…. nella finestra watch vedo sempre la variabile diventare TRUE quando attivo l’ingresso ma il programma continua a girare come se fosse FALSE. Se inizializzo la variabile a TRUE, funziona al primo giro, poi quando uso l’ingresso non va più (ma nel watch è sempre tutto OK). Ho ipotizzato problemi di sintassi mettendo la variabile dentro e fuori parentesi ma continua ad ignorarmi !
Riassumo, per chiarezza: sul PLC nel task di background girano due programmi, uno scritto in LD che ascolta sulla porta 1111 e un altro scritto in ST che ascolta sulla porta 2000. In un tentativo che ho fatto c’è un terzo programma in ladder che mappa i 4 ingressi della CPU in un array letto dal programma ST. Questo programma era stato messo nel task SLOW.
Il tuo programma di esempio, naturalmente, funziona… il che mi fa pensare che nel mio ci sia ancora qualche problema “esistenziale” legato ad interazioni con altre funzionalità…
Gennaio 16, 2015 alle 9:53 am #38658Sergio Bertana
Amministratore del forumMi parli di array in cui mappi gli ingressi digitali da programma LD e sinceramente non ho ben chiaro a cosa ti riferisci in questo topic si parla di array di I/O digitali.
Però vista la complessità della domanda forse è meglio se invii alla nostra eMail di supporto il programma così da poterlo verificare direttamente.
Gennaio 16, 2015 alle 10:24 am #38659Giulio
PartecipanteForse sono stato troppo prolisso…la cosa non è complessa ! io ho usato una semplice variabile mappata sull’I/O come nel tuo esempio… poi, visto che non funzionava, ho provato di tutto, tra cui il mappaggio su un array fatto tramite un programma LD (4 network, su ciascuno un contatto che valorizzava una posizione dell’array).
Dimentica l’array… Il problema resta semplice e sicuramente legato a qualche mio errore basilare e concettuale: ho una variabile “PremutoTasto” collegata all’ingresso 1 del modulo CPU e la testo in AND alla SocketConnect ; Quando premo il tasto, nella finestra di watch si vede la variabile passare a TRUE, ma il programma continua a considerarla FALSE…
Controprova: Definisco la variabile inizializzata a TRUE; il primo giro va bene, viene riconosciuta e la stringa parte, poi, tornata FALSE, non viene più letta correttamente dal programma (mentre in watch window evolve correttamente).
Gennaio 16, 2015 alle 10:57 am #38660Sergio Bertana
Amministratore del forumEcco lo screenshot del tuo programma (Tanti piccoli errori da correggere e/o migliorie da consigliarti).
Come vedi parlo di effetto -]P[- da creare in ST, nel linguaggio LD basta mettere il simbolo in ST devi creare l’effetto transizione per poter gestire il fronte di salita e/o discesa ecco come fare. AuxPls è una variabile BOOL locale nel tuo programma.
IF (Ingresso <> AuxPls) THEN
AuxPls:=Ingresso; (* Auxiliary pulse *)IF (Ingresso) THEN
Tutto quello scritto qui avviene sul fronte di attivazione -]P[-
END_IF;IF NOT(Ingresso) THEN
Tutto quello scritto qui avviene sul fronte di disattivazione -]N[-
END_IF;
END_IF;Nel tuo progetto hai anche scelto di eseguire il download del codice sorgente ad ogni download e questo rallenta il download ad ogni modifica di programma, leggi attentamente questo topic.
Gennaio 16, 2015 alle 3:24 pm #38663Giulio
PartecipanteDavvero un aiuto prezioso… sono pochi giorni che sto utilizzando l’ambiente e andando di fretta, con tanta roba, temo sempre sfugga qualcosa di grosso ! Apprezzo davvero molto il tuo contributo.
In altre prove che ho fatto ho gestito meglio i dettagli di contorno ma qui mi sono incastrato in mille prove sul codice e quello che tu hai è solo uno dei vari tentativi (come ti accennavo ho usato variabili globali, locali, array, assegnazioni dappertutto… porcherie di ogni genere per aggirare il problema che pensavo potesse essere di indirizzamento).
Quindi, in conclusione, mi sembra di capire che il problema è legato anche in questo caso alla necessità di lettura del fronte invece che semplicemente dello stato dell’I/O…. però nel programma ladder il comportamento era opposto: li’ ad ogni ciclo veniva trasmessa la stringa sino al rempimento del buffer, qui veniva ignorato tutto ! Hai idea del perchè di questa differenza ?
Gennaio 16, 2015 alle 3:38 pm #38664Sergio Bertana
Amministratore del forumNon ho l’ultimo tuo programma, ma il perchè il quell’esempio ST viene ignorato l’ingresso l’ho spiegato nello screnshot, entri nella IF dove leggi l’ingresso solo sul fronte di connessione del socket poi non entri più.
In pratica tutto quello che è scritto dentro la IF non viene mai eseguito IF vuol dire se… se è vera la condizione THEN allora esegui…
IF (SktLsn.Connect <> WMsgPulse) THEN è vera solo sul fronte di connessione perchè dopo
WMsgPulse:=SktLsn.Connect; copia lo stato della connessione sul BOOL WMsgPulseE tu copiavi l’ingresso proprio dentro l’IF quindi non lo copiavi mai… o meglio lo avresti copiato una sola volta sulla connessione del socket.
-
AutorePost
- Devi essere connesso per rispondere a questo topic.