Vai al contenuto

Sergio Bertana

Risposte nei forum create

Stai visualizzando 15 post - dal 1 a 15 (di 4,232 totali)
  • Autore
    Post
  • 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?

    in risposta a: Errore acquisizione termocoppie #82061
    Sergio Bertana
    Amministratore del forum

    Quello che succede è molto strano, vediamo alcuni consigli…

    Il più importante di tutti è lo stato dei ponticelli, hai inserito LK4 e rimosso LK5 e LK6. Inoltre và rimossa la coppia di ponticelli per ogni ingresso analogico a cui connetti la termocoppia.

    Non dici in che task PLC viene eseguito il tuo programma, meglio è eseguirlo in task Back.

    Nel programma sposterei il controllo su variabile i prima di eseguire la GetAnInput come qui sotto. Perchè nel tuo programma quando arrivi dopo l’inizializzazione avrai i che punta la posizione dell’array successiva al numero definito andando così fuori array.

        i := (i+1);
        IF i > AN_INPUT_MAX_IDX THEN
            i := 0;
        END_IF;
    
        FB_GetAnInput[i]();

    Ho visto che iteri su tutti i canali quindi anche sul canale 4 che quando viene acquisita almeno una termocoppia non può essere utilizzato. Quindi sicuramente gestendolo con la GetAnInput avrai un errore 9983200 sul canale.

    Proverei ad eseguire il solo programma di acquisizione termocoppie escludendo tutti gli altri, per evitare che errori di accesso ad array e/o pointer possano agire sulle variabili del programma di acquisizione “sporcandole”. Dai una occhiata al capitolo Abilitare i controlli run-time programma nelle FAQ.

    in risposta a: How to use dynamic memory in a program #81909
    Sergio Bertana
    Amministratore del forum

    I partially correct what I said in my previous post. Even if in the the LogicLab there isn’t any NEW instruction It’s possible to bypass the obstacle by using the following approach. In the example the FB BlinkValue is instantiated on a SysMAlloc memory.

    VAR
        Blk : BlinkValue;
        PBlk : ARRAY[0..3] OF @BlinkValue;
    END_VAR
    
        // Allocates memory to instantiate FBs.
    
        IF (SysFirstLoop) THEN
            PBlk[0]:=SysMAlloc(SIZEOF(Blk));
            PBlk[1]:=SysMAlloc(SIZEOF(Blk));
            PBlk[2]:=SysMAlloc(SIZEOF(Blk));
        END_IF;
    
        // FBs executing.
    
        @PBlk[0].Enable:=TRUE;
        @PBlk[0].BlinkNr:=1;
        @PBlk[0]();
    
        @PBlk[1].Enable:=TRUE;
        @PBlk[1].BlinkNr:=2;
        @PBlk[1]();
    
        @PBlk[2].Enable:=TRUE;
        @PBlk[2].BlinkNr:=3;
        @PBlk[2]();

    As you see to get the size of the FB it’s necessary to instantiate it on a data memory, after that the SIZEOF operator can return its size.

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

    Aggiungo due esempi di programma per l’aggiornamento del tempo di lavoro dispositivi.

    Il primo esempio è più intuitivo ma “paga” l’errore del campionamento sul tempo di loop. In pratica ad ogni secondo si perde il tempo che trascorre tra il passaggio del secondo e quando il programma lo controlla

    VAR
        DOn : ARRAY[0..2] OF BOOL; (* Device attivo *)
        TTrig : R_TRIG; (* Time trigger *)
    END_VAR
    
        TTrig(CLK:=SysClock1000); //Time trigger
        IF NOT(TTrig.Q) THEN RETURN; END_IF;
    
        // Calcolo tempo dispositivi.
    
        IF (DOn[0]) THEN DWTime[0]:=DWTime[0]+1; END_IF;
        IF (DOn[1]) THEN DWTime[1]:=DWTime[1]+1; END_IF;
        IF (DOn[2]) THEN DWTime[2]:=DWTime[2]+1; END_IF;

    Il secondo esempio calcola il tempo senza errori.

    VAR
        DOn : ARRAY[0..2] OF BOOL; (* Device attivo *)
        SysTimeMs : UDINT; (* System time (mS) *)
        TimeDelay : UDINT; (* Time delay (mS) *)
        TimeBf : UDINT; (* Time buffer (mS) *)
    END_VAR
    
        // Eseguo inizializzazione.
    
        IF (SysFirstLoop) THEN
            TimeBf:=SysTimeGetMs(); //Time buffer (mS)
        END_IF;
    
        // Gestione base tempi.
    
        SysTimeMs:=SysTimeGetMs(); //System time (mS)
        TimeDelay:=SysTimeMs-TimeBf; //Time delay (mS)
        IF (TimeDelay < 1000) THEN RETURN; END_IF;
        TimeBf:=SysTimeMs-(TimeDelay-1000); //Time buffer (mS)
    
        // Calcolo tempo dispositivi.
    
        IF (DOn[0]) THEN DWTime[0]:=DWTime[0]+1; END_IF;
        IF (DOn[1]) THEN DWTime[1]:=DWTime[1]+1; END_IF;
        IF (DOn[2]) THEN DWTime[2]:=DWTime[2]+1; END_IF;
    in risposta a: Computo ore funzionamento dispositivi con FB TimeBalancing #81865
    Sergio Bertana
    Amministratore del forum

    La funzione principale del FB TimeBalancing è il comando di dispositivi in base alle ore di funzionamento, settando il numero di bits in DRequest in base al numero di dispositivi da comandare il FB comanda i dispositivi con meno ore attivando i relativi bits in DCommand.

    Ma settando i bits in DForce è possibile comandare il relativo dispositivo, indipendentemente dalle sue ore di funzionamento. Alla attivazione di un bit in DForce se il relativo bit in DEnable è attivo il relativo bit in DCommand si attiva. In questo modo è possibile gestire il comando manuale dei dispositivi. Le ore di funzionamento del dispositivo sono conteggiate anche sul comando manuale.

    Quindi venendo alla tua necesità, non vedo perchè tu debba utilizzare ulteriori ingressi logici per leggere lo stato del contatore, quando puoi semplicemente gestire i bits in DForce per il comando delle pompe in manuale.

    Ma se proprio vuoi prenderti questa “rogna” ti basterà realizzare un programma che sull’attivazione del relativo ingresso logico ad ogni secondo esegue l’incremento del valore del tempo nell’array definito in DWTime alla posizione relativa al dispositivo.

    in risposta a: How to use dynamic memory in a program #81830
    Sergio Bertana
    Amministratore del forum

    On LogicLab programmable systems we provide two ways to allocate dynamic memory, in the allocated memory buffer it’s possible to store any kind of data but it’s not possible to instantiate FBs. The LogicLab compiler istantiates FBs only in data memory area.

    SysMAlloc: This function allocate static dynamic memory and returns its address. There’s a dedicated RAM area on wich the function operates, this area is cleaned at program starting, the function reserves the defined size of memory and returns its address. The allocated area cannot be removed, it still allocated until a the program stops.

    SysRMAlloc: This function allocate relocatable dynamic memory and returns its address on a pointer variable. Calling the function if the desired space of memory is available it’s cleaned and the address is saved in the defined buffer. By calling SysRMFree function the buffer is released so the memory can be reused. A proprietary garbage collector operates on the memory moving allocated buffers recovering free spaces optimizing memory use. For this reason the returned address can change during program execution and it’s necessary refer to it anytime before to use it.

    So you cannot store FBs on relocatable memory, but if your own FBs use large amount of data for store variable or strings you can use SysRMalloc to create space for them on relocatable memory and freee the space after use. Many of our FBs use this technique to save memory, for example FIFOFile can be set to use dynamic memory to store the file. Since the file on the memory must be used for ever the SysRMalloc is used to allocate it.

    In the ST_SendFileByEMail example program the SysRMAlloc function is used to allocate space to save the email body, when the eMail is sent the used memory can be relased.

    in risposta a: Acquisizione sensore analogico con dispositivo STE2 #81821
    Sergio Bertana
    Amministratore del forum

    Sì, è possibile acquisire qualsiasi sensore con interfaccia 4-20mA attraverso l’utilizzo di questo convertitore 4-20mA/1Wire.

    Il convertitore è dotato di doppia interfaccia 1-Wire e, in tal modo, permette la connessione Daisy-chain evitando di impegnare un porta 1-Wire di STE2 R2.

    Per il set-up è richiesto l’utilizzo del calibratore 1-Wire UNI USB, che permette di abbinare al valore dell’ingresso analogico il corrispondente valore dell’unità ingegneristica acquisita.

    in risposta a: Problemi su aggiornamento firmware SlimLine Cortex M7 #81796
    Sergio Bertana
    Amministratore del forum

    Il software è relativo alla architettura XTarget12 ed è molto datato, in quella versione di firmware non era utilizzato il file system di tipo FAT quindi le directories erano predefinite come vedi dallo screenshot di FileZilla. E non era possibile creare nuove directories, ecco perchè il comando MKD non funziona.

    Quindi per eseguire l’upgrade di quel sistema devi necessariamente eseguirlo da porta seriale o USB seguendo le informazioni riportate nella pagina di upgrade quindi non puoi eseguirlo da remoto ma solo da locale. Come detto l’upgrade alla nuova versione di firmware trasforma il file system in FAT. Terminato l’upgrade occorre eseguire il comando di Format sia sul disco C: che D: se presente. Attenzione il comando cancellerà tutti i dati presenrti sul disco quindi se hai dati utili esegui un download con FileZilla prima di iniziare la procedura di upgrade. Avendo eseguito il format verrà persa la configurazione, il sistema non avrà più l’indirizzo IP definito ma si imposterà in DHCP client. Ecco le operazioni da eseguire:

    Nell’eseguire l’upgrade hai 2 possibilità.

    Mantenere l’architettura XTarget12: In questo modo hai la completa compatibilità del programma sviluppato. Ecco le operazioni da eseguire:

    • Esegui il download dalla pagina di upgrade del firmware per architettura XTarget12.
    • Esegui l’upgrade del sistema da porta seriale o da USB.
    • Esegui il comando di Format sia sul disco C: che D: se presente.
    • Utilizza la procedura di Discoverer per impostare l’indirizzo IP.
    • Da connessione telnet con Toolly esegui il comando Cfgcommit -d per reimpostare il tutto a default.
    • Utilizzando un client FTP esegui l’upgrade delle pagine web.
    • Utilizzando un client FTP crea le eventuali tue cartelle e ricarica gli eventuali files precedentemente salvati.
    • Ora potrai collegare LogicLab al sistema, ricompilare e ricaricare il tuo programma.

    Passare ad architettura XUnified: In questo modo hai l’aggiornamento alla versione più aggiornata del sistema operativo. Ecco le operazioni da eseguire:

    • Esegui il download dalla pagina di upgrade del firmware per architettura XUnified.
    • Esegui l’upgrade del sistema da porta seriale o da USB.
    • Esegui il comando di Format sia sul disco C: che D: se presente.
    • Utilizza la procedura di Discoverer per impostare l’indirizzo IP.
    • Da connessione telnet con Toolly esegui il comando Cfgcommit -d per reimpostare il tutto a default.
    • Utilizzando un client FTP esegui l’upgrade delle pagine web.
    • Utilizzando un client FTP crea le eventuali tue cartelle e ricarica gli eventuali files precedentemente salvati.
    • Per mantenere la compatibilità con il tuo programma (Vedi articolo) dovrai modificare il tuo progetto LogicLab utilizzando la raccolta librerie.
    • Dal menù Project – Library manager inserire nel progetto la libreria eLLabXUnifiedAdjLib. La trovi nella raccolta.
    • Ora potrai collegare LogicLab al sistema, ricompilare e ricaricare il tuo programma.
    in risposta a: Information about eTO_JUNK() instruction #81781
    Sergio Bertana
    Amministratore del forum

    The IEC 61131 norm requires that all functions have a return value and that the return value must transferred to a variable of the same type.

    This forces to define variables only to store the return values ​​from the functions even if these values ​​are not useful in the development of the program.

    The eTO_JUNK instruction (Present in the library package version from PCK055A030) allows to discard the return value of the functions without generating warnings or compilation errors.

Stai visualizzando 15 post - dal 1 a 15 (di 4,232 totali)