Both sides previous revision Previous revision Next revision | Previous revision |
en:appnote:an007 [2017/04/28 17:11] – [Create multiple recursive views mixed with text displays] qem103 | en:appnote:an007 [2019/08/29 17:01] (current) – external edit 127.0.0.1 |
---|
</code> | </code> |
| |
==== Creare una introduzione dati semplice ==== | ==== Create a simple data input ==== |
| |
Si voglia scrivere un programma Qcl che permetta all'utente di introdurre un valore su una variabile, ad esempio una utilizzata per memorizzare un conta pezzi. Innanzitutto dovremo dichiarare tale variabile, ad esempio //cntPieces// nell'apposita sezione della unit di configurazione. Supponiamo che si voglia visualizzare il messaggio "CP" sulla parte sinistra del display ad indicare l'introduzione del conta pezzi, e che il valore da introdurre sia di 4 caratteri e posizionato sulla parte più a destra del display. Il data entry occuperà i display dis0, dis1, dis2, dis3 mentre il messaggio verrà scritto in dis5 e dis6. | You want to write a Qcl program that allows the user to input a value to a variable , for example, one used to store a pieces counting. First we will declare that variable, for example //cntPieces// in the section of the configuration unit. Suppose you want to view the "CP" message on the left side of the display to indicate the introduction of pieces counting, and that the value to be introduced is 4 charactersand positioned on the far right of the display. The data entry will occupy the dis0, dis1, dis2, dis3 display while the message is written in dis5 and dis6. |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
La posizione del punto decimale sarà ovviamente posta a 0 ed eseguiremo la copia del valore del conta pezzi attuale nel parametro //devalue// per far sì che all'ingresso dell'introduzione dati compaia tale valore sul display. | The position of the decimal point will be placed to 0 and we will copy the value of the current pieces in the //devalue// parameter count to ensure that data appears at the entrance of the introduction that value on the display. |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
Infine abiliteremo l'introduzione dati con l'apposito flag, disabiliteremo il segno (un conta pezzi non potrà essere negativo) e attiveremo la procedura d'introduzione con il comando //DATAENTRY//: | Finally we will enable the data input using the appropriate flag, we will disable the sign (a pieces counter cannot be negative) and activate the introduction with the //DATAENTRY// command: |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
A questo punto comincerà a lampeggiare sul display il digit più significativo del valore di //cntPieces// e sarà necessario attendere che l'utente introduca il dato e lo confermi con il tasto ENTER. Successivamente si dovrà leggere il dato introdotto (nel parametro //devalue//) e copiarlo nella nostra variabile del conta pezzi //cntPieces//. Lo stato //st_dentry// ci permette di sapere se il data entry è attivo quindi attendiamo che questo vada a 0 per poi fare le operazioni di copia: | At this point the most significant digit on the display will start flashing the value of //cntPieces// and you will have to wait for the user to enter the data and confirm with the ENTER button. Then you must read the introduced data (in the //devalue// parameter) and copy it into our variable //cntPieces// of pieces counting. The //st_dentry// state lets us know if data entry is active o expect this go to 0 before copying: |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
A questo punto la variabile //cntPieces// è aggiornata con il valore introdotto dall'utente. | At this point the//cntPieces// variable is updated with the value entered by the user. |
| |
==== Creare una introduzione dati complessa ==== | ==== Create a complex data introduction ==== |
| |
Si voglia scrivere un programma Qcl che permetta all'utente di introdurre un valore su una variabile, come già fatto nell'esempio precedente, ma con le seguenti caratteristiche aggiuntive: | You want to write a Qcl program that allows the user to input a value to a variable, as in the previous example, but with the following additional features: |
| |
* controllare che il dato sia compreso tra 1 e 1000 ed in caso contrario visualizzare "Error" per 1 secondo e ripetere l'introduzione dati | * check that the figure is between 1 to 1000 and otherwise show "Error" for 1 second and repeat the data entry |
* se viene premuto il tasto F si esca dall'introduzione dati senza memorizzare il dato introdotto e venga stampato per un secondo il messaggio "Exit F" | * if the F key is pressed you step out of the data input without storing the data introduced and may be printed for a second the "Exit F" message |
* se viene premuto il tasto CLEAR si esca dall'introduzione dati senza memorizzare il dato introdotto e venga stampato per un secondo il messaggio "Exit C" | * If the CLEAR key is pressed you step out of the data input without storing the data introduced and may be printed for a second the "Exit C" message |
* stampare per un secondo il messaggio "MOdiFY" se il dato in introduzione è stato modificato | * print for a second the "MOdiFY" message if the introduced data has been modified |
| |
=== Controllo limiti dato === | === Control data limits === |
Per abilitare il controllo dei limiti del dato introdotto è necessario abilitare tale funzionalità ponendo a 1 l'apposito bit del parametro //deflags// ed impostare nei parametri //deuplim// e //delowlim// i valori dei limiti superiore ed inferiore. Rispetto al codice del precedente esempio dovremo aggiungere, prima del comando //DATAENTRY//, le seguenti istruzioni Qcl: | |
| To enable bounds checking of the introduced data you must enable this feature putting to 1 the relevant bits of the //deflags// parameter and set in //deuplim// and //delowlim// parameters the values of the upper and lower limits. Compared to the previous example code we will add, before the //DATAENTRY// command, the following Qcl instructions: |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
e sostituire l'istruzione di impostazione del parametro deflags con: | and replace the setting instruction of the deflags parameter: |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
=== Configurare uno o più tasti di uscita dal data entry === | === Configure one or more keys to exit from data entry === |
Per abilitare l'uscita dal data entry con un tasto è necessario impostare il parametro //deExKeymask// cioè la maschera per i tasti di uscita. Per abilitare un tasto a funzionare come tasto di uscita dal data entry, è sufficiente attivare il bit corrispondente del parametro sopracitato. Quindi se vogliamo far si che si esca dal data entry con i tasti F e CLEAR serve inserire la seguente istruzione Qcl prima del comando //DATAENTRY//: | |
| To enable the output from data entry with a key You must set the //deExKeymask// parameter that is the form to exit buttons. To enable a button to function as data entry exit key, simply activate the corresponding bit of the above mentioned parameter. So if we want to ensure that you exit from data entry with the F and CLEAR keys you must insert the following //DATAENTRY// command instruction Qcl: |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
=== Verificare se il dato introdotto è nei limiti === | === Check if the introduced data is within limits === |
All'uscita dal data entry (quindi con lo stato //st_dentry// = 0), è sufficiente controllare il valore degli stati //st_uplim// e //st_lowlim// per sapere se il dato introdotto è superiore ai limiti impostati. Se //st_uplim// vale 1 significa che il valore introdotto è maggiore del limite superiore, mentre se //st_lowlim// vale 1 significa che il valore introdotto è minore del limite inferiore. Quindi controlleremo tali stati e faremo una chiamata alla subroutine ERROR (che si occuperà di visualizzare il messaggio di errore per 1 secondo) nel caso di superamento dei limiti. | |
| When you exit from the data entry (then with the //st_dentry// = 0 State), check the value of the //st_uplim// and //st_lowlim// states to know if the data introduced is in excess of the limits set. If //st_uplim// vale 1 means that the input value is greater than the upper limit, while if //st_lowlim// vale 1 means that the input value is less than the lower limit. Then we will check those states, and we will make a call to the ERROR subroutine (that will display the error message for 1 second) if the limits are exceeded. |
| |
<code QCL> | <code QCL> |
;Controllo limiti dati | ;Data limits control |
IF ( dvHMI:st_uplim OR dvHMI:st_lowlim ) | IF ( dvHMI:st_uplim OR dvHMI:st_lowlim ) |
CALL ERROR ;stampa messaggio d'errore | CALL ERROR ;print error message |
JUMP Dentry ;ritorno introduzione datai | JUMP Dentry ;return datai introduction |
ENDIF | ENDIF |
</code> | </code> |
| |
=== Controllare il tasto di uscita dal data entry === | === Check the output key from data entry === |
Controllando il parametro //deExitKey// e gli stati //st_modified// ed //st_exitcmd//, è possibile capire in quale modo si è usciti dal data entry. La seguente tabella riassume le possibili condizioni:\\ | |
^//deExitKey//^//st_exitcmd//^Descrizione| | Checking the//deExitKey// parameter and the //st_modified// and //st_exitcmd// states, you can understand in what way you are signed out from data entry. The following table summarizes the possible conditions:\\ |
|0|0|Uscita con conferma tramite pressione del tasto ENTER o tramite comando //EXITDEC//| | ^//deExitKey//^//st_exitcmd//^Description| |
|0|1|Uscita senza conferma tramite domando //EXITDE//| | |0|0|Exit with confirmation by pressing the ENTER key or by //EXITDEC// command| |
|!=0|X|Uscita senza conferma tramite pressione del tasto identificato dal valore del parametro //deExitKey//| | |0|1|Exit without confirmation by //EXITDE// command| |
| |!=0|X|Exit without confirmation by pressing the button identified by the value of the //deExitKey// parameter| |
| |
| === Check if the data has been modified === |
| |
=== Verificare se il dato è stato modificato === | To check if the introduced data has changed, simply check the //st_modified// status. It takes the 1 value If the input value is different from the previous value of the devalue parameter befor of the //DATAENTRY// command.\\ |
Per verificare se il dato introdotto è stato modificato basta semplicemente controllare lo stato //st_modified//. Esso assume valore 1 se il valore introdotto è diverso dal valore che aveva il parametro devalue prima del comando //DATAENTRY//.\\ | The full program will then: |
Il programma completo sarà quindi: | |
| |
<code QCL> | <code QCL> |
| |
IF dvHMI:deExitKey | IF dvHMI:deExitKey |
;--Uscita da data entry con tasti d'uscita | ;--Output from data entry with output keys |
dvHMI:dis6 = CHAR_E | dvHMI:dis6 = CHAR_E |
dvHMI:dis5 = CHAR_H | dvHMI:dis5 = CHAR_H |
dvHMI:dis1 = CHAR_ | dvHMI:dis1 = CHAR_ |
IF dvHMI:deExitKey EQ KEY_F | IF dvHMI:deExitKey EQ KEY_F |
dvHMI:dis0 = CHAR_F ;Pressione tasto F | dvHMI:dis0 = CHAR_F ;F key press |
ELSE | ELSE |
IF dvHMI:deExitKey EQ KEY_CLEAR | IF dvHMI:deExitKey EQ KEY_CLEAR |
dvHMI:dis0 = CHAR_C ;Pressione tasto CLEAR | dvHMI:dis0 = CHAR_C ;CLEAR key press |
ENDIF | ENDIF |
ENDIF | ENDIF |
ELSE | ELSE |
;--Uscita da data entry con conferma | ;--Output from data entry with confirm |
;--Controllo limiti | ;--Limits control |
IF ( dvHMI:st_uplim OR dvHMI:st_lowlim ) | IF ( dvHMI:st_uplim OR dvHMI:st_lowlim ) |
CALL ERROR ;stampa mesaggio d'errore | CALL ERROR ;print error message |
JUMP LABEL0 ;ritorna all'introduzione dati | JUMP LABEL0 ;return to data entry |
ENDIF | ENDIF |
;--Verifica se i dati sono stati modificati | ;--Checks if the data has changed |
IF dvHMI:st_modified | IF dvHMI:st_modified |
dvHMI:dis6 = CHAR_ ;stampa messaggio "MODIFY" | dvHMI:dis6 = CHAR_ ;print "MODIFY" message |
dvHMI:dis5 = CHAR_M | dvHMI:dis5 = CHAR_M |
dvHMI:dis4 = CHAR_O | dvHMI:dis4 = CHAR_O |
WAIT tm01 | WAIT tm01 |
ENDIF | ENDIF |
cntPieces = dvHMI:devalue ;memorizza valore introdotto | cntPieces = dvHMI:devalue ;stores entered value |
ENDIF | ENDIF |
| |
| |
SUB ERROR | SUB ERROR |
dvHMI:dis6 = CHAR_ ;stampa messaggio "ERROR" | dvHMI:dis6 = CHAR_ ;print "ERROR" message |
dvHMI:dis5 = CHAR_E | dvHMI:dis5 = CHAR_E |
dvHMI:dis4 = CHAR_R | dvHMI:dis4 = CHAR_R |
</code> | </code> |
| |
==== Creare una visualizzazione mista non ricorsiva ==== | ==== Create a mixed non-recursive visualization ==== |
| |
Si voglia creare una visualizzazione di un messaggio composto dalla stringa "Error" e da un numero identificativo dell'errore che appaia quando si verifica un errore, mentre normalmente venga visualizzato, in maniera ricorsiva, il valore di un conteggio. Per realizzare questo, sfruttiamo il funzionamento di sola visualizzazione di un valore numerico presente nella funzionalità del comando //DATAENTRY// ed abilitata impostando a 0 il bit //DE_ENABLE// del parametro //deflags//. Per semplicità, realizzeremo una condizione fittizia di errore tramite la fine di un timer caricato a 5 sec. Come vedremo, sarà importante ricordarsi di disabilitare la visualizzazione ricorsiva prima di visualizzare il messaggio di errore, altrimenti il risultato non sarà quello che ci si aspetta.\\ | You want to create a view of a message consisting of the "Error" string and an identification number of the error that appears when occurs an error, while normally appears, recursively the counter value. To achieve this, we exploit the functioning can only be displayed by a numerical value present in //DATAENTRY// command functionality and enabled by setting to 0 the //DE_ENABLE// bits of the //deflags// parameter. For simplicity, we'll create a fictitious error condition by the end of a timer uploaded to 5 sec. As will see, It will be important to remember to disable recursive view before showing the error message, otherwise the result will not be what you expect.\\ |
Il codice risulta essere: | The code is: |
| |
<code QCL> | <code QCL> |
dvHMI:dis6 = CHAR_C | dvHMI:dis6 = CHAR_C |
| |
;configura e abilita screenA | ;Configure and enable screenA |
dvHMI:ncharA = 6 | dvHMI:ncharA = 6 |
dvHMI:offsA = 0 | dvHMI:offsA = 0 |
dvHMI:scflags = dvHMI:scflags ORB SCRA_ENABLE | dvHMI:scflags = dvHMI:scflags ORB SCRA_ENABLE |
| |
tm01 = 5000 ;utilizzo del timer per causare un errore | tm01 = 5000 ;how to use the timer to cause an error |
| |
LOOP: | LOOP: |
;Errore? | ;Errore? |
IF tm01 | IF tm01 |
;disabilita screenA | ;disable screenA |
dvHMI:scflags = dvHMI:scflags ANDB ( NOT SCRA_ENABLE ) | dvHMI:scflags = dvHMI:scflags ANDB ( NOT SCRA_ENABLE ) |
CALL ERROR | CALL ERROR |
| |
SUB ERROR | SUB ERROR |
;stampa "ERROR" | ;print "ERROR" |
dvHMI:dis6 = CHAR_E | dvHMI:dis6 = CHAR_E |
dvHMI:dis5 = CHAR_R | dvHMI:dis5 = CHAR_R |
| |
| |
;stampa errore con identificativo | ;printing error with the ID |
dvHMI:deoffs = 0 | dvHMI:deoffs = 0 |
dvHMI:denchar = 2 | dvHMI:denchar = 2 |
DATAENTRY dvHMI | DATAENTRY dvHMI |
| |
;attesa 2 secondi | ;wait 2 seconds |
tm01 = 2000 | tm01 = 2000 |
WAIT tm01 | WAIT tm01 |
</code> | </code> |
| |
==== Diagnostica Ingressi ==== | ==== Diagnostic Inputs ==== |
| |
Si voglia creare una visualizzazione che rappresenti lo stato di 9 ingressi digitali. Lo stesso esempio potrà essere poi utilizzato per la rappresentazione di uscite digitali. Assegneremo perciò, ad ogni ingresso, uno dei segmenti di ciascuno dei tre digit più a destra e lo attiveremo quando il corrispondente ingresso sarà attivo.\\ | You want to create a view that represents the State of 9 digital inputs. The same example can be used for the representation of digital outputs. We will assign to each input, one of the segments of each of the three rightmost digit and we will activate when the corresponding input will be active.\\ |
La figura mostra l'assegnamento scelto per gli ingressi ed i segmenti dei digit del display: | The figure shows the assignment chose for the inputs and segments of the digits of the display: |
| |
{{:software:devices:hmi:an007:an_hmi2_01.png?nolink400|}} | {{:software:devices:hmi:an007:an_hmi2_01.png?nolink400|}} |
| |
Innanzitutto dichiareremo, nella unit di configurazione, 9 variabili di dimensione FLAG il cui valore simulerà lo stato dei 9 ingressi digitali. | First we will declare, in the configuration unit, 9 variables of FLAG dimensions whose value will simulate the condition of 9 digital inputs. |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
Dichiareremo poi anche un array global da 8 elementi che servirà per contenere i codici dei caratteri da stampare per ogni combinazione degli ingressi. | We will declare a global array to 8 items that will serve to hold character codes to print for each combination of inputs. |
| |
<code QCL> | <code QCL> |
ARRGBL | ARRGBL |
diagnTab B 8 ;tabella caratteri per diagnostica | diagnTab B 8 ;character table for Diagnostics |
</code> | </code> |
| |
Infatti per ogni gruppo di tre ingressi associati ad uno dei tre digit sul display avremo 8 possibili combinazioni. La tabella riassume, ad esempio, per la combinazione degli ingressi I7,I8 ed I9, i possibili lo stati del digit associato: | In fact, for each group of three inputs associated with one of the three digits on the display we will have 8 possible combinations. For example, the table summarizes the possible States of the digit associated with, the combination of inputs I7,I8 ed I9: |
| |
^I7^I8^I9^Display^ | ^I7^I8^I9^Display^ |
|1|1|1|$| | |1|1|1|$| |
| |
Servirà infine anche la definizione di alcune costanti da utilizzare come maschera per bit generici di un byte: | Will finally also defining some constants to be used as a mask for generic bits of a byte: |
| |
<code QCL> | <code QCL> |
</code> | </code> |
| |
Il codice completo per ottenere la funzione di diagnostica è: | The complete code to obtain the diagnostic function is: |
| |
<code QCL> | <code QCL> |
;inizializza tabella | ;Initializes table |
diagnTab[1] = CHAR_ | diagnTab[1] = CHAR_ |
diagnTab[2] = CHAR_UP | diagnTab[2] = CHAR_UP |
diagnTab[8] = CHAR_LOWUPCE | diagnTab[8] = CHAR_LOWUPCE |
| |
;stampa messaggio "INP." | ;print "INP." message |
hmi:dis6 = CHAR_I | hmi:dis6 = CHAR_I |
hmi:dis5 = CHAR_N | hmi:dis5 = CHAR_N |