Vai al contenuto

Invio di stringhe con valore variabile su socket TCP

Home Forum Programmazione IEC 61131 (LogicLab) Invio di stringhe con valore variabile su socket TCP

Stai visualizzando 12 post - dal 1 a 12 (di 12 totali)
  • Autore
    Post
  • #35707
    Giulio
    Partecipante

    Stò 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 ?

    #38649
    Sergio Bertana
    Amministratore del forum

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

    #38652
    Giulio
    Partecipante

    La 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 !

    #38653
    Sergio Bertana
    Amministratore del forum

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

    #38654
    Giulio
    Partecipante

    OK…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 ?

    #38655
    Sergio Bertana
    Amministratore del forum

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

    #38657
    Giulio
    Partecipante

    No, è 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à…

    #38658
    Sergio Bertana
    Amministratore del forum

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

    #38659
    Giulio
    Partecipante

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

    #38660
    Sergio Bertana
    Amministratore del forum

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

    #38663
    Giulio
    Partecipante

    Davvero 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 ?

    #38664
    Sergio Bertana
    Amministratore del forum

    Non 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 WMsgPulse

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

Stai visualizzando 12 post - dal 1 a 12 (di 12 totali)
  • Devi essere connesso per rispondere a questo topic.