Vai al contenuto

Sergio Bertana

Risposte nei forum create

Stai visualizzando 15 post - dal 76 a 90 (di 4,315 totali)
  • Autore
    Post
  • in risposta a: Invio eMail da sistema SlimLine #82287
    Sergio Bertana
    Amministratore del forum

    Venendo al tuo programma vediamo le inesattezze, ce ne sono molte…

    • Il TCPClient è sempre in connessione. Occorre connettersi solo quando si invia la eMail e sconnettersi al termine dell’invio. Se vedi nei ns esempi il comando di Connect è gestito dal FB di invio eMail TCPClient(Connect:=Mailer.Connect).
    • Esegui un invio a raffica di tutti i comandi HELO, username, password. L’invio dei dati và fatto in risposta alle richieste del server.
    • Terminato l’invio occore atendere l’Ok dal server e solo dopo inviare il comando di QUIT.
    • Inviato il comando di QUIT occorre chiudere la connessione con il server.
    • Ho visto che hai scritto SysFWrite e non Sysfwrite, siccome non hai errori di compilazione immagino che non hai settato il controllo maiuscole/minuscole nel progetto.

    Riguardo all’errore:

    i := Sysfwrite(Fp, ADR('EHLO smtp.office365.com' + CHR(13) + CHR(10)), Sysstrlen('EHLO smtp.office365.com' + CHR(13) + CHR(10)));

    La funzione Sysfwrite, ha come 1° parametro l’indirizzo della stringa da inviare, come 2° parametro la lunghezza della stringa, come 3° parametro il numero di stringhe e come 4° parametro lo stream di comunicazione a cui inviare i dati. Quindi và scritta in questo modo:

    eTO_JUNK(Sysfwrite(ADR('EHLO smtp.office365.com$r$n'), Sysstrlen(ADR('EHLO smtp.office365.com$r$n')), 1, Fp));

    Ho sostituito i:= con la nuova definizione eTO_JUNK. Ho sostituito CHR(13) e CHR(10) con le rispettive codifiche $r e $n vedi articolo.

    Attenzione alla capienza del buffer dello stream di comunicazione, nel TCP client hai definito il buffer di trasmissione a 256 caratteri ma la somma delle tue scritture Sysfwrite credo abbia dimensione maggiore quindi i caratteri che non ci stanno nel buffer vengono scartati.

    in risposta a: Invio eMail da sistema SlimLine #82280
    Sergio Bertana
    Amministratore del forum

    Per inviare l’eMail dal un sistema SlimLine devi utilizzare il FB EMailSend, puoi utilizzare l’esempio ST_EMailSend in fondo alla pagina. Colgo l’occasione della domanda per evidenziare alcuni punti.

    • L’invio eMail senza crittografia TLS ormai non è quasi piu accettato dai servers SMTP, nel’esempio ho utilizzato Virgilio che sembra ancora accettare invio non crittografato.
    • Per poter inviare eMail su qualunque server SMTP occorre utilizzare la crittografia come riportato nell’esempio ST_TLSEMailSend.
    • In alternativa al FB SysTLSClient eseguire un programma mail relay su un PC, SlimLine invia al relay l’eMail non crittografata ed il relay l’inoltrerà al server pubblico crittografato.
    • Per utilizzare come server di inoltro GMail occorre utilizzare la password generata dal servizio Password per le app. Rimando alla lettura di questa nota applicativa.
    in risposta a: Question about object polymorphism #82272
    Sergio Bertana
    Amministratore del forum

    I’ve rewritten your program in a form I supposed was correct but there’s two compiling errors.

    VAR
        SquareArea : REAL; (* Square area *)
        SquarePerimeter : REAL; (* Square perimeter *)
        RectangleArea : REAL; (* Rectangle area *)
        RectanglePerimeter : REAL; (* Rectangle perimeter *)
        RForm : Form; (* Reference to Form *)
        MySquare : Square^; (* Reference to Square *)
        MyRectangle : Rectangle^; (*  Reference to Rectangle *)
    END_VAR
    
        // Program initializations.
    
        IF (SysFirstLoop) THEN
    //        MySquare:=SysMAlloc(SIZEOF(Square));
    //        MyRectangle:=SysMAlloc(SIZEOF(Rectangle));
    
            MySquare^.Side:=10; //Square side
    
            MyRectangle^.Width:=20; //Rectangle width
            MyRectangle^.Height:=4; //Rectangle height
        END_IF;
    
        // Calculates area and perimeter.
    
        RForm:=MySquare^; //Reference to Form
        SquareArea:=RForm.Area(); //Square area
        SquarePerimeter:=RForm.Perimeter(); //Square perimeter
    
        RForm:=MyRectangle^; //Reference to Form
        RectangleArea:=RForm.Area(); //Rectangle area
        RectanglePerimeter:=RForm.Perimeter(); //Rectangle perimeter

    I’ve to ask to Axel support how to manage this  scenario.

    I’ve a question, why you would dynamically instantiate the FBs? Is not easiest simply instantiate they in the data memory?

    in risposta a: Invio eMail da dispositivo STE2 su server SMTP autenticato #82264
    Sergio Bertana
    Amministratore del forum

    I prezzi sono visibili direttamente dal sito su registrazione, oltre ai prezzi è visibile anche la disponibilità del prodotto.

    Il prodotto può inviare eMail su allarme senza bisogno di licenze, in questa nota applicativa si trovano le impostazioni per impostare come server SMTP di inoltro un qualsiasi account di GMail.

    In aggiunta all’invio autonomo delle eMail il prodotto può essere connesso al portale HWg-Cloud senza bisogno di licenze mentre è prevista una licenza per il portale SensDesk (Vedi articolo).

    in risposta a: Question about object polymorphism #82251
    Sergio Bertana
    Amministratore del forum

    Yes, also in LogicLab as in many modern IEC 61131-3 environments such as TwinCAT 3, Codesys v3.x, it is possible to dynamically assign a Function Block (FB) to a variable of interface type, provided that the FB implements that interface. The idea is that you can use an interface as an abstract type and dynamically assign an FB that implements it usually through pointer dereferencing (^) or a type cast.

    You can download Polymorphism a LogicLab program with an example of use the polymorphism, essentially referring to the screenshot yo can see the Form interface that refer to a trigonometric figure that has two method prototypes.

    • Area: This method calculates the area of the form
    • Perimeter: This method calculates the perimeter of the form

    Then two FBs are been defined each implement the Form interface, with the code to calculate the perimeter and area of the relate trigonometric figure. In the FBReference program the RForm variable of Form interface type is istantiated. Then by referencing RForm to different trigonometric figure is possible to calculate perimeter and area of them.

    in risposta a: Copia e comparazione array e strutture dati #82240
    Sergio Bertana
    Amministratore del forum

    In effetti LogicLab permette di definire la copia di variabili sia di tipo array che di tipo struttura, ma non permette operazioni di confronto.

    Nelle nostre librerie è disponibile la funzione MemCompare che oltre ad eseguire la comparazione tra qualsiasi tipo di variabile se il parametro Update è attivo esegue anche la copia del valore della variabile definita in Source nella variabile definita in Destination.

    Quindi il tuo programma diventerà:

    VAR
        ChkOk : BOOL;
        MyStruct1 : MYSTRUCT;
        MyStruct2 : MYSTRUCT;
    END_VAR
    
        MyStruct2:=MyStruct1;
        ChkOk:=NOT(MemCompare(ADR(MyStruct2), ADR(MyStruct1), SIZEOF(MyStruct2), FALSE));
    in risposta a: Acquisizione in corrente 4-20mA su ingressi analogici modulo CPU #82216
    Sergio Bertana
    Amministratore del forum

    Su qualsiasi sistema gli ingressi in mA in realtà sono in volt in quanto i convertitori A/D convertono segnali in volt. Quindi per acquisire una corrente si utilizza una resistenza di shunt di valore predefinito e si acquisisce la tensione ai sui capi rilevando la corrente con la legge di Ohm (I=V/R).

    Sui nostri moduli CPU SlimLine gli ingressi sono 0-10Volt quindi inserendo una resistenza di shunt da 500Ohm avremo alla corrente di 20mA i 10Volt in ingresso. Se guardi alla definizione AI_MODE del parametro Mode del FB SysGetAnInp vedrai che le acquisizioni in corrente non sono possibili sui moduli CPU. E se le imposti nel programma il FB SysGetAnInp avrà l’uscita di Fault sempre attiva. Con il comando SysLog vedrai il messaggio: User program error:9983200 e dalla pagina errori:

    9983200 Il modo acquisizione definito in “Mode” non è corretto SysGetAnInp.

    Venendo alla tua necessità di acquisire un trasduttore 4-20mA con gli ingressi analogici del modulo CPU dovrai mettere tra l’ingresso e massa una resistenza da 500Ohm ed acquisire l’ingresso in tensione 0-10Volt. Potrai con la funzione ValueScale trasformare i 2-10Volt acquisiti dall’ingresso nella grandezza ingegneristica rilevata dal trasduttore.

    in risposta a: Problema nella gestione uscite PWM #82207
    Sergio Bertana
    Amministratore del forum

    Le versioni dei firmware sui moduli sono aggiornate…

    Ma riguardando il tuo programma mi sono accorto che nella task Slow esegui una ventina di acquisizioni analogiche (FB SysGetAnInp), come riportato nel capitolo Multiplexing acquisizione del FB l’acquisizione analogica sul bus di estensione richiede un tempo variabile tra i 300-500uS quindi di media occorrono circa 8mS per acquisire tutti i moduli, considerando che il task Slow viene seguito ogni 10mS re dovendo anche gestrire sia gli I/O logici che le uscite PWM si rischia di saturare completamente il tempo e non lasciare più tempo per eseguire la task Back.

    Quindi il consiglio è di sequenziare le acquisizioni analogiche tanto è inutile eseguirle ogni 10mS visto che il tempo di conversione A/D è di minimo 60mS e che quando si acquisiscono temperature le variazioni sono molto lente. Alcune informazioni aggiuntive:

    • Mi sono perso l’inizio della storia, questo programma inizialmente funzionava e poi ha smesso di funzionare, oppure si hanno sempre avuti problemi fin dall’inizio.
    • Le uscite PWM che hanno problemi sono sempre e solo quelle del modulo di estensione oppure sono anche quelle del modulo CPU.
    • Puoi inviare al supporto tecnico il file di log del sistema. Lo trovi nella cartella C:\System e lo puoi scaricare via FTP.
    • Puoi verificare i tempi di esecuzione delle varie tasks. Puoi mettere in debug la variabili con i tempi presenti in libreria.
    in risposta a: Problema nella gestione uscite PWM #82176
    Sergio Bertana
    Amministratore del forum

    Ho analizzato il programma che hai mandato è molto complesso quindi mi è difficile capire cosa succede ma ho notato alcune cose:

    Hai eseguito in task Fast il programma CYCLE che gestisce l’abilitazione delle tue FB di gestione PWM le quali però sono eseguite in task Slow.  Questa soluzione non dà vantaggi perchè i tempi di gestione del PWM sono comunque quelli della task Slow. Inoltre gestire variabili cross task con la task Fast può nascondere delle insidie la task Fast non gestisce l’immagine di processo sulle variabili. Quindi il primo consiglio è di spostare il programma CYCLE in task Slow.

    Puoi dirmi la versione del firmware del modulo CPU e la versione del firmware del modulo di I/O che gestisce il PWM. Per visualizzare la versione devi connetterti in telnet ed utilizzare il comando SLineInfos.

    Quando dici “Talvolta almeno una delle uscite PWM non si ferma anche se Frequency e Duty sono a zero” intendi che non si ferma immediatamente oppure che continua a generare l’uscita.

    Quando dici “Talvolta almeno una delle uscite PWM non parte anche se Frequency e Duty sono diversi da zero” in questo caso il valore di Frequency è comunque maggiore del valore minimo gestito da quel canale PWM. I valori li trovi qui nel capitolo “Moduli supportati”.

    Per completezza e rifacendomi al cast delle variabili ho visto che la compilazione del tuo programma genera 260 warnings. Certo le warnings solitamente non generano problemi ma attenzione warning come questa

    P_OB1(58) - warning G0082:  DUTY_C_M3 => Writing a signed value into an unsigned variable

    Satnno ad indicare che stai copiando il valore di una variabile con segno nel tuo caso di tipo INT in una variabile senza segno nel tuo caso UINT. Ora se il valore della variabile INT diventa negativo (Ad esempio -1) il valore della variabile UINT divente 65535. Quindi in questi casi bisogna essere certi che la variabile con segno non diventi mai negativa.

    in risposta a: Computo ore funzionamento dispositivi con FB TimeBalancing #82161
    Sergio Bertana
    Amministratore del forum

    Quindi con selettore in AUT dovrai abilitare il relativo bit in DEnable così da permettere al FB di gestire la pompa in base alla richiesta.

    Con il selettore in MAN dovrai disabilitare il relativo bit in DEnable così da impedire al FB di gestire la pompa. E poi dovrai gestire l’incremento del tempo utilizzando l’ingresso che indica lo stato di contatore attivo.

    in risposta a: Lettura ingressi con richiesta HTTP #82146
    Sergio Bertana
    Amministratore del forum

    La soluzione è facilmente realizzabile utilizzando il FB HTTPClient. Ti posto il programma HTTPLIAcquire che fà quello che ti serve.

    PROGRAM HTTPLIAcquire
    VAR
        IRequest : BOOL; (* Input request *)
        CaseNr : USINT; (* Program case *)
        Errors : UDINT; (* Execution errors *)
        APtr : PVOID; (* Auxiliary pointer *)
        Page : STRING[ 512 ]; (* Page string *)
        LInput : ARRAY[0..1] OF BOOL; (* Input status *)
        TCPClient : SysTCPClient; (* TCP client management *)
        HTTPRq : HTTPClient_v5; (* HTTP client *)
    END_VAR
    
    // *****************************************************************************
    // PROGRAM "HTTPLIAcquire"
    // *****************************************************************************
    // Acquisizione ingressi via HTTP.
    // -----------------------------------------------------------------------------
    
        // -------------------------------------------------------------------------
        // INITIALIZATIONS
        // -------------------------------------------------------------------------
        // Program initializations.
    
        IF (SysFirstLoop) THEN
    
            // Set TCPClient parameters.
    
            TCPClient.PeerAdd:=ADR('127.0.0.1'); //Peer address
            TCPClient.PeerPort:=80; //Peer port
            TCPClient.LocalAdd:=ADR('0.0.0.0'); //Local address
            TCPClient.LocalPort:=0; //Local port
            TCPClient.FlushTm:=50; //Flush time (mS)
            TCPClient.LifeTm:=20; //Life time (S)
            TCPClient.RxSize:=512; //Rx buffer size
            TCPClient.TxSize:=512; //Tx buffer size
    
            // Set HTTPClient parameters.
    
            HTTPRq.SpyOn:=TRUE; //Activate the spy
            HTTPRq.KeepAlive:=FALSE; //HTTP keep-alive
            HTTPRq.RMethod:=HTTP_REQUEST#HTTP_GET; //HTTP request method
            HTTPRq.HostName:=TCPClient.PeerAdd; // Hostname
            HTTPRq.Page:=ADR('InputRead.html'); //Web page
            HTTPRq.Request:=eNULL; //Request string
            HTTPRq.Header:=eNULL; //HTTP header
            HTTPRq.DBSize:=512; //Data buffer size
            HTTPRq.Timeout:=T#10s; //Execution timeout
        END_IF;
    
        // -------------------------------------------------------------------------
        // MANAGE CONNECTION
        // -------------------------------------------------------------------------
        // Manage the connection.
    
        TCPClient(Connect:=HTTPRq.Connect); //TCPClient management
        HTTPRq(Enable:=TRUE, File:=TCPClient.File); //HTTP client
        IF (HTTPRq.Fault) THEN CaseNr:=0; END_IF;
    
        // -------------------------------------------------------------------------
        // PROGRAM SEQUENCIES
        // -------------------------------------------------------------------------
        // Program sequencies.
    
        CASE (CaseNr) OF
    
            // ---------------------------------------------------------------------
            // Initialize the time to manage acquisition delay.
    
            0:
            HTTPRq.Send:=FALSE; //Send request
            IF NOT(IRequest) THEN RETURN; END_IF;
            eTO_JUNK(Sysmemset(ADR(Page), 0, SIZEOF(Page))); //Empty page string
            IRequest:=FALSE; //Input request
            HTTPRq.Send:=TRUE; //Send request
            CaseNr:=CaseNr+1; //Program case
    
            // ---------------------------------------------------------------------
            // Trasferisco in "Page" i dati ricevuti.
    
            1:
            IF ((HTTPRq.DBChars <> 0) AND HTTPRq.HPSelector) THEN
                IF ((Sysstrlen(ADR(Page))+HTTPRq.DBChars) < SIZEOF(Page)) THEN
                    eTO_JUNK(Sysmemmove(TO_DWORD(ADR(Page))+Sysstrlen(ADR(Page)), HTTPRq.DBAddress, HTTPRq.DBChars));
                END_IF;
            END_IF;
    
            // Sul "Done" terminato ricezione risposta.
            // Controllo se ricevuto dati dal server.
    
            IF NOT(HTTPRq.Done) THEN RETURN; END_IF;
    
            CaseNr:=0; //Program case
            IF NOT(HTTPRq.PLoad) THEN Errors:=Errors+1; RETURN; END_IF;
    
            // Sul "PLoad" in "Page" ho la stringa ricevuta "&0&0&2&1&1&".
            // Decodifica valori ricevuti, qui posso fare tutti i controlli.
            // Intanto se s tringa sempre stessa lunghezza la posso verificare.
    
            IF (Sysstrlen(ADR(Page)) <> 11) THEN Errors:=Errors+1; RETURN; END_IF;        
    
            // Se stringa prima del 1° dato è sempre "&0&0&2&" per leggere il dato.
            
            APtr:=SysStrFind(ADR(Page), ADR('&0&0&2&'), FIND_GET_END);
            IF (APtr = eNULL) THEN Errors:=Errors+1; RETURN; END_IF;     
            IF NOT(SysVsscanf(APtr, ADR('%d'), BOOL_TYPE, ADR(LInput[0]))) THEN Errors:=Errors+1; RETURN; END_IF;
            IF NOT(SysVsscanf(APtr+2, ADR('%d'), BOOL_TYPE, ADR(LInput[1]))) THEN Errors:=Errors+1; RETURN; END_IF;
        END_CASE;
    
    // [End of file]

    Per provarlo ho caricato una pagina con la stringa dfi testo direttamente nella cartella Web dello SlimLine e quindi mi sono connesso al localhost 127.0.0.1. Nel tuo programma dovrai modificare:

        TCPClient.PeerAdd:=ADR('192.168.100.101'); //Peer address
        HTTPRq.Page:=ADR('input.cgi#'); //Web page
    in risposta a: Costruzione macchina per spazzolare catene #82137
    Sergio Bertana
    Amministratore del forum

    Adesso è più chiaro…

    Si puoi utilizzare MPS056B320 se abbini un convertitore RS232/RS485 come l’HWPATC106. Questo convertitore non isola la RS485 ma se la connessione è interno quadro è accettabile.

    Il modulo CPU può gestire 2 uscite PWM se vuoi gestire anche il posizionamento devi connettere le uscite PWM ad un ingresso counter ed il modulo ne supporta 2 nativi e altri 2 con una opzione. Quindi 2 motori passo-passo con frequenza fino a 3KHz sono gestibili con il solo modulo CPU senza opzioni.

    Per gestire 4 motori devi utilizzare un modulo di estensione PCB124B010 dove 1 counter è nativo ma serve una opzione per abilitarne altri 3.

    Veniamo al FB MotorPositioning, questo FB è stato realizzato per un cliente specifico per il comando del posizionamento via Modbus e prevede l’acquisto di una opzione. Nello svilupparlo abbiamo anche previsto la possibilità di gestire il posizionamento di un motore step con uscita PWM ed ingresso counter ma con il PWM è stata provata solo in laboratorio quindi magari necessita di aggiustamenti in fase di test.

    in risposta a: Costruzione macchina per spazzolare catene #82129
    Sergio Bertana
    Amministratore del forum

    Cerco di dare le risposte alle varie domande.

    • Comando 2 Motori Brushless tramite MODBUS seriale RTU, immagino i driver abbiano interfaccia RS485, quindi ti consiglio MPS054C110. Per la gestione della comunicazione puoi utilizzare il FB ModbusMaster.
    • Comando 2 Motori Passo-Passo, puoi utilizzare le 2 uscite digitali del modulo CPU con il FB SysSetPWMOut puoi gestire range frequenza 5Hz÷3kHz.
    • 2 Apparecchiature con comando 0-10V, puoi utilizzare un modulo mixed I/O PCB122D100.
    • 15 ingressi digitali, 12 sono disponibili sul modulo PCB122D100.
    • 10 uscite digitali, 8 sono disponibili sul modulo PCB122D100.
    in risposta a: Problema nella gestione uscite PWM #82117
    Sergio Bertana
    Amministratore del forum

    Nel FB SysSetPWMOut azzerando Frequency e/o azzerando Duty l’uscita PWM deve azzerarsi, così come impostando un valore nei due parametri l’uscita deve generare la frequenza impostata, trovo strano che questo non succeda.

    Nel tuo programma vedo che le variabili APPO_FREQ ed APPO_DUTY sono di tipo UINT mentre il FB vuole variabili di tipo REAL, credo che nella compilazione del programma ti vengano segnalate warnings ad indicare questa incongruità di tipo sulle variabili.

    Teoricamente LogicLab dovrebbe effettuare il cast del valore corettamente, comunque proverei ad inserire il cast sui valori.

    FB_PWM_OUT(Address:=ADDR, Channel:=CHAN, Frequency:=TO_REAL(APPO_FREQ), Duty:=TO_REAL(APPO_DUTY));
    • Il FB da te realizzato è sempre eseguito?
    • In che task lo stai eseguendo?
    • Puoi verificare con il comando SysLog se hai errori di esecuzione?
    • Eventualmente puoi inviare il programma alla nostra eMail di supporto e proviamo a dare una occhiata.
    in risposta a: Errore acquisizione termocoppie #82088
    Sergio Bertana
    Amministratore del forum

    Strano comportamento, è tutto corretto anche i ponticelli sono corretti.

    I ponticelli degli ingressi non utilizzati li puoi lasciare inseriti.

    Hai provato ad eseguire solo il programma di acquisizione escludendo tutti gli altri?

    Hai provato ad abilitare i controlli Run-time?

Stai visualizzando 15 post - dal 76 a 90 (di 4,315 totali)