Funzioni ed FB di utilità generale ---------------------------------- BLINK, blink command ^^^^^^^^^^^^^^^^^^^^^^^ |image0| +----------+------------------+ | **Type** | **Library** | | | | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione gestisce una uscita lampeggiante con tempo di ciclo definibile. Attivando l'ingresso **ENABLE** l'uscita **OUT** inizia a lampeggiare con tempi di ciclo alto e basso definiti. +-----------------------------------+-----------------------------------+ | **ENABLE** (BOOL) | Abilitazione blocco funzione, | | | attivandolo viene gestita | | | l'uscita OUT lampeggiante. | | | Disattivandolo l'uscita OUT viene | | | resettata. | +-----------------------------------+-----------------------------------+ | **TIMELOW** (UDINT) | Definisce il tempo in cui | | | l'uscita OUT rimane nello stato | | | logico low, espresso in mS. | +-----------------------------------+-----------------------------------+ | **TIMEHIGH** (UDINT) | Definisce il tempo in cui | | | l'uscita OUT rimane nello stato | | | logico high espresso in mS. | +-----------------------------------+-----------------------------------+ | **OUT** (BOOL) | Stato uscita lampeggiante. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene impostato un lampeggio con 100 mS di tempo On e 1000 mS di tempo Off. Attivando l'ingresso digitale **Di00M00** l'uscita digitale **Do00M00** lampeggia con i tempi definiti. Disattivando l'ingresso digitale **Di00M00** l'uscita digitale **Do00M00** si azzera immediatamente. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image3| | +-----------------------------------------------------------------------+ **Esempio LD** *(PTP14A100, LD_BLINK)* |image4| **Esempio IL** *(PTP14A100, IL_BLINK)* .. code-block:: none CAL FB_BLINK (\* Call the BLINK function block \*) LD Di00M00 ST FB_BLINK.ENABLE (\* Transfer the digital input to enable input \*) LD 1000 ST FB_BLINK.TIMELOW (\* Set the time low \*) LD 100 ST FB_BLINK.TIMEHIGH (\* Set the time high \*) LD FB_BLINK.OUT ST Do00M00 (\* Copy FB output to logic output \*) **Esempio ST** *(PTP14A100, ST_BLINK)* FB_BLINK(TIMELOW:=1000, TIMEHIGH:=100); (\* Call the BLINK function block \*) FB_BLINK.ENABLE:=Di00M00; (\* Transfer the digital input to FB enable \*) Do00M00:=FB_BLINK.OUT; (\* Transfer the FB output to digital output \*) BlinkValue, blink out value ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image5| +----------+------------------+ | **Type** | **Library** | | | | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione gestisce una uscita lampeggiante con possibilità di definire il numero di lampeggi. Attivando l'ingresso **Enable** e definendo il numero di lampeggi in **BlinkNr**, l'uscita **OutBit** inizia a lampeggiare con il numero di lampeggi definito. Il numero di lampeggi è definito in decine ed unità, il valore delle decine è riportato con un lampeggio lento (1 Sec), mentre il numero delle unità è riportato con un lampeggio veloce (250 mS). Una pausa di 3 Sec separa le sequenze di lampeggio. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione blocco funzione, | | | attivandolo viene gestita | | | l'uscita **OutBit** lampeggiante. | | | Disattivandolo l'uscita viene | | | resettata. | +-----------------------------------+-----------------------------------+ | **BlinkNr** (USINT) | Definisce il numero di lampeggi | | | dell'uscita **OutBit**. Definendo | | | tempo 0 l'uscita si disattiva. | +-----------------------------------+-----------------------------------+ | **OutBit** (BOOL) | Stato uscita lampeggiante. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Attivando l'ingresso digitale **Di00M00** l'uscita digitale **Do00M00** lampeggia con 2 lampeggi lenti (1 Sec), 3 lampeggi veloci (250 mS) ed una pausa di 3 Sec. Disattivando l'ingresso digitale **Di00M00** l'uscita digitale **Do00M00** si azzera immediatamente. +--------------------------------------------------------------------------+ | **Definizione variabili** | +--------------------------------------------------------------------------+ | |image6| | +--------------------------------------------------------------------------+ **Esempio LD** *(PTP14A100, LD_BlinkValue)* |image7| **Esempio IL** *(PTP14A100, IL_BlinkValue)* .. code-block:: none CAL FBData (\* Call the "BlinkValue" function block \*) LD Di00M00 ST FBData.Enable (\* Transfer the digital input to enable input \*) LD 23 ST FBData.BlinkNr (\* Set the number of blink \*) LD FBData.OutBit ST Do00M00 (\* Copy FB output to logic output \*) **Esempio ST** *(PTP14A100, ST_BlinkValue)* FBData(BlinkNr:=23); (\* Call the BLINK function block \*) FBData.Enable:=Di00M00; (\* Transfer the digital input to FB enable \*) Do00M00:=FBData.OutBit; (\* Transfer the FB output to digital output \*) ModbusMaster, modbus master ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image8| +----------+------------------+ | **Type** | **Library** | | | | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione esegue la gestione del protocollo modbus master, con **Type** è possibile selezionare il tipo di protocollo RTU, Ascii ed over IP. Con **File** è possibile definire il terminale di I/O su cui effettuare la comunicazione. Attivando **Enable** sul terminale di I/O viene inviato un frame per eseguire la funzione modbus definita in **Fcode** sul nodo definito in Node. Terminata l'esecuzione del comando viene attivata l'uscita **Done**. Se l'esecuzione comando ha esito positivo si attiva per un loop di programma l'uscita **Ok**. Disattivando **Enable** si azzera **Done** e l'eventuale **Fault**, per eseguire nuovamente il comando occorre riabilitare l'ingresso **Enable**. L'ingresso **SpyOn** se attivo permette di spiare il funzionamento della FB. Se **FCode** è una funzione di lettura, il valore delle variabili a partire dall'indirizzo definito in **Address** per il numero di variabili definito da **Points**, viene letto dal sistema slave e trasferito nelle variabili indirizzate da **Buffer**. Se **FCode** è una funzione di scrittura, il valore delle variabili presenti nel buffer di memoria indirizzato da **Buffer** per il numero di variabili definito da **Points**, è inviato al dispositivo slave che lo trasferirà nelle sue variabili a partire dall'indirizzo definito in **Address**. In caso di errore esecuzione o tempo di esecuzione comando superiore al tempo definito in **Timeout**, viene attivata per un loop di programma l'uscita **Fault** ed incrementato il valore in **Errors**. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Comando abilitazione esecuzione | | | comando modbus. Per rieseguire il | | | comando disabilitare e poi | | | riabilitare questo ingresso. | +-----------------------------------+-----------------------------------+ | **SpyOn** (BOOL) | Se attivo permette di spiare il | | | funzionamento della FB. | +-----------------------------------+-----------------------------------+ | **File** (FILEP) | Flusso dati **stream** ritornato | | | dalla funzione **Sysfopen**. | +-----------------------------------+-----------------------------------+ | **Type** (USINT) | Tipo di protocollo modbus. 0:RTU, | | | 1:Ascii, 2:TCP | +-----------------------------------+-----------------------------------+ | **Node** (USINT) | Numero di nodo modbus su cui | | | effettuare il comando (Range da 0 | | | a 255). | +-----------------------------------+-----------------------------------+ | **FCode** (USINT) | Codice funzione modbus da | | | eseguire nel comando (Range da 0 | | | a 255). | | | | | | | 16#01: | | | | Read coil status (Massimo 250 | | | coils. | | | | | | | 16#02: | | | | Read input status (Massimo 125 | | | inputs | | | | | | | 16#03: | | | | Read holding registres (Massimo | | | 125 registri) | | | | | | | 16#04: | | | | Read input registers (Massimo | | | 125 registri) | | | | | | | 16#05: | | | | Force single coil | | | | | | | 16#06: | | | | Preset single register | | | | | | | 16#0: | | | | Force multiple coils (Massimo | | | coils) | | | | | | | 16#10: | | | | Preset multiple registers | | | (Massimo 32 registri) | | | | | | | 16#41: | | | | Read memory bytes (User | | | function) (Massimo 250 bytes) | | | | | | | 16#42: Write memory | | | | Write memomry bytes (User | | | function) (Massimo 250 bytes) | | | | +-----------------------------------+-----------------------------------+ | **Address** (UINT) | Indirizzo di allocazione | | | variabili su sistema slave. In | | | accordo alle specifiche modbus | | | l'indirizzo inviato nel frame | | | dati è (**Address-1**) (Range da | | | 16#0001 a 16#FFFF). | +-----------------------------------+-----------------------------------+ | **Points** (USINT) | Numero di variabili consecutive | | | su cui opera il comando. | +-----------------------------------+-----------------------------------+ | **Buffer** (@USINT) | Indirizzo buffer dati letti o da | | | scrivere. | +-----------------------------------+-----------------------------------+ +-----------------------------------+-----------------------------------+ | **IFTime** (UDINT) | Tempo ricezione caratteri (μS), | | | se comunicazione su porta seriale | | | il tempo deve essere definito in | | | base al baud rate. Nel caso di | | | comunicazione su rete ethernet è | | | possibile definire il valore | | | minimo. | | | | | | | 300 Baud - 112000 (uS) | | | | 600 Baud - 56000 (uS) | | | | 1200 Baud - 28000 (uS) | | | | 2400 Baud - 14000 (uS) | | | | 4800 Baud - 7000 (uS) | | | | 9600 Baud - 3430 (uS) | | | | 19200 Baud - 1720 (uS) | | | | 38400 Baud - 860 (uS) | | | | 57600 Baud - 573 (uS) | | | | 76800 Baud - 429 (uS) | | | | 115200 Baud - 286 (uS) | +-----------------------------------+-----------------------------------+ | **Timeout** (UINT) | Tempo massimo esecuzione comando | | | espresso in mS. Se il comando non | | | termina nel tempo definito viene | | | abortito ed attivata l'uscita | | | **Fault**. | +-----------------------------------+-----------------------------------+ | **Delay** (UINT) | Tempo di pausa dopo l'esecuzione | | | del comando modbus espresso in | | | mS. | +-----------------------------------+-----------------------------------+ | **Done** (BOOL) | Si attiva al termine della | | | esecuzione comando. | +-----------------------------------+-----------------------------------+ | **Ok** (BOOL) | Attivo per un loop se esecuzione | | | comando corretta. | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo per un loop se errore | | | esecuzione comando. | +-----------------------------------+-----------------------------------+ | **Errors** (UDINT) | Numero di errori, incrementato ad | | | ogni nuovo errore, raggiunto | | | valore massimo riparte da 0. | +-----------------------------------+-----------------------------------+ **Trigger di spy** Se **SpyOn** attivo viene eseguita la funzione `SysSpyData <#FctSysSpyData>`__ che permette di spiare il funzionamento della FB. Sono previsti vari livelli di triggers. +-------------+------------------------------------------+ | **TFlags** | **Descrizione** | +-------------+------------------------------------------+ | 16#00000001 | **Tx:** Invio frame comando modbus. | +-------------+------------------------------------------+ | 16#00000002 | **Rx:** Ricezione frame risposta modbus. | +-------------+------------------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +-----------------------------------+-----------------------------------+ | 10007010 | Valore di **File** non definito. | +-----------------------------------+-----------------------------------+ | 10007050 | Timeout esecuzione. | +-----------------------------------+-----------------------------------+ | 10007060 | Errore esecuzione. | +-----------------------------------+-----------------------------------+ | 10007080 | Errore definizione **Type**. | +-----------------------------------+-----------------------------------+ | 10007100 | Codice funzione definito in | | | **Function** non gestito. | +-----------------------------------+-----------------------------------+ | 10007120 | Valore di **Points** errato. | +-----------------------------------+-----------------------------------+ | 10007200~2 | Errore trasmissione frame | | | comando. | +-----------------------------------+-----------------------------------+ | 10007500~7 | Errore in ricezione frame | | | risposta (Carattere errato, | | | lunghezza errata, CRC). | +-----------------------------------+-----------------------------------+ **Esempi Modbus master su seriale** Viene presentato un esempio di lettura da un sistema SlimLine slave. Viene eseguita la lettura di 8 registri a partire da indirizzo 40000 dal nodo modbus 1. Il valore dei registri letti è trasferito nell'array **RxData**. Terminata la lettura si attiverà per un loop l'uscita logica **Done**. +--------------------------------------------------------------------+ | **Definizione variabili** | +--------------------------------------------------------------------+ | VAR | | | | RxData : ARRAY[ 0..7 ] OF UINT; (\* Rx data buffer \*) | | | | Mdb : ModbusMaster; (\* Modbus master FB \*) | | | | Serial : SysSerialPort; (\* Serial port \*) | | | | END_VAR | +--------------------------------------------------------------------+ | **Esempio FBD** *(PTP114A670, FBD_ModbusMasterSerial)* | +--------------------------------------------------------------------+ | |image9| | +--------------------------------------------------------------------+ **Esempio ST** *(PTP114A660, ST_ModbusMaster)* .. code-block:: none (\* Program initialization. \*) IF (SysFirstLoop) THEN (\* Serial port initialization. \*) Serial.COM:=ADR('COM0'); (\* COM port definition \*) Serial.Baudrate:=9600; (\* Baudrate \*) Serial.Parity:='N'; (\* Parity \*) Serial.DataBits:=8; (\* Data bits \*) Serial.StopBits:=1; (\* Stop bits \*) Serial.DTRManagement:=DTR_AUTO_WO_TIMES; (\* DTR management \*) Serial.DTRComplement:=FALSE; (\* DTR complement \*) Serial.EchoFlush:=FALSE; (\* Received echo flush \*) Serial.DTROnTime:=0; (\* DTR On time delay (mS) \*) Serial.DTROffTime:=0; (\* DTR Off time delay (mS) \*) Serial.FlushTm:=0; (\* Flush time (mS) \*) Serial.RxSize:=0; (\* Rx buffer size \*) Serial.TxSize:=0; (\* Tx buffer size \*) (\* Modbus master initialization. \*) Mdb.SpyOn:=TRUE; (\* Spy On \*) Mdb.Type:=0; (\* Modbus type \*) Mdb.Node:=1; (\* Device modbus node \*) Mdb.FCode:=16#03; (\* Modbus function code \*) Mdb.Address:=4000; (\* Modbus register address \*) Mdb.Points:=8; (\* Modbus register points \*) Mdb.Buffer:=ADR(RxData); (\* Memory buffer address \*) Mdb.IFTime:=3430; (\* Interframe time (uS) \*) Mdb.Timeout:=500; (\* Timeout time (mS) \*) Mdb.Delay:=100; (\* Delay time (mS) \*) END_IF; (\* Manage the modbus master communication. \*) Serial(Open:=TRUE); (\* Serial port management \*) Mdb.File:=Serial.File; (\* File pointer \*) Mdb(); (\* Modbus master \*) Mdb.Enable:=Serial.Opened AND NOT(Mdb.Done); (\* Modbus enable \*) **Esempi Modbus master su TCP** Ecco come si presenta lo stesso esempio di prima utilizzando una connessione TCP verso un'altro sistema SlimLine. Nel campo **PeerAdd** è possibile definire un URL al posto dell'indirizzo IP. +--------------------------------------------------------+ | **Definizione variabili** | +--------------------------------------------------------+ | VAR | | | | RxData : ARRAY[ 0..7 ] OF UINT; (\* Rx data buffer \*) | | | | Mdb : ModbusMaster; (\* Modbus master FB \*) | | | | TCPClient : SysTCPClient; (\* Client connection \*) | | | | END_VAR | +--------------------------------------------------------+ **Esempio FBD** *(PTP114A670, FBD_ModbusMasterTCP)* |image10| ModbusSlave_v1, modbus slave ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image11| +----------+------------------+ | **Type** | **Library** | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Sui sistemi SlimLine il protocollo modbus slave è già implementato dal sistema operativo, pertanto non occorre inserire blocchi funzione appositi nel programma utente. Questo blocco esegue l'override della gestione di sistema operativo e si utilizza in casi particolari, dove non è possibile utilizzare la gestione implementata nel sistema operativo. Per esempio quando si vuole consentire l'accesso ad un propria area di memoria diversa dalla DB100. Questo blocco funzione esegue la gestione del protocollo modbus slave con **Type** è possibile selezionare il tipo di protocollo RTU, Ascii ed over IP. Con **File** è possibile definire il terminale di I/O su cui effettuare la comunicazione. Occorre definire il nodo modbus **Node**, e l'eventuale offset di indirizzo frame modbus **Offset**. I comandi modbus ricevuti operano sul buffer di memoria il cui indirizzo è definito in **Buffer** e la dimensione in bytes è definita in **Size**. In **IFTime** occorre definire il tempo di interframe dei comandi modbus, cioè il tempo che intercorre tra la ricezione di un comando ed il comando successivo. Su linea seriale questo tempo coincide con il tempo di ricezione di 3 caratteri al baud rate definito. Alla ricezione di ogni comando modbus corretto si attiva per un loop l'uscita **Done**, in caso di errore comando viene attivata per un loop l'uscita **Fault** ed incrementato il valore in **Errors**. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Comando di abilitazione blocco | | | funzione. | +-----------------------------------+-----------------------------------+ | **SpyOn** (BOOL) | Se attivo permette di spiare il | | | funzionamento della FB. | +-----------------------------------+-----------------------------------+ | **File** (FILEP) | Flusso dati **stream** ritornato | | | dalla funzione **Sysfopen**. | +-----------------------------------+-----------------------------------+ | **Type** (USINT) | Tipo di protocollo modbus. 0:RTU, | | | 1:Ascii, 2:TCP | +-----------------------------------+-----------------------------------+ | **Node** (USINT) | Numero di nodo modbus (Range da 0 | | | a 255). | +-----------------------------------+-----------------------------------+ | **Offset** (UINT) | Offset su indirizzo modbus | | | ricevuto nel frame dati (Range da | | | 16#0000 a 16#FFFF). | +-----------------------------------+-----------------------------------+ | **Buffer** (@USINT) | Indirizzo buffer dati su cui | | | operano i comandi modbus. | +-----------------------------------+-----------------------------------+ | **Size** (UDINT) | Dimensione in byte del buffer | | | dati su cui operano i comandi | | | modbus. | +-----------------------------------+-----------------------------------+ | **IFTime** (UDINT) | Tempo ricezione caratteri (μS), | | | se comunicazione su porta seriale | | | il tempo deve essere definito in | | | base al baud rate. Nel caso di | | | comunicazione su rete ethernet è | | | possibile definire il valore | | | minimo. | | | | | | | 300 Baud - 112000 (uS) | | | | 600 Baud - 56000 (uS) | | | | 1200 Baud - 28000 (uS) | | | | 2400 Baud - 14000 (uS) | | | | 4800 Baud - 7000 (uS) | | | | 9600 Baud - 3430 (uS) | | | | 19200 Baud - 1720 (uS) | | | | 38400 Baud - 860 (uS) | | | | 57600 Baud - 573 (uS) | | | | 76800 Baud - 429 (uS) | | | | 115200 Baud - 286 (uS) | | | | +-----------------------------------+-----------------------------------+ | **Done** (BOOL) | Attivo per un loop alla ricezione | | | di comando modbus. | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo per un loop su errore | | | ricezione comando modbus. | +-----------------------------------+-----------------------------------+ | **Errors** (UDINT) | Numero di errori riscontrati. | | | Viene incrementato ad ogni nuovo | | | errore, raggiunto il valore | | | massimo il conteggio riparte da | | | 0. | +-----------------------------------+-----------------------------------+ **Comandi supportati** Il blocco funzione supporta solo alcuni comandi previsti dal protocollo modbus, i comandi supportati sono: +------------+--------------------------------------------------------+ | **Codice** | **Descrizione** | +------------+--------------------------------------------------------+ | 16#01 | Read coil status (Massimo 250 coils) | +------------+--------------------------------------------------------+ | 16#02 | Read input status (Massimo 250 coils) | +------------+--------------------------------------------------------+ | 16#03 | Read holding registers (Massimo 125 registri) | +------------+--------------------------------------------------------+ | 16#04 | Read input registers (Massimo 125 registri) | +------------+--------------------------------------------------------+ | 16#05 | Force single coil | +------------+--------------------------------------------------------+ | 16#06 | Preset single register | +------------+--------------------------------------------------------+ | 16#08 | Loopback diagnostic test | +------------+--------------------------------------------------------+ | 16#0F | Force multiple coils (Massimo 250 coils) | +------------+--------------------------------------------------------+ | 16#10 | Preset multiple registers (Massimo 125 registri) | +------------+--------------------------------------------------------+ | 16#41 | Read memory bytes (User function) (Massimo 250 bytes) | +------------+--------------------------------------------------------+ | 16#42 | Write memory bytes (User function) (Massimo 250 bytes) | +------------+--------------------------------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. In caso di eccezione su comando modbus viene riportato il codice di errore ma non viene attivata l'uscita **Fault**. +-----------------------------------+-----------------------------------+ | 10038010 | Valore di **File** non definito. | +-----------------------------------+-----------------------------------+ | 10038050 | Errore di timeout esecuzione. | +-----------------------------------+-----------------------------------+ | 10038060 | Errore esecuzione. | +-----------------------------------+-----------------------------------+ | 10038080 | Errore definizione **Type**. | +-----------------------------------+-----------------------------------+ | 10038100 | Modbus Ascii, ricevuto carattere | | | errato. | +-----------------------------------+-----------------------------------+ | 10038101 | Ricevuto frame troppo lungo. | +-----------------------------------+-----------------------------------+ | 10038102 | Modbus RTU, ricevuto frame troppo | | | corto. | +-----------------------------------+-----------------------------------+ | 10038103 | Modbus RTU, errore CRC nel frame | | | ricevuto. | +-----------------------------------+-----------------------------------+ | 10038104 | Modbus Ascii, manca in frame | | | ricevuto. | +-----------------------------------+-----------------------------------+ | 10038105 | Modbus Ascii, ricevuto frame | | | troppo corto. | +-----------------------------------+-----------------------------------+ | 10038106 | Modbus Ascii, errore LRC nel | | | frame ricevuto. | +-----------------------------------+-----------------------------------+ | 10038107 | Modbus TCP, ricevuto frame troppo | | | corto. | +-----------------------------------+-----------------------------------+ | 10038108 | Modbus TCP, protocol identifier | | | errato in frame ricevuto. | +-----------------------------------+-----------------------------------+ | 10038109 | Modbus TCP, length errato in | | | frame ricevuto. | +-----------------------------------+-----------------------------------+ | 10038110 | Richiesto numero di elementi | | | errato. | +-----------------------------------+-----------------------------------+ | 10038200~2 | Errore trasmissione frame | | | risposta. | +-----------------------------------+-----------------------------------+ | 10038501 | Eccezione 01.\ **Illegal | | | function**, comando ricevuto non | | | è tra quelli gestiti. | +-----------------------------------+-----------------------------------+ | 10038502 | Eccezione 02. **Illegal data | | | address**, comando ricevuto ha | | | indirizzo o numero dati fuori | | | range. | +-----------------------------------+-----------------------------------+ | 10038503 | Eccezione 03. **Illegal data | | | value**, comando ricevuto ha | | | campo dati fuori range. | +-----------------------------------+-----------------------------------+ | 10038504 | Eccezione 04.\ **Failure in | | | associated device**, comando | | | ricevuto contiene imprecisioni. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene gestito il protocollo modbus slave su porta seriale **COM0**. I comandi modbus possono agire sull'array di WORD **DArray**. +-----------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------+ | VAR | | | | Mdb : ModbusSlave_v1; (\* Modbus slave FB \*) | | | | Serial : SysSerialPort; (\* Serial port \*) | | | | DArray : ARRAY[ 0..31 ] OF WORD; (\* Modbus accessible area \*) | | | | END_VAR | +-----------------------------------------------------------------+ **Esempio FBD** *(PTP114A670, FBD_ModbusSlave_v1)* |image12| **Esempio ST** *(PTP114A670, ST_ModbusSlave_v1)* .. code-block:: none (\* Program initialization. \*) IF (SysFirstLoop) THEN (\* Serial port settings. \*) Serial.COM:=ADR('COM0'); (\* COM port definition \*) Serial.Baudrate:=9600; (\* Baudrate \*) Serial.Parity:='E'; (\* Parity \*) Serial.DataBits:=8; (\* Data bits \*) Serial.StopBits:=1; (\* Stop bits \*) Serial.DTRManagement:=DTR_AUTO_WO_TIMES; (\* DTR management \*) Serial.DTRComplement:=FALSE; (\* DTR complement \*) Serial.EchoFlush:=FALSE; (\* Received echo flush \*) Serial.DTROnTime:=0; (\* DTR On time delay (mS) \*) Serial.DTROffTime:=0; (\* DTR Off time delay (mS) \*) Serial.FlushTm:=0; (\* Flush time (mS) \*) Serial.RxSize:=0; (\* Rx buffer size \*) Serial.TxSize:=0; (\* Tx buffer size \*) (\* Modbus slave settings. \*) Mdb.SpyOn:=TRUE; (\* Spy On \*) Mdb.Type:=0; (\* Modbus type \*) Mdb.Node:=1; (\* Device modbus node \*) Mdb.Offset:=1000; (\* Modbus address offset \*) Mdb.Buffer:=ADR(DArray); (\* Modbus buffer address \*) Mdb.Size:=SIZEOF(DArray); (\* Modbus buffer size \*) Mdb.IFTime:=3430; (\* Interframe time (uS) \*) END_IF; (\* Manage the modbus slave. \*) Serial(Open:=TRUE); (\* Serial port management \*) Mdb.File:=Serial.File; (\* File pointer \*) Mdb(Enable:=Serial.Opened); (\* Modbus slave \*) ModbusCon version, Modbus Ascii/RTU conversion ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image13| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | FB | eLLabUtyLib_C050 | +-----------------------+-----------------------+ Questo blocco funzione esegue la conversione di protocollo tra il Modbus Ascii ed il Modbus RTU. Il protocollo Ascii ricevuto dallo stream **FpAscii** viene convertito in RTU e trasmesso sullo stream **FpRTU** e viceversa. E' quindi possibile connettendo due porte seriali fare dialogare tra di loro due sistemi che utilizzano i due tipi di protocollo. In **IFTime** occorre definire il tempo di interframe dei comandi modbus, cioè il tempo che intercorre tra la ricezione di un comando ed il comando successivo. Su linea seriale questo tempo coincide con il tempo di ricezione di 3 caratteri al baud rate definito. I frames modbus ricevuti vengono controllati verificando il LRC per i frame Ascii ed il CRC per i frames RTU. In caso di errore comando viene attivata per un loop l'uscita **Fault**. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Comando di abilitazione blocco | | | funzione. | +-----------------------------------+-----------------------------------+ | **SpyOn** (BOOL) | Se attivo permette di spiare il | | | funzionamento della FB. | +-----------------------------------+-----------------------------------+ | **FpAscii** (FILEP) | Flusso dati **stream** per la | | | gestione del protocollo Modbus | | | Ascii. | +-----------------------------------+-----------------------------------+ | **FpRTU** (FILEP) | Flusso dati **stream** per la | | | gestione del protocollo Modbus | | | RTU. | +-----------------------------------+-----------------------------------+ | **IFTime** (UDINT) | Tempo ricezione caratteri (μS), | | | se comunicazione su porta seriale | | | il tempo deve essere definito in | | | base al baud rate. Nel caso di | | | comunicazione su rete ethernet è | | | possibile definire il valore | | | minimo. | | | | | | | 300 Baud - 112000 (uS) | | | | 600 Baud - 56000 (uS) | | | | 1200 Baud - 28000 (uS) | | | | 2400 Baud - 14000 (uS) | | | | 4800 Baud - 7000 (uS) | | | | 9600 Baud - 3430 (uS) | | | | 19200 Baud - 1720 (uS) | | | | 38400 Baud - 860 (uS) | | | | 57600 Baud - 573 (uS) | | | | 76800 Baud - 429 (uS) | | | | 115200 Baud - 286 (uS) | +-----------------------------------+-----------------------------------+ | **Enabled** (BOOL) | Attivo se blocco funzione | | | abilitato. | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo per un loop su errore | | | ricezione comando modbus. | +-----------------------------------+-----------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +------------+----------------------------------------------+ | 10069010 | Valore di **FpAscii** non definito. | +------------+----------------------------------------------+ | 10069011 | Valore di **FpRTU** non definito. | +------------+----------------------------------------------+ | 10069020 | Valore di **IFTime** non definito. | +------------+----------------------------------------------+ | 10069100 | Modbus Ascii, timeout conversione. | +------------+----------------------------------------------+ | 10069110 | Modbus Ascii, ricevuto carattere errato. | +------------+----------------------------------------------+ | 10069150 | Modbus Ascii, ricevuto frame troppo lungo. | +------------+----------------------------------------------+ | 10069160 | Modbus Ascii, frame non termina con . | +------------+----------------------------------------------+ | 10069170 | Modbus Ascii, ricevuto frame troppo corto. | +------------+----------------------------------------------+ | 10069180 | Modbus Ascii, errore LRC nel frame ricevuto. | +------------+----------------------------------------------+ | 10069200 | Modbus Ascii, errore trasmissione frame RTU. | +------------+----------------------------------------------+ | 10069300 | Modbus RTU, timeout conversione. | +------------+----------------------------------------------+ | 10069350 | Modbus RTU, ricevuto frame troppo lungo. | +------------+----------------------------------------------+ | 10069370 | Modbus RTU, ricevuto frame troppo corto. | +------------+----------------------------------------------+ | 10069380 | Modbus RTU, errore CRC nel frame ricevuto. | +------------+----------------------------------------------+ | 10069400~5 | Modbus RTU, errore trasmissione frame Ascii. | +------------+----------------------------------------------+ **Esempi** """"""""""" Viene gestita la conversione tra il protocollo Modbus Ascii ricevuto sulla porta seriale COM0 a **19200, e, 8, 1** ed protocollo Modbus RTU sulla porta seriale COM1 a **115200, e, 8, 1**. +---------------------------+ | **Definizione variabili** | +---------------------------+ | |image14| | +---------------------------+ **Esempio LD** *(PTP114A660, LD_ModbusConversion)* |image15| OnOffCycl e_v1, on/off cycle with random times ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image16| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | FB | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questo blocco funzione esegue la temporizzazione di un ciclo On/Off con tempi random di On e di Off definibili tra valori minimo e massimo. Il massimo valore di tempo gestito è di oltre 1193 ore. Attivando il comando di **Enable** l'uscita **Out** esegue un lampeggio On/Off con tempi random compresi tra i valori minimo e massimo definiti. Disabilitando l'ingresso l'uscita **Out** si disattiva. La variabile **Delay** ritorna il valore di ritardo attualmente attivo, mentre in Time è ritornato il countdown del tempo. Impostando 0 nei tempi Min e Max si ottiene una uscita impulsiva (Un loop) sulla relativa temporizzazione. Su attivazione abilitazione viene calcolato il tempo di delay random, quindi è possibile disabilitare il FB su attivazione uscita per avere una nuova temporizzazione di Off. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Comando di abilitazione. | +-----------------------------------+-----------------------------------+ | **MinOffTime** (UDINT) | Valore minimo di tempo off | | | comando (mS). | +-----------------------------------+-----------------------------------+ | **MaxOffTime** (UDINT) | Valore massimo di tempo off | | | comando (mS). | +-----------------------------------+-----------------------------------+ | **MinOnTime** (UDINT) | Valore minimo di tempo on comando | | | (mS). | +-----------------------------------+-----------------------------------+ | **MaxOnTime** (UDINT) | Valore massimo di tempo on | | | comando (mS). | +-----------------------------------+-----------------------------------+ | **Out** (BOOL) | Stato comando On/Off in uscita. | +-----------------------------------+-----------------------------------+ | **Delay** (UDINT) | Valore di tempo attualmente in | | | temporizzazione (mS). | +-----------------------------------+-----------------------------------+ | **Time** (UDINT) | Countdown tempo in | | | temporizzazione (mS). | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene eseguito il lampeggio della uscita **Do00M00** con tempi random variabili tra i 2 ed i 4 secondi. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image19| | +-----------------------------------------------------------------------+ **Esempio LD** *(PTP114A640, LD_OnOffCycle_v1)* |image20| **Esempio IL** *(PTP114A640, IL_OnOffCycle_v1)* .. code-block:: none CAL FBData (\* Call the ONOFFCYCLE function block \*) LD Di00M00 ST FBData.Enable (\* Transfer the digital input to Enable input \*) LD 2000 ST FBData.MinOffTime (\* Set the minimum off time \*) LD 4000 ST FBData.MaxOffTime (\* Set the maximum off time \*) LD 2000 ST FBData.MinOnTime (\* Set the minimum on time \*) LD 4000 ST FBData.MaxOnTime (\* Set the maximum on time \*) LD FBData.Out ST Do00M00 (\* Copy the Out value to logic output \*) LD FBData.Delay ST VarOut (\* The Delay time is copied to variable \*) **Esempio ST** *(PTP114A640, ST_OnOffCycle_v1)* .. code-block:: none FBData(); (\* Call the ONOFFCYCLE function block \*) FBData.Enable:=Di00M00; (\* Transfer the digital input to Enable input \*) FBData.MinOffTime:=2000; (\* Set the minimum off time \*) FBData.MaxOffTime:=4000; (\* Set the maximum off time \*) FBData.MinOnTime:=2000; (\* Set the minimum on time \*) FBData.MaxOnTime:=4000; (\* Set the maximum on time \*) Do00M00:=FBData.Out; (\* Copy the Out value to logic output \*) VarOut:=FBData.Delay; (\* The Delay time is copied to variable \*) PIDMng_v1, PID management ^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image21| +----------+------------------+ | **Type** | **Library** | | | | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione esegue la regolazione PID. E' prevista la possibilità di abilitare singolarmente i vari tipi di azione (**P**)roporzionale (**I**)ntegrativa, (**D**)erivativa. Un comando di **Reverse** permette di invertire il segno del segnale in uscita **Out**. Nella versione (v1) sono stati inseriti i due ingressi **OMin** e **OMax** per la definizione del valore minimo e massimo in uscita dalla regolazione. +-----------------------------------+-----------------------------------+ | **PIDEnable** (BOOL) | Abilitazione regolazione PID, | | | attivando l'ingresso si abilita | | | la regolazione. Disattivando | | | l'ingresso si azzera il valore in | | | uscita **Out**. | +-----------------------------------+-----------------------------------+ | **IEnable** (BOOL) | Abilitazione regolazione | | | integrativa, attivando l'ingresso | | | si abilita la regolazione | | | integrativa. | +-----------------------------------+-----------------------------------+ | **DEnable** (BOOL) | Abilitazione regolazione | | | derivativa, attivando l'ingresso | | | si abilita la regolazione | | | derivativa. | +-----------------------------------+-----------------------------------+ | **Reverse** (BOOL) | Inversione segno su valore in | | | uscita **Out**. | +-----------------------------------+-----------------------------------+ | **SetPoint** (REAL) | Set point, il valore è espresso | | | nell'unità di misura del processo | | | da controllare. | +-----------------------------------+-----------------------------------+ | **PValue** (REAL) | Valore acquisito dal processo, il | | | valore è espresso nell'unità di | | | misura del processo da | | | controllare. | +-----------------------------------+-----------------------------------+ | **PBand** (REAL) | Banda proporzionale, questo | | | valore definisce il valore di | | | errore oltre al quale la | | | regolazione viene disabilitata | | | forzando l'uscita **Out** al | | | massimo **±100%**. Il valore è | | | espresso nell'unità di misura del | | | processo da controllare. | +-----------------------------------+-----------------------------------+ | **ST** (REAL) | Tempo di scansione, occorre | | | impostare il tempo in cui si | | | desidera vengano eseguite le | | | regolazioni integrativa e | | | derivativa se abilitate, il | | | valore è in **mS**. | +-----------------------------------+-----------------------------------+ | **KP** (REAL) | Costante proporzionale, si | | | ricorda che più è elevato il | | | valore più è pronta è la | | | regolazione con un conseguente | | | aumento del valore di overshot. | | | Il valore è un numero. | +-----------------------------------+-----------------------------------+ | **IT** (REAL) | Tempo integrativo, si ricorda che | | | più è elevato il valore meno è | | | veloce la regolazione integrativa | | | a recuperare l'errore. Il valore | | | è espresso in **Sec**. | +-----------------------------------+-----------------------------------+ | **DT** (REAL) | Tempo derivativo, si ricorda che | | | più è elevato il valore più è | | | veloce la regolazione derivativa | | | a recuperare l'errore. Il valore | | | è espresso in **Sec**. | +-----------------------------------+-----------------------------------+ | **OMin** (REAL) | Valore minimo dell'uscita PID Il | | | valore è espresso in **%**. | +-----------------------------------+-----------------------------------+ | **OMax** (REAL) | Valore massimo dell'uscita PID Il | | | valore è espresso in **%**. | +-----------------------------------+-----------------------------------+ | **Enabled** (BOOL) | Regolazione PID abilitata. | +-----------------------------------+-----------------------------------+ | **Error** (BOOL) | Errore nella esecuzione. | +-----------------------------------+-----------------------------------+ | **OUT** (REAL) | Valore di correzione in uscita | | | dalla regolazione PID. Questo | | | valore deve essere utilizzato per | | | il comando del processo. Il | | | valore è espresso in **%**. | +-----------------------------------+-----------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Error**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +----------+----------------------------------------+ | 10012050 | Non è stato definito valore di **ST**. | +----------+----------------------------------------+ **Esempi** """"""""""" Nell'esempio è gestita una regolazione di temperatura su di un termoriscaldatore. Viene acquisita la sonda di temperatura da una Pt100 e viene gestita una uscita PWM **Do00M00** per il comando. Le costanti del loop PID sono allocate in memoria backup e sono mantenute allo spegnimento, inoltre sono accessibili da modbus. +------------------------------------------+ | **Definizione variabili** | +------------------------------------------+ | |image22| | +------------------------------------------+ **Esempio LD** *(PTP114A100, LD_PIDMng)* |image23| PWMOut, PWM output management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image24| +----------+------------------+ | **Type** | **Library** | | | | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione esegue la gestione di una uscita PWM. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione gestione uscita PWM, | | | attivando l'ingresso si abilita | | | la gestione. Disattivando | | | l'ingresso si azzera l'uscita | | | **Out**. | +-----------------------------------+-----------------------------------+ | **SET** (REAL) | Valore di set PWM, il valore è | | | espresso in **%**. | +-----------------------------------+-----------------------------------+ | **TCycle** (REAL) | Tempo di di ciclo PWM, il valore | | | è espresso in **S**. | +-----------------------------------+-----------------------------------+ | **TMin** (REAL) | Tempo minimo comando uscita | | | **Out**, il valore è espresso in | | | **S**. | +-----------------------------------+-----------------------------------+ | **Out** (BOOL) | Uscita PWM. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Nell'esempio è gestita una uscita PWM definendo un tempo di ciclo di 5 secondi con un tempo minimo di 0.5 secondi. Impostando come set point il valore 50% attivando l'ingresso **Di00M00** avremo che l'uscita **Do00M00** sarà attivata per 2.5 secondi e disattivata per 2,5 secondi. +------------------------------------------+ | **Definizione variabili** | +------------------------------------------+ | |image25| | +------------------------------------------+ **Esempio LD** *(PTP114A100, LD_PWMOut)* |image26| SysDMXMng, DMX management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image27| +----------+--------------+ | **Type** | **Library** | | | | +----------+--------------+ | FB | XTarget_07_0 | +----------+--------------+ Questo blocco funzione esegue la gestione del protocollo DMX, questo è un blocco funzione protetto per utilizzarlo occorre richiedere il codice di protezione, vedi `protezione funzioni e blocchi funzione <#ChpFctFBProtection>`__. E' comunque possibile utilizzarlo liberamente in modo test per 15 Min. Attivando l'ingresso di **Start** viene inviato sulla porta seriale identificata da **File** un frame DMX che inizia con il valore di **Status** e segue con il valore di preset dei dispositivi definiti da **Devices**. Il valore di preset dei vari dispositivi deve essere caricato in un array di dati il cui indirizzo è passato in **DataPtr**. Mantenendo sempre attivo l'ingresso **Start** verranno inviati consecutivamente frames DMX. Al termine dell'invio del comando DMX si attiverà per un loop di programma l'uscita **Done**. +-----------------------------------+-----------------------------------+ | **Start** (BOOL) | Comando di invio frame DMX su | | | porta seriale, si resetta | | | automaticamente all'invio del | | | frame. | +-----------------------------------+-----------------------------------+ | **File** (FILEP) | Flusso dati **stream** ritornato | | | dalla funzione **Sysfopen**. | +-----------------------------------+-----------------------------------+ | **Status** (USINT) | Valore byte di stato inviato nel | | | protocollo DMX prima dei byte di | | | preset dispositivi. | +-----------------------------------+-----------------------------------+ | **Devices** (UINT) | Numero di dispositivi connessi al | | | bus DMX. | +-----------------------------------+-----------------------------------+ | **Delay** (UINT) | Tempo di pausa trasmissione | | | frames DMX (mSec) | +-----------------------------------+-----------------------------------+ | **DataPtr** (@USINT) | Pointer all'array dati valori di | | | preset dispositivi DMX. | +-----------------------------------+-----------------------------------+ | **Done** (BOOL) | Attivo per un loop al termine | | | dell'invio frame DMX del comando | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo in caso di errore nella | | | gestione. | +-----------------------------------+-----------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +-----------------------------------+-----------------------------------+ | 9979050 | Errore allocazione blocco | | | funzione. | +-----------------------------------+-----------------------------------+ | 9979060 | Terminato spazio memoria | | | rilocabile, non è possibile | | | eseguire l''FB. | +-----------------------------------+-----------------------------------+ | 9979070 | Errore versione blocco funzione. | +-----------------------------------+-----------------------------------+ | 9979085 | FB protetta, terminato tempo | | | funzionamento in modo demo. | +-----------------------------------+-----------------------------------+ | 9979200 | Protocollo DMX non supportato dal | | | dispositivo definito in **File**. | +-----------------------------------+-----------------------------------+ | 9979990 | Non implementata nel simulatore. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Dovendo gestire puntatori a memoria è preferibile utilizzare il blocco funzione all'interno di un programma ST, nell'esempio viene attivato il protocollo DMX sulla porta seriale **COM1**. Vengono gestiti 5 dispositivi con indirizzi da 1 a 5. Il frame DMX è continuamente inviato ai dispositivi. Attivando l'ingresso digitale **Di00M00** viene impostato il valore 0, su tutti i dispositivi. Attivando l'ingresso digitale **Di01M00** su dispositivo 1 viene impostato il valore 10, sul 2 il valore 20, e così via fino al quinto in cui viene impostato il valore 50. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image29| | +-----------------------------------------------------------------------+ **Esempio ST** .. code-block:: none (\* ESEGUO APERTURA PORTA SERIALE \*) (\* Here the COM1 port is opened in read/write. \*) IF (FBDMX.File = NULL) THEN FBDMX.File:=Sysfopen('COM1', 'rw'); (\* Port COM1 file pointer \*) END_IF; (\* ESEGUO ATTIVAZIONE COMANDI \*) (\* Attivazione comandi su input Di00M00. \*) DiPls[0](CLK:=Di00M00); IF (DiPls[0].Q) THEN DMXData[0]:=0; (\* Preset dispositivo con indirizzo 1 \*) DMXData[1]:=0; (\* Preset dispositivo con indirizzo 2 \*) DMXData[2]:=0; (\* Preset dispositivo con indirizzo 3 \*) DMXData[3]:=0; (\* Preset dispositivo con indirizzo 4 \*) DMXData[4]:=0; (\* Preset dispositivo con indirizzo 5 \*) FBDMX.Start:=TRUE; (\* Start \*) END_IF; (\* Attivazione comandi su input Di01M00. \*) DiPls[1](CLK:=Di01M00); IF (DiPls[1].Q) THEN DMXData[0]:=10; (\* Preset dispositivo con indirizzo 1 \*) DMXData[1]:=20; (\* Preset dispositivo con indirizzo 2 \*) DMXData[2]:=30; (\* Preset dispositivo con indirizzo 3 \*) DMXData[3]:=40; (\* Preset dispositivo con indirizzo 4 \*) DMXData[4]:=50; (\* Preset dispositivo con indirizzo 5 \*) FBDMX.Start:=TRUE; (\* Start \*) END_IF; (\* ESEGUO GESTIONE PROTOCOLLO DMX \*) (\* Gestione protocollo DMX. \*) FBDMX.Status:=0; (\* Status byte \*) FBDMX.Devices:=5; (\* Number of devices \*) FBDMX.Delay:=0; (\* Interframe delay (mSec) \*) FBDMX.DataPtr:=ADR(DMXData); (\* Data array pointer \*) FBDMX(); (\* FB gestione protocollo DMX \*) IF (FBDMX.Done) THEN FBDMX.Start:=FALSE; END_IF; (\* [End of file] \*) IOEncoder , incremental encoder over I/O ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image30| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | FB | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questo blocco funzione esegue la lettura di un encoder incrementale connesso agli ingressi logici. Basta appoggiare sui due ingressi **APhase** e **BPhase** del blocco funzione i due ingressi di acquisizione del canale **A** e del canale **B** di un encoder incrementale. Il blocco funzione esegue la quadratura dei segnali, il controllo della direzione di rotazione e gestisce il valore di **Quote** in uscita. La quadratura dei segnali esegue la moltiplicazione per 4 delle tacche encoder quindi il valore di **Quote** al termine di un giro completo dell'encoder è pari al numero di tacche encoder moltiplicato per 4. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione gestione conteggio | | | encoder. | +-----------------------------------+-----------------------------------+ | **Reset** (BOOL) | Comando di reset quota encoder. | | | Attivando l'ingresso si azzera il | | | valore di **Quote**. | +-----------------------------------+-----------------------------------+ | **APhase** (BOOL) | Ingresso canale **A** encoder. | +-----------------------------------+-----------------------------------+ | **BPhase** (BOOL) | Ingresso canale **B** encoder. | +-----------------------------------+-----------------------------------+ | **Enabled** (BOOL) | Conteggio encoder abilitato. | +-----------------------------------+-----------------------------------+ | **Error** (BOOL) | Attivo per un loop su errore | | | acquisizione encoder. Si attiva | | | se la frequenza di ingresso dei | | | segnali encoder è maggiore | | | rispetto al tempo di esecuzione | | | del blocco funzione. | +-----------------------------------+-----------------------------------+ | **Quote** (UDINT) | Valore di quota encoder espresso | | | in impulsi. Numero tacche giro | | | encoder moltiplicato per 4. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Nell'esempio è gestita l'acquisizione di un encoder incrementale connesso agli ingressi del modulo CPU. Ruotando di un giro l'encoder, il valore di **Quote** verrà incrementato se la rotazione è oraria (CW) oppure decrementato se la rotazione è antioraria (CCW), del numero di tacche giro moltiplicato per 4. +---------------------------+ | **Definizione variabili** | +---------------------------+ | |image31| | +---------------------------+ **Esempio LD** |image32| GetISO115 5Crc, calculate CRC according ISO1155 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image33| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | Function | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questa funzione esegue il calcolo del CRC **Cyclic Redundancy Check**, (Controllo Ciclico di Ridondanza) su di un'area dati. Il calcolo è effettuato secondo le specifiche **ISO 1155**. Occorre passare alla funzione l'indirizzo del buffer di memoria **Buffer** ed il numero di bytes **ByteNr** su cui eseguire il calcolo del CRC. +-----------------------------------+-----------------------------------+ | **Buffer** (@USINT) | Indirizzo dell'area di memoria su | | | cui eseguire il calcolo del CRC. | +-----------------------------------+-----------------------------------+ | **ByteNr** (UINT) | Numero di bytes su cui eseguire | | | il calcolo del CRC a partire | | | dall'indirizzo definito in | | | **Buffer**. | +-----------------------------------+-----------------------------------+ | (UINT) | Valore CRC calcolato. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene calcolato il CRC di una richiesta di lettura del registro 1.8.1 da un contatore di energia elettrica secondo lo standard IEC 62056-2. Il frame di richiesta è **'R11.8.1()'**. Il valore del CRC ritornato in **CRCValue** è 16#5A (90 decimale). +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image35| | +-----------------------------------------------------------------------+ **Esempio ST** .. code-block:: none (\* IEC1155 CRC CALCULATION \*) (\* Register read command 'R11.8.1()'. \*) DataFrame:='$01R1$021.8.1()$03'; (\* Data frame \*) CRCValue:=GetISO1155Crc(ADR(DataFrame), 12); (\* CRC Value \*) IODataExc hange, exchange data by using ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image36| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | FB | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questo blocco funzione permette lo scambio di dati tra due sistemi, uno master ed uno slave, utilizzando una connessione tramite I/O logici. Sono utilizzati due ingressi e due uscite digitali per ogni sistema, è possibile definire il numero di bytes di dati da scambiarsi. Occorre connettere l'uscita digitale **OStrobe** di un sistema con l'ingresso digitale **IStrobe** dell'altro sistema e l'uscita **OData** con l'ingresso digitale **IData** dell'altro. Il trasferimento dati è bidirezionale, i dati presenti nel buffer **TxData** di un sistema sono trasferiti nel buffer **RxData** dell'altro sistema e viceversa, per il numero di bytes definito in **ByteNr**. La comunicazione è verificata mediante l'invio di un CRC secondo lo standard ISO 1155. Ad ogni **fine** trasferimento dati si attiva per un loop l'uscita **Done**, sulla sua attivazione occorre provvedere a trasferire i dati da trasmettere nel buffer di trasmissione e leggere i dati dal buffer di ricezione. In caso di **errore** nella comunicazione si attiva per un loop l'uscita **Fault**, ed i due sistemi si risincronizzano per riprendere una nuova trasmissione. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione gestione | | | comunicazione. | +-----------------------------------+-----------------------------------+ | **IsMaster** (BOOL) | **TRUE:** Modo master, **FALSE:** | | | Modo slave. | +-----------------------------------+-----------------------------------+ | **IStrobe** (BOOL) | Occorre appoggiare l'ingresso | | | digitale di strobe. | +-----------------------------------+-----------------------------------+ | **IData** (BOOL) | Occorre appoggiare l'ingresso | | | digitale di dato. | +-----------------------------------+-----------------------------------+ | **RxData** (UDINT) | Indirizzo buffer dati ricevuti. | +-----------------------------------+-----------------------------------+ | **TxData** (UDINT) | Indirizzo buffer dati da | | | trasmettere. | +-----------------------------------+-----------------------------------+ | **ByteNr** (USINT) | Numero bytes da scambiare con | | | altro sistema (Da 1 a 30). | +-----------------------------------+-----------------------------------+ | **TrigDelay** (UINT) | Tempo attesa tra uscita dato | | | **OData** ed uscita strobe | | | **OStrobe** (Da 0 a 30 mS). | +-----------------------------------+-----------------------------------+ | **OStrobe** (BOOL) | Da appoggiare su uscita digitale | | | di strobe. | +-----------------------------------+-----------------------------------+ | **OData** (BOOL) | Da appoggiare su uscita digitale | | | di dato. | +-----------------------------------+-----------------------------------+ | **Done** (BOOL) | Si attiva per un loop al termine | | | dello scambio dati. | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Si attiva per un loop in caso di | | | errore su scambio dati. | +-----------------------------------+-----------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +------------+----------------------------------------------------+ | 10011080 | Errore definizione valore **ByteNr**. | +------------+----------------------------------------------------+ | 10011082 | Errore definizione valore **TrigDelay**. | +------------+----------------------------------------------------+ | 10011100~1 | Timeout attesa attivazione segnale **IStrobe**. | +------------+----------------------------------------------------+ | 10011110~1 | Timeout attesa disattivazione segnale **IStrobe**. | +------------+----------------------------------------------------+ | 10011200~1 | Errore CRC dati ricevuti. | +------------+----------------------------------------------------+ **Esempi** """"""""""" Utilizzando due sistemi attivando modo master (**Di01M00** attivo) su di un sistema e modo slave (**Di01M00** disattivo) sull'altro, è possibile eseguire lo scambio di 4 bytes di memoria tra i sistemi. I 4 bytes allocati ad indirizzo **MD100.0** di un sistema saranno trasferiti su 4 bytes allocati ad indirizzo **MD100.16** dell'altro sistema. Al termine del trasferimento, i dati ricevuti dalla memoria **MD100.0** sono trasferiti nella variabile **RxData**, mentre la variabile **TxData** è trasferita in memoria **MD100.16**. +-------------------------------+ | **Definizione variabili** | +-------------------------------+ | |image37| | +-------------------------------+ **Esempio LD** *(Ptp121A000)* |image38| Average, value average ^^^^^^^^^^^^^^^^^^^^^^^^ |image39| +----------+------------------+ | **Type** | **Library** | +==========+==================+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione esegue la media su di un valore. L'azione di media è definita da un parametro **Coefficient**, maggiore è il valore del parametro e maggiore sarà l'azione di media sul valore in uscita **Average**. +------------------------+--------------------------------------------+ | **Value** (REAL) | Valore su cui effettuare l'azione di media | +------------------------+--------------------------------------------+ | **Coefficient** (REAL) | Valore del coefficiente di media. | +------------------------+--------------------------------------------+ | **Average** (REAL) | Valore mediato in uscita. | +------------------------+--------------------------------------------+ **Esempi** """"""""""" Viene eseguita una acquisizione analogica dall'ingresso **0** del modulo con indirizzo **0**, in modo 0÷10 volt. Il valore acquisito viene mediato e poi trasferito nella variabile **AnaValue**. +---------------------------------------------+ | **Definizione variabili** | +---------------------------------------------+ | |image40| | +---------------------------------------------+ **Esempio FBD** *(PTP114A500, FBD_Average)* |image41| HIDClkDtaReader, HID RFID clock/data reader ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image42| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | FB | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questo blocco funzione esegue l'acquisizione di un lettore HID tipo clock e dato. La gestione del lettore deve essere eseguita almeno ogni 400 uSec, quindi si consiglia di utilizzarlo in un programma eseguito nella task fast, definendo il tempo di esecuzione della task a 400 uS tramite la funzione `SysSetTaskLpTime <#FctSysSetTaskLpTime>`__. Il blocco funzione può acquisire tags RFID con codice di lunghezza fino ad 8 bytes, il codice letto viene trasferito nel buffer indirizzato da **CData**, occorre definire la lunghezza del codice in **CDLength**. +-----------------------------------+-----------------------------------+ | **Clock** (BOOL) | Ingresso di clock del lettore | | | RFID. | +-----------------------------------+-----------------------------------+ | **Data** (BOOL) | Ingresso di dato del lettore | | | RFID. | +-----------------------------------+-----------------------------------+ | **CData** (@BYTE) | Indirizzo buffer codice letto dal | | | tag RFID. | +-----------------------------------+-----------------------------------+ | **CDLength** (USINT) | Numero bytes codice letto dal tag | | | RFID. | +-----------------------------------+-----------------------------------+ | **Done** (BOOL) | Attivo per un loop al termine | | | della lettura tag RFID. | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo per un loop su errore | | | lettura tag RFID. | +-----------------------------------+-----------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +------------+-----------------------------------------+ | 10039050 | Errore definizione valore **CDLength**. | +------------+-----------------------------------------+ | 10039060 | Errore esecuzione. | +------------+-----------------------------------------+ | 10039100~2 | Errore lettura dati tag RFID. | +------------+-----------------------------------------+ **Esempi** """"""""""" Viene gestita la lettura di un reader della HID clock e dato connesso agli ingressi digitali del modulo CPU. Ricordo che il programma deve essere eseguito almeno ogni 400 uS quindi si consiglia di eseguilo nella task Fast impostando il tempo di esecuzione a 400 uS. Il valore di codice letto dal TAG RFID è trasferito nell'array **CData**. +---------------------------------------------------+ | **Definizione variabili** | +---------------------------------------------------+ | |image43| | +---------------------------------------------------+ **Esempio LD** *(PTP114A610, LD_HIDClkDtaReader)* |image44| Linearize , linearize a non linear value ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image45| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | Function | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questa funzione esegue la linearizzazione di un valore. Occorre fornire alla funzione l'indirizzo dell'array definizione valore in ingresso da linearizzare **VinReference**, l'indirizzo dell'array definizione del corrispondente valore in uscita linearizzato **VOutReference** ed il numero di valori presenti nell'array **ReferenceNr**. E' importante definire i dati negli array in modo crescente, quindi a partire dal valore più piccolo. La funzione esegue la ricerca nell'array **VinReference** del valore immediatamente superiore a **Vin** interpolando linearmente tra il valore trovato e quello precedente, calcolando il valore in uscita in base ai due valori presenti nelle stesse posizioni dell'array **VOutReference**. +-----------------------------------+-----------------------------------+ | **VIn** (REAL) | Valore su cui effettuare la | | | linearizzazione | +-----------------------------------+-----------------------------------+ | **VInReference** (@REAL) | Puntatore all'array definizione | | | valore in ingresso da | | | linearizzare. | +-----------------------------------+-----------------------------------+ | **VOutReference** (@REAL) | Puntatore all'array definizione | | | valore in uscita linearizzato. | +-----------------------------------+-----------------------------------+ | **ReferenceNr** (USINT) | Numero di valori negli arrays di | | | definizione linearizzazione. | +-----------------------------------+-----------------------------------+ | (REAL) | Valore linearizzato in uscita. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene eseguita tramite una acquisizione analogica la lettura di un livello di un serbatoio di forma irregolare, tramite la funzione viene ritornato il valore dei litri presenti nel serbatoio. Il valore di livello viene mediato per avere una lettura piu regolare. Ad 1 volt corrispondono 1000 litri, a 2 volt corrispondono 4000 litri, a 3 volt corrispondono 6000 litri. +-----------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------+ | |image46| | +-----------------------------------------------+ **Esempio FBD** *(PTP114A610, FBD_Linearize)* |image47| ValueScale, scales a value ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image48| +----------+------------------+ | **Type** | **Library** | | | | +==========+==================+ | Function | eLLabUtyLib_C030 | +----------+------------------+ Questa funzione esegue la messa in scala di un valore. E' possibile definire il limite minimo e massimo del valore in ingresso da scalare (**ILow**, **IHigh**) ed il valore minimo e massimo del valore in uscita scalato (**OLow**, **OHigh**). L'utilizzo di questa funzione è particolarmente indicato per convertire valori acquisiti da sensori in corrente (4-20 mA) nella corrispondente unità di misura rilevata dal trasduttore. +------------------+---------------------------------------------------+ | **Input** (REAL) | Valore in ingresso da scalare. | +------------------+---------------------------------------------------+ | **ILow** (REAL) | Limite minimo del valore in ingresso da scalare. | +------------------+---------------------------------------------------+ | **IHigh** (REAL) | Limite massimo del valore in ingresso da scalare. | +------------------+---------------------------------------------------+ | **OLow** (REAL) | Limite minimo del valore in uscita scalato. | +------------------+---------------------------------------------------+ | **OHigh** (REAL) | Limite massimo del valore in uscita scalato. | +------------------+---------------------------------------------------+ | (REAL) | Valore scalato in uscita. | +------------------+---------------------------------------------------+ **Esempi** """"""""""" Viene eseguita una acquisizione analogica di un sensore di temperatura con uscita in corrente 4-20 mA, il sensore ha come valore in uscita la corrente di 4 mA a -50 °C e la corrente di 20 mA a 150 °C. Utilizzando la funzione si esegue direttamente la conversione in gradi centigradi del valore acquisito. +-------------------------------------------+ | **Definizione variabili** | +-------------------------------------------+ | |image49| | +-------------------------------------------+ **Esempio FBD** *(PTP114A610, FBD_Scale)* |image50| GetPolyno mialCRC, polynomial CRC calculation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image51| +-----------------------+-----------------------+ | **Type** | **Library** | | | | +=======================+=======================+ | Function | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questa funzione esegue il calcolo del CRC su di un array di dati in accordo allo standard CCITT. In **Data** occorre indicare l'indirizzo dell'array di dati su cui calcolare il CRC, **Length** indica la lunghezza dell'array in byte. In **CRC** è ritornato il valore del CRC calcolato. +-----------------------------------+-----------------------------------+ | **Data** (@USINT) | Indirizzo array dati su cui | | | eseguire il calcolo del CRC. | +-----------------------------------+-----------------------------------+ | **Length** (USINT) | Lunghezza array in bytes. | +-----------------------------------+-----------------------------------+ | (WORD) | Valore CRC calcolato. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene eseguito il calcolo del CRC su di un array di dati. Supponendo di avere un array di 8 bytes allocato in DB100 all'indirizzo 16 che contiene i valori 16#04, 16#3B, 16#1B, 16#00, 16#00, 16#00, 16#00, 16#00 , il CRC calcolato sarà 16#5AF0. +----------------------------------------------------+ | **Definizione variabili** | +----------------------------------------------------+ | |image52| | +----------------------------------------------------+ **Esempio ST** *(PTP114A620, ST_GetPolynomialCRC)* .. code-block:: none BData[0]:=16#04; BData[1]:=16#3B; BData[2]:=16#1B; BData[3]:=16#00; BData[4]:=16#00; BData[5]:=16#00; BData[6]:=16#00; BData[7]:=16#00; CRCValue:=GetPolynomialCRC(ADR(BData), 8); LRamp, linear ramp ^^^^^^^^^^^^^^^^^^^^^ |image53| +----------+------------------+ | **Type** | **Library** | | | | +----------+------------------+ | FB | eLLabUtyLib_C030 | +----------+------------------+ Questo blocco funzione esegue una rampa lineare sul valore di ingresso. Il valore **Out** in uscita segue il valore di ingresso **In** con li valori di pendenza definiti. Il valore **UPSlope** imposta la pendenza in salita mentre **DWSlope** quella in discesa. Disabilitando il blocco funzione l'uscita si azzera. I valori di pendenza sono definiti in unità al secondo, ad esempio con **UPSlope** settato a 1 (1 unità al secondo), ipotizzando uno step di 10 in ingresso **In**, avremo l'uscita **Out** che raggiunge il valore 10 in 10 secondi. +--------------------+------------------------------------------------------+ | **Enable** (BOOL) | Abilitazione al blocco funzione. | +--------------------+------------------------------------------------------+ | **In** (REAL) | Valore in ingresso su cui viene effettuata la rampa. | +--------------------+------------------------------------------------------+ | **UPSlope** (REAL) | Valore di pendenza rampa in salita (Unit/Second) | +--------------------+------------------------------------------------------+ | **DWSlope** (REAL) | Valore di pendenza rampa in discesa (Unit/Second) | +--------------------+------------------------------------------------------+ | **Enable** (BOOL) | Blocco funzione abilitato. | +--------------------+------------------------------------------------------+ | **Out** (REAL) | Valore di rampa in uscita. | +--------------------+------------------------------------------------------+ **Esempi** """"""""""" Viene eseguita una rampa sul valore di **Source** con pendenza di salita di 1 e discesa di 2. Supponendo uno step in **Source** di 10 avremo **Destination** che raggiunge il valore in 10 scendi. Mentre portando a 0 il valore di **Source** avremo **Destination** che si azzera i 5 secondi. +---------------------------+ | **Definizione variabili** | +---------------------------+ | |image54| | +---------------------------+ **Esempio FBD** |image55| VaPotentiometer, voltage acquisition potentiometer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image56| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | Function | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questa funzione esegue il calcolo del valore ohmico di un potenziometro acquisendo il valore di tensione in uscita dal suo cursore. In **PVoltage** occorre indicare la tensione di alimentazione del potenziometro, in **Resistance** la sua resistenza. Fornendo in **AVoltage** il valore acquisito dal suo cursore il blocco funzione calcola il valore del potenziometro alla sua posizione attuale. Per compensare l'errore di lettura dovuto alla impedenza di ingresso del canale di acquisizione della tensione occorre definirla in **Aimpedance**. +-----------------------------------+-----------------------------------+ | **PVoltage** (REAL) | Tensione di alimentazione del | | | potenziometro. La tensione | | | applicata ai suoi estremi (V). | +-----------------------------------+-----------------------------------+ | **Resistance** (REAL) | Valore resistivo del | | | potenziometro (Ohm). | +-----------------------------------+-----------------------------------+ | **AVoltage** (REAL) | Valore di tensione acquisita sul | | | cursore del potenziometro (V). | +-----------------------------------+-----------------------------------+ | **AImpedance** (REAL) | Valore di impedenza di ingresso | | | del canale di acquisizione (Ohm). | +-----------------------------------+-----------------------------------+ | (REAL) | Valore resistenza letta dal | | | potenziometro (Ohm). | +-----------------------------------+-----------------------------------+ |image57| **Esempi** Viene acquisito il valore ohmico alla posizione del cursore di un potenziometro da 5 KOhm alimentato con tensione di 10 Volt. Il valore è acquisito tramite un modulo di ingresso analogico. +-----------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------+ | |image58| | +-----------------------------------------------------+ **Esempio FBD** *(PTP114A640, FBD_VaPotentiometer)* |image59| ResistorValue, resistor value acquire ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image60| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | Function | eLLabUtyLib_C030 | +-----------------------+-----------------------+ Questa funzione esegue la lettura del valore ohmico di una resistenza acquisendo il valore di tensione su di un partitore resistivo. In **PVoltage** occorre indicare la tensione di alimentazione del partitore resistivo, in **RSeries** il valore in Ohm della resistenza serie. Fornendo in **AVoltage** il valore di tensione acquisito ai capi della resistenza da misurare il blocco funzione calcola il valore della resistenza.Per compensare l'errore di lettura dovuto alla impedenza di ingresso del canale di acquisizione della tensione occorre definirla in **AImpedance**. +-----------------------------------+-----------------------------------+ | **PVoltage** (REAL) | Tensione di alimentazione | | | partitore resistivo (V). | +-----------------------------------+-----------------------------------+ | **RSeries** (REAL) | Valore resistivo della resistenza | | | serie (Ohm). | +-----------------------------------+-----------------------------------+ | **AVoltage** (REAL) | Valore di tensione acquisita ai | | | capi della resistenza da misurare | | | (V). | +-----------------------------------+-----------------------------------+ | **AImpedance** (REAL) | Valore di impedenza di ingresso | | | del canale di acquisizione (Ohm). | +-----------------------------------+-----------------------------------+ | (REAL) | Valore resistenza (Ohm). | +-----------------------------------+-----------------------------------+ |image61| **Esempi** """"""""""" Viene acquisito il valore ohmico di una resistenza inserita in un partitore con una resistenza da 4,7KOhm. Il partitore viene alimentato con una tensione di 10 Volt. Il valore è acquisito tramite un modulo di ingresso analogico. Il valore acquisito viene poi filtrato con una FB **Average** per avere un valore stabile. +---------------------------------------------------+ | **Definizione variabili** | +---------------------------------------------------+ | |image62| | +---------------------------------------------------+ **Esempio FBD** *(PTP114A640, FBD_ResistorValue)* |image63| BufferModified, checks if a buffer has been modified ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image64| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | FB | eLLabUtyLib_C040 | +-----------------------+-----------------------+ Questo FB controlla se vi è stata una variazione nel contenuto di un buffer di memoria. In **Buffer** occorre definire l'indirizzo ed in **Size** la dimensione del buffer di memoria da controllare. Abilitando il FB viene allocato automaticamente al suo interno un buffer di comparazione e si attiva l'uscita **Ready**. Ad ogni esecuzione viene comparato il contenuto del buffer con il buffer di comparazione interno, e se differenza si attiva per un loop l'uscita **Modified**. Variando l'indirizzo del buffer e/o la sua dimensione l'FB automaticamente rialloca un nuovo buffer di riferimento. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione FB, disattivando il | | | bit viene anche rilasciata la | | | memoria del bufffer interno. | +-----------------------------------+-----------------------------------+ | **Buffer** (@BYTE) | Indirizzo del buffer da | | | controllare. | +-----------------------------------+-----------------------------------+ | **Size** (UDINT) | Dimensione del buffer da | | | controllare. | +-----------------------------------+-----------------------------------+ | **Ready** (BOOL) | Attivo se FB stà eseguendo il | | | controllo. | +-----------------------------------+-----------------------------------+ | **Modified** (BOOL) | Attivo per un loop se il | | | contenuto del buffer si è | | | modificato. | +-----------------------------------+-----------------------------------+ **Esempi** """"""""""" Viene eseguito il controllo sul contenuto del buffer **Data**. Se vi sono variazioni viene attivato **Modifed**. Occorrerà agire da debug per resettarlo. +--------------------------------------------------+ | **Definizione variabili** | +--------------------------------------------------+ | |image65| | +--------------------------------------------------+ **Esempio LD** *(PTP114A640, LD_BufferModified)* |image66| Wiegand26Dcd, decodes the Wiegand 26 bits code ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image67| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | FB | eLLabUtyLib_C050 | +-----------------------+-----------------------+ Questo FB decodifica un codice Wiegand a 26 bits. Il FB può essere eseguito come una funzione, occorre fornire in **WBits** il codice Wiegand acquisito. In uscita se il codice è corretto sarà attivo **CodeOk** ed avremo in **Facillity** ed in **IDNumber** il codice decodificato. In caso di errore nella decodifica viene attivata per un loop di programma l'uscita **Fault**. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione FB, attivandolo | | | viene eseguita la decodifica del | | | codice. | +-----------------------------------+-----------------------------------+ | **WBits** (DWORD) | Codice Wiegand da decodificare. | +-----------------------------------+-----------------------------------+ | **CodeOk** (BOOL) | Si attiva se decodifica | | | correttamente eseguita. | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo per un loop se errore | | | decodifica. | +-----------------------------------+-----------------------------------+ | **Facility** (USINT) | Facility code decodificato. | +-----------------------------------+-----------------------------------+ | **IDNumber** (UDINT) | ID number decodificato. | +-----------------------------------+-----------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +------------+---------------------------------------------------------------+ | **Codice** | **Descrizione** | +------------+---------------------------------------------------------------+ | 10068100 | Codice Wiegand in **WBits** non è corretto ha più di 26 bits. | +------------+---------------------------------------------------------------+ | 10068110 | Even parity errata. | +------------+---------------------------------------------------------------+ | 10068120 | Odd parity errata. | +------------+---------------------------------------------------------------+ **Esempi** """"""""""" Viene eseguita l'acquisizione di un lettore TAGS RFID connesso agli ingressi Di00 e Di01 di un modulo CPU SlimLine. Il valore del TAG acquisito è visualizzabile da debug. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image69| | +-----------------------------------------------------------------------+ **Esempio ST** *(PTP114A660, ST_Wiegand26Dcd)* .. code-block:: none (\* Program initialization. \*) IF (SysFirstLoop) THEN DWiegand:=SysSetTaskLpTime(TaskID:=ID_TASK_FAST, Time:=150); LInp.Address:=255; (\* Module address \*) LInp.Mode:=DI_I_8_LL; (\* Acquisition mode \*) END_IF; (\* Se non variazione ingressi per tempo definito bus a riposo. \*) IF (DStrobe) THEN IF ((SysGetSysTime(TRUE)-BTime) > 100000) THEN DStrobe:=FALSE; (\* Data strobe \*) (\* Eseguo decodifica codice Wiegand. \*) IF (BWiegand = 26) THEN WDecoder(Enable:=TRUE, WBits:=DWiegand); (\* Wiegand decoder \*) END_IF; END_IF; END_IF; (\* Acquisizione e controllo se variazione ingressi. \*) LInp(); (\* Acquisizione ingressi logici \*) IF (LInp.Value = Value) THEN RETURN; END_IF; Value:=LInp.Value; (\* Digital input value \*) BTime:=SysGetSysTime(TRUE); (\* Buffer time (uS) \*) (\* Se variazione ingressi dopo bus a riposo start dati. \*) IF NOT(DStrobe) THEN DStrobe:=TRUE; (\* Data strobe \*) BWiegand:=0; (\* Wiegand bits \*) DWiegand:=0; (\* Wiegand data \*) END_IF; (\* Gestione "D0" ogni transizione è un bit con valore "0". \*) IF (TO_BOOL(LInp.Value AND 16#01) <> Data[0]) THEN Data[0]:=NOT(Data[0]); (\* Appoggio ingresso "D0" \*) IF NOT(Data[0]) THEN DWiegand:=(DWiegand*2); BWiegand:=BWiegand+1; END_IF; END_IF; (\* Gestione "D1" ogni transizione è un bit con valore "1". \*) IF (TO_BOOL(LInp.Value AND 16#02) <> Data[1]) THEN Data[1]:=NOT(Data[1]); (\* Appoggio ingresso "D1" \*) IF NOT(Data[1]) THEN DWiegand:=(DWiegand*2)+16#00000001; BWiegand:=BWiegand+1; END_IF; END_IF; CLIManager, manages a command-line user interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image70| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | FB | eLLabUtyLib_C050 | +-----------------------+-----------------------+ Questo FB gestisce l'interfaccia a linea di comando di un dispositivo. Occorre passare in **Fp** lo stream di comunicazione con il dispositivo, in **CPointer** la stringa di comando e in **EOLString** la stringa di risposta attesa (Se non definita non è attesa nessuna risposta). Attivando per un loop **CSend** il comando viene inviato al dispositivo e si riceve la risposta se non ricevuta nel tempo definito in **AETime** viene generato errore. In **ABPointer** ed **ABLength** occorre definire l'indirizzo e la dimensione del buffer dove verrà trasferita la risposta. Se si desidera controllare la ricezione di ogni singola riga della risposta basterà definire in **EOLString** la stringa di terminazione riga (Esempio '$r$n'). In **AETime** è possibile definire il tempo di fine ricezione risposta, se non sono ricevuti caratteri per il tempo definito, si attiva per un loop l'uscita **AEnd**. L'uscita **EOL** si attiva per un loop alla ricezione di una riga (Solo se definito **EOLString**), l'uscita **ABFull** si attiva per un loop se il buffer di ricezione risposta è pieno. In **ABRxChrs** è ritornato il numero di caratteri di risposta ricevuti. In caso di errore viene attivata per un loop di programma l'uscita **Fault**. +-----------------------------------+-----------------------------------+ | **Enable** (BOOL) | Abilitazione FB. | +-----------------------------------+-----------------------------------+ | **CSend** (BOOL) | Sul fronte di attivazione viene | | | inviato al dispositivo il comando | | | definito in **Cpointer**. Per | | | inviare un nuovo comando occorre | | | resettarlo e riattivarlo. | +-----------------------------------+-----------------------------------+ | **SpyOn** (BOOL) | Se attivo permette di spiare il | | | funzionamento della FB. | +-----------------------------------+-----------------------------------+ | **Fp** (FILEP) | Stream comunicazione con | | | dispositivo. | +-----------------------------------+-----------------------------------+ | **CPointer** (@STRING) | Puntatore alla stringa di | | | definizione comando da inviare. | +-----------------------------------+-----------------------------------+ | **ABPointer** (@STRING) | Puntatore buffer memorizzazione | | | risposta. | +-----------------------------------+-----------------------------------+ | **ABLength** (UDINT) | Dimensione buffer memorizzazione | | | risposta. | +-----------------------------------+-----------------------------------+ | **EOLString** (@STRING) | Puntatore a stringa di controllo | | | fine ricezione. Se NULL non viene | | | controllata la risposta ricevuta. | +-----------------------------------+-----------------------------------+ | **AETime** (REAL) | Tempo di attesa fine ricezione | | | risposta (S). | +-----------------------------------+-----------------------------------+ | **EOLTime** (REAL) | Tempo di attesa stringa fine | | | ricezione (S). | +-----------------------------------+-----------------------------------+ | **EOL** (BOOL) | Attivo per un loop su fine | | | ricezione riga (Solo se definito | | | **EOLString**). | +-----------------------------------+-----------------------------------+ | **AEnd** (BOOL) | Attivo per un loop su fine | | | ricezione risposta (Non ricevuti | | | caratteri per tempo **AETime**). | +-----------------------------------+-----------------------------------+ | **ABFull** (BOOL) | Attivo per un loop se buffer | | | risposta pieno (Ricevuti | | | caratteri definitri in | | | **ABLength**). | +-----------------------------------+-----------------------------------+ | **Fault** (BOOL) | Attivo per un loop se errore. | +-----------------------------------+-----------------------------------+ | **ABRxChrs** (UDINT) | Numero di caratteri di risposta | | | ricevuti. | +-----------------------------------+-----------------------------------+ **Trigger di spy** Se **SpyOn** attivo viene eseguita la funzione `SysSpyData <#FctSysSpyData>`__ che permette di spiare il funzionamento della FB. Sono previsti vari livelli di triggers. +-------------+-------------------------------------------------+ | **TFlags** | **Descrizione** | +-------------+-------------------------------------------------+ | 16#00000001 | 'Tx' Invio comando | +-------------+-------------------------------------------------+ | 16#00000002 | 'Rl' Risposta ricevuta su fine linea "EOL" | +-------------+-------------------------------------------------+ | | 'Re' Risposta ricevuta su fine ricezione "AEnd" | +-------------+-------------------------------------------------+ | | 'Rf' Risposta ricevuta buffer pieno "ABFull" | +-------------+-------------------------------------------------+ **Codici di errore** In caso di errore si attiva l'uscita **Fault**, con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +------------+----------------------------------------+ | **Codice** | **Descrizione** | +------------+----------------------------------------+ | 10082020 | FB eseguito in task diversa da back. | +------------+----------------------------------------+ | 10082100 | Timeout invio comando. | +------------+----------------------------------------+ | 10082200 | Timeout ricezione risposta al comando. | +------------+----------------------------------------+ **Esempi** """"""""""" Viene eseguito il login su un sistema SlimLine (Userbname Admin, Password Admin) e viene acquisito il comando HwStats. La risposta al comando viene ricevuta riga per riga (Fine linea ). Dalla risposta ricevuta viene rilevato il numero di accensioni **SwOn** e la temperatura della CPU **Temperature**. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image72| | +-----------------------------------------------------------------------+ **Esempio ST** *(PTP114A660, ST_CLIManager)* .. code-block:: none (\* Eseguo inizializzazioni. \*) IF (SysFirstLoop) THEN (\* Inizializzo TCP client. \*) TCPClient.PeerAdd:=ADR('192.168.0.230'); (\* Peer address \*) TCPClient.PeerPort:=23; (\* 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:=128; (\* Rx buffer size \*) TCPClient.TxSize:=128; (\* Tx buffer size \*) (\* Inizializzo interfaccia comandi. \*) CLI.SpyOn:=TRUE; (\* Spy On \*) CLI.ABPointer:=ADR(ABuffer); (\* Answer buffer pointer \*) CLI.ABLength:=SIZEOF(ABuffer); (\* Answer buffer length \*) CLI.AETime:=0.01; (\* Answer end time (S) \*) CLI.EOLTime:=1.0; (\* End of line time (S) \*) (\* Inizializzo variabili. \*) TimeBf:=SysGetSysTime(TRUE); (\* Time buffer (uS) \*) END_IF; (\* CONNESSIONE AL SERVER TELNET \*) (\* Manage the TCP client. \*) TCPClient(); (\* TCPClient \*) CLI.Fp:=TCPClient.File; (\* File pointer \*) CLI(Enable:=TCPClient.Connected); (\* Command interface \*) CLI.CSend:=FALSE; (\* Command send \*) (\* GESTIONE FAULT \*) (\* Gestione fault. \*) IF (ErrorNr <> 0) THEN CaseNr:=0; END_IF; (\* GESTIONE TIMEOUT SEQUENZA \*) (\* Viene gestito il timeout esecuzione sequenze. \*) IF ((CaseNr = 0) OR (CaseNr <> CaseAx)) THEN TimeBf:=SysGetSysTime(TRUE); END_IF; IF ((SysGetSysTime(TRUE)-TimeBf) > 10000000) THEN ErrorNr:=10; RETURN; END_IF; CaseAx:=CaseNr; (\* Case auxiliary \*) (\* GESTIONE SEQUENZE \*) (\* Gestione sequenze programma. \*) CASE (CaseNr) OF (\* CONNESSIONE AL SERVER \*) (\* Eseguo connessione al server. \*) 0: TCPClient.Connect:=FALSE; (\* Connessione al server \*) IF (Di00CPU = Pulse) THEN RETURN; END_IF; Pulse:=Di00CPU; (\* Command pulse \*) IF NOT(Di00CPU) THEN RETURN; END_IF; (\* Eseguo connessione al server. \*) RVars:=0; (\* Readed variables \*) ErrorNr:=0; (\* Error number \*) TCPClient.Connect:=TRUE; (\* Connessione al server \*) CaseNr:=CaseNr+1; (\* Case gestione \*) (\* Controllo se socket connesso attendo prompt. \*) 1: IF NOT(TCPClient.Connected) THEN RETURN; END_IF; IF NOT(CLI.AEnd) THEN RETURN; END_IF; IF (SysStrFind(ADR(ABuffer), ADR('Login:'), FIND_GET_END) = NULL) THEN ErrorNr:=20; RETURN; END_IF; (\* Invio login ed attendo richiesta password. \*) CLI.CPointer:=ADR('Admin$r'); (\* Invio Username \*) CLI.EOLString:=ADR('Password:'); (\* Attendo stringa "Password:" \*) CLI.CSend:=TRUE; (\* Command send \*) CaseNr:=CaseNr+1; (\* Case gestione \*) (\* Controllo se ricevuto richiesta password. se fine risposta errore. \*) 2: IF (CLI.AEnd) THEN ErrorNr:=30; RETURN; END_IF; IF NOT(CLI.EOL) THEN RETURN; END_IF; CLI.CPointer:=ADR('Admin$r'); (\* Invio Password \*) CLI.EOLString:=NULL; (\* End of line string \*) CLI.CSend:=TRUE; (\* Command send \*) CaseNr:=CaseNr+1; (\* Case gestione \*) (\* Attendo prompt di sistema "[Admin]>". Se il buffer di appoggio è \*) (\* piccolo potrebbe essere nella prima ricezione su buffer pieno. \*) 3: IF (CLI.ABFull OR CLI.AEnd) THEN IF (SysStrFind(ADR(ABuffer), ADR('[Admin]>'), FIND_GET_END) <> NULL) THEN Logged:=TRUE; END_IF; END_IF; (\* Controllo se fine ricezione risposta. Si deve esere loggati. \*) IF NOT(CLI.AEnd) THEN RETURN; END_IF; IF NOT(Logged) THEN ErrorNr:=40; RETURN; END_IF; CaseNr:=10; (\* Case gestione \*) (\* USCITA COMANDO \*) (\* Invio comando richiesta status. Ogni riga di risposta al comando \*) (\* termina con . \*) 10: CLI.CPointer:=ADR('HwStats$r'); CLI.EOLString:=NULL; (\* End of line string \*) CLI.EOLString:=ADR('$r$n'); (\* End of line string \*) CLI.CSend:=TRUE; (\* Command send \*) CaseNr:=CaseNr+1; (\* Case gestione \*) (\* Controllo risposte. \*) 11: IF (CLI.EOL OR CLI.AEnd) THEN IF (SysVarsscanf(SysStrFind(ADR(ABuffer), ADR('Switched on times:..'), FIND_GET_END), '%d', UDINT_TYPE, ADR(SwOn))) THEN RVars:=RVars+1; END_IF; IF (SysVarsscanf(SysStrFind(ADR(ABuffer), ADR('Internal temp.[C]:.'), FIND_GET_END), '%f', REAL_TYPE, ADR(Temperature))) THEN RVars:=RVars+1; END_IF; END_IF; (\* Controllo se fine ricezione risposta. Devo avere 2 variabili. \*) IF NOT(CLI.AEnd) THEN RETURN; END_IF; IF (RVars <> 2) THEN ErrorNr:=50; RETURN; END_IF; CaseNr:=0; (\* Case gestione \*) END_CASE; (\* [End of file] \*) .. |image0| image:: media/image1.jpg :width: 1.44861in :height: 0.89792in .. |image1| image:: media/image2.jpg :width: 7.08681in :height: 0.32292in .. |image2| image:: media/image3.jpg :width: 7.08681in :height: 1.37431in .. |image3| image:: media/image2.jpg :width: 7.08681in :height: 0.32292in .. |image4| image:: media/image3.jpg :width: 7.08681in :height: 1.37431in .. |image5| image:: media/image4.jpg :width: 1.04306in :height: 0.68889in .. |image6| image:: media/image5.jpg :width: 7.08681in :height: 0.35833in .. |image7| image:: media/image6.jpg :width: 7.08681in :height: 1.075in .. |image8| image:: media/image7.jpg :width: 1.5in :height: 2.62569in .. |image9| image:: media/image8.jpg :width: 7.08681in :height: 3.8625in .. |image10| image:: media/image9.jpg :width: 5.46875in :height: 3.42708in .. |image11| image:: media/image10.jpg :width: 1.55139in :height: 2.05139in .. |image12| image:: media/image11.jpg :width: 7.08681in :height: 3.98819in .. |image13| image:: media/image12.jpg :width: 1.51181in :height: 1.51181in .. |image14| image:: media/image13.jpg :width: 7.08681in :height: 0.73611in .. |image15| image:: media/image14.jpg :width: 7.08681in :height: 8.40972in .. |image16| image:: media/image15.jpg :width: 1.61389in :height: 1.24028in .. |image17| image:: media/image16.jpg :width: 7.08681in :height: 0.55139in .. |image18| image:: media/image17.jpg :width: 7.08681in :height: 1.79931in .. |image19| image:: media/image16.jpg :width: 7.08681in :height: 0.55139in .. |image20| image:: media/image17.jpg :width: 7.08681in :height: 1.79931in .. |image21| image:: media/image18.jpg :width: 1.53125in :height: 2.80347in .. |image22| image:: media/image19.jpg :width: 7.08681in :height: 2.25972in .. |image23| image:: media/image20.jpg :width: 7.08681in :height: 6.37431in .. |image24| image:: media/image21.jpg :width: 1.11389in :height: 1.075in .. |image25| image:: media/image22.jpg :width: 7.08681in :height: 0.35417in .. |image26| image:: media/image23.jpg :width: 7.08681in :height: 1.52361in .. |image27| image:: media/image24.jpg :width: 1.09444in :height: 1.44861in .. |image28| image:: media/image25.jpg :width: 7.08681in :height: 0.83472in .. |image29| image:: media/image25.jpg :width: 7.08681in :height: 0.83472in .. |image30| image:: media/image26.jpg :width: 1.29167in :height: 1.05139in .. |image31| image:: media/image27.jpg :width: 7.08681in :height: 0.7125in .. |image32| image:: media/image28.jpg :width: 7.08681in :height: 1.79931in .. |image33| image:: media/image29.jpg :width: 1.60625in :height: 0.62569in .. |image34| image:: media/image30.jpg :width: 7.08681in :height: 0.52361in .. |image35| image:: media/image30.jpg :width: 7.08681in :height: 0.52361in .. |image36| image:: media/image31.jpg :width: 1.25208in :height: 1.75972in .. |image37| image:: media/image32.jpg :width: 7.08681in :height: 1.23611in .. |image38| image:: media/image33.jpg :width: 7.08681in :height: 3.97222in .. |image39| image:: media/image34.jpg :width: 1.46875in :height: 0.72014in .. |image40| image:: media/image35.jpg :width: 7.08681in :height: 0.84236in .. |image41| image:: media/image36.jpg :width: 6.30347in :height: 1.25208in .. |image42| image:: media/image37.jpg :width: 1.51944in :height: 1.12569in .. |image43| image:: media/image38.jpg :width: 7.08681in :height: 0.72014in .. |image44| image:: media/image39.jpg :width: 7.08681in :height: 6.11042in .. |image45| image:: media/image40.jpg :width: 1.82292in :height: 1.01944in .. |image46| image:: media/image41.jpg :width: 7.08681in :height: 1.08681in .. |image47| image:: media/image42.jpg :width: 7.08681in :height: 1.83889in .. |image48| image:: media/image43.jpg :width: 1.45694in :height: 1.15764in .. |image49| image:: media/image44.jpg :width: 7.08681in :height: 0.56319in .. |image50| image:: media/image45.jpg :width: 6.51944in :height: 1.81111in .. |image51| image:: media/image46.jpg :width: 1.51181in :height: 0.64583in .. |image52| image:: media/image47.jpg :width: 7.08681in :height: 0.51181in .. |image53| image:: media/image48.jpg :width: 1.25208in :height: 1.075in .. |image54| image:: media/image49.jpg :width: 7.08681in :height: 0.61042in .. |image55| image:: media/image50.jpg :width: 5.08264in :height: 1.43681in .. |image56| image:: media/image51.jpg :width: 1.99236in :height: 1in .. |image57| image:: media/image52.jpg :width: 2.11736in :height: 1.74306in .. |image58| image:: media/image53.jpg :width: 7.08681in :height: 0.73611in .. |image59| image:: media/image54.jpg :width: 6.85417in :height: 2.62569in .. |image60| image:: media/image55.jpg :width: 1.85417in :height: 0.99236in .. |image61| image:: media/image56.jpg :width: 2.11736in :height: 1.74306in .. |image62| image:: media/image57.jpg :width: 7.08681in :height: 0.89792in .. |image63| image:: media/image58.jpg :width: 7.08681in :height: 2.2125in .. |image64| image:: media/image59.jpg :width: 1.34236in :height: 0.93681in .. |image65| image:: media/image60.jpg :width: 7.08681in :height: 0.72431in .. |image66| image:: media/image61.jpg :width: 7.03125in :height: 2.55208in .. |image67| image:: media/image62.jpg :width: 1.53125in :height: 1.12569in .. |image68| image:: media/image63.jpg :width: 7.08681in :height: 1.53542in .. |image69| image:: media/image63.jpg :width: 7.08681in :height: 1.53542in .. |image70| image:: media/image64.jpg :width: 1.36597in :height: 2.27153in .. |image71| image:: media/image65.jpg :width: 7.08681in :height: 2.33889in .. |image72| image:: media/image65.jpg :width: 7.08681in :height: 2.33889in