Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
en:appnote:an007 [2017/04/28 17:55] – [Configurare uno o più tasti di uscita dal data entry] qem103 | en:appnote:an007 [2019/08/29 17:01] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== AN007 - Application examples of the HMI2 device ====== | ||
+ | In this chapter we will analyze some programming examples useful to be able to perform basic functionality with the help of the HMI2 device. How will only use an D221 hardware platform, but the applicability of such examples, with any small changes, is extended to all microQMove hardware. It's a good idea, before using this device, define a constant value series (in the CONST section of the configuration unit of the Qcl application) to be inserted in the module configuration to improve readability and maintenance of the application developed. | ||
+ | |||
+ | <code QCL> | ||
+ | ; | ||
+ | ;Definition of values associated with the keys | ||
+ | ; | ||
+ | CONST | ||
+ | |||
+ | KEY_ENTER 1 ; enter key | ||
+ | KEY_CLEAR 8 ; clear key | ||
+ | KEY_PLUS | ||
+ | KEY_MINUS 32 ; - key | ||
+ | KEY_F | ||
+ | |||
+ | ; | ||
+ | ;Definition of values associated with the leds | ||
+ | ; | ||
+ | |||
+ | LED_L1 | ||
+ | LED_L2 | ||
+ | LED_L3 | ||
+ | LED_L4 | ||
+ | LED_F | ||
+ | LED_AL | ||
+ | |||
+ | ; | ||
+ | ;Definition of values associated with the display characters | ||
+ | ; | ||
+ | |||
+ | CHAR_ | ||
+ | CHAR_0 | ||
+ | CHAR_1 | ||
+ | CHAR_2 | ||
+ | CHAR_3 | ||
+ | CHAR_4 | ||
+ | CHAR_5 | ||
+ | CHAR_6 | ||
+ | CHAR_7 | ||
+ | CHAR_8 | ||
+ | CHAR_9 | ||
+ | CHAR_A | ||
+ | CHAR_B | ||
+ | CHAR_C | ||
+ | CHAR_D | ||
+ | CHAR_E | ||
+ | CHAR_F | ||
+ | CHAR_G | ||
+ | CHAR_H | ||
+ | CHAR_I | ||
+ | CHAR_J | ||
+ | CHAR_K | ||
+ | CHAR_L | ||
+ | CHAR_M | ||
+ | CHAR_N | ||
+ | CHAR_O | ||
+ | CHAR_P | ||
+ | CHAR_Q | ||
+ | CHAR_R | ||
+ | CHAR_S | ||
+ | CHAR_T | ||
+ | CHAR_U | ||
+ | CHAR_V | ||
+ | CHAR_W | ||
+ | CHAR_Y | ||
+ | CHAR_UP | ||
+ | CHAR_CENTER | ||
+ | CHAR_LOWER | ||
+ | CHAR_UPCEN | ||
+ | CHAR_LOWCEN | ||
+ | CHAR_LOWUP | ||
+ | CHAR_LOWUPCE | ||
+ | CHAR_NONE | ||
+ | CHAR_POINT | ||
+ | </ | ||
+ | |||
+ | This methodology is important to apply it to all parameters formats from bit fields such as //scflags// or // | ||
+ | |||
+ | <code QCL> | ||
+ | SCRA_ENABLE | ||
+ | SCRB_ENABLE | ||
+ | SCRC_ENABLE | ||
+ | SCRA_DISSIGN | ||
+ | SCRB_DISSIGN | ||
+ | SCRC_DISSIGN | ||
+ | SCRA_DISLZB | ||
+ | SCRB_DISLZB | ||
+ | SCRC_DISLZB | ||
+ | |||
+ | DE_ENABLE | ||
+ | DE_DISSIGN | ||
+ | DE_ENALIM | ||
+ | </ | ||
+ | |||
+ | Insert then the HMI2 device with sampling time of 5ms in the specific section: | ||
+ | |||
+ | <code QCL> | ||
+ | INTDEVICE | ||
+ | |||
+ | dvHMI HMI2 5 | ||
+ | </ | ||
+ | |||
+ | In the following examples, the device will always be dvHMI. | ||
+ | |||
+ | ==== Wait for a KeyPress or more keys for some time ==== | ||
+ | |||
+ | You want to write a Qcl program wait for the keystroke F for executing a subroutine. Simply verify that the //key// parameter having the bit for the F key active: | ||
+ | |||
+ | <code QCL> | ||
+ | MAIN: | ||
+ | IF ( dvHMI:key ANDB KEY_F ) | ||
+ | CALL MyFUNC | ||
+ | ENDIF | ||
+ | WAIT 1 | ||
+ | JUMP MAIN | ||
+ | |||
+ | SUB MyFUNC | ||
+ | ; | ||
+ | ;subroutine code | ||
+ | ; | ||
+ | ENDSUB | ||
+ | </ | ||
+ | |||
+ | This code does not ensure that it is only pressed the F button: the MyFUNC function may also be called if they were pressed together with F key also other keys. To ensure the exclusivity of the pressure of F the code becomes: | ||
+ | |||
+ | <code QCL> | ||
+ | IF ( dvHMI:key EQ KEY_F ) | ||
+ | CALL MyFUNC | ||
+ | ENDIF | ||
+ | </ | ||
+ | |||
+ | You want now write code that listens for the both pressure of the CLEAR and ENTER keys for at least 2 seconds: | ||
+ | |||
+ | <code QCL> | ||
+ | IF ( dvHMI:key EQ (KEY_ENTER+KEY_CLEAR) ) | ||
+ | IF tm01:remain EQ 0 ;check expired timer | ||
+ | CALL MyFUNC | ||
+ | ENDIF | ||
+ | ELSE | ||
+ | tm01=2000 | ||
+ | ENDIF | ||
+ | </ | ||
+ | |||
+ | ==== Create a recursive view ==== | ||
+ | |||
+ | You want to write a program that enables a Qcl recursive view on the leftmost 4 display with sign and 2 decimal places. We decide for ease to use screenA. We must first set the number of characters you want to shown bearing in mind that the sign is a character; we can therefore say that the number of characters is the number of digits of the display that are occupied and manipulated by the view. The maximum and minimum values that will allow us to shown are 9999 and -999. If the data to be showed is less than this minimum value or greater than this maximum value, the display shows the out of range characters '' | ||
+ | We'll set: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | We will put our view on the leftmost display setting the offset value to: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI:offsA = dvHMI: | ||
+ | </ | ||
+ | |||
+ | We set decimal point position to 2: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | Enable recursive view screenA by setting the corresponding enable of the scflags variable: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | Executing the above statement We automatically disabled the other two recursive views and we have enabled the display of the sign on screenA. In case we wanted to preserve the States of other screenB and screenC views we should have written: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | Finally, you can simply update the screenA variable with the value you want to shown and normally contained in another variable of our program (in the example, suppose we use a variable with the //count// name): | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | The update operation of screenA must be continuously performed by our program with the refresh rate more appropriate for reasons of functionality that the programmer has planned for that variable. | ||
+ | |||
+ | ==== Create a text view ==== | ||
+ | |||
+ | You want to write a Qcl program that writes on display " | ||
+ | |||
+ | <code QCL> | ||
+ | ;Print " | ||
+ | dvHMI:dis6 = CHAR_ | ||
+ | dvHMI:dis5 = CHAR_ | ||
+ | dvHMI:dis4 = CHAR_H | ||
+ | dvHMI:dis3 = CHAR_E | ||
+ | dvHMI:dis2 = CHAR_L | ||
+ | dvHMI:dis1 = CHAR_L | ||
+ | dvHMI:dis0 = CHAR_O | ||
+ | </ | ||
+ | |||
+ | ^: | ||
+ | |||
+ | ==== Create multiple recursive views mixed with text displays ==== | ||
+ | |||
+ | You want to create a view consists of two fixed texts and two recursive values. As an example, you shown a time in seconds and a program number. The desired show might be: "t51 Pr2" where " | ||
+ | First we print the texts: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI:dis6 = CHAR_T | ||
+ | dvHMI:dis3 = CHAR_ | ||
+ | dvHMI:dis2 = CHAR_P | ||
+ | dvHMI:dis1 = CHAR_R | ||
+ | </ | ||
+ | |||
+ | Then we set the data for the numerical display of the time through the screenA. | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | dvHMI:offsA = 4 | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | We then the data for the numerical display of the program using the screenB. | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | dvHMI:offsB = 0 | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | We enable the two views: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | Then recursively we will update the view data: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | ==== Create a simple data input ==== | ||
+ | |||
+ | 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 // | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI:dis6 = CHAR_C | ||
+ | dvHMI:dis5 = CHAR_P | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | 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> | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | 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 // | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | DATAENTRY dvHMI | ||
+ | </ | ||
+ | |||
+ | At this point the most significant digit on the display will start flashing the value of // | ||
+ | |||
+ | <code QCL> | ||
+ | WHILE (dvHMI: | ||
+ | WAIT 1 | ||
+ | ENDWHILE | ||
+ | cntPieces = dvHMI: | ||
+ | </ | ||
+ | |||
+ | At this point the// | ||
+ | |||
+ | ==== Create a complex data introduction ==== | ||
+ | |||
+ | 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: | ||
+ | |||
+ | * check that the figure is between 1 to 1000 and otherwise show " | ||
+ | * 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 | ||
+ | * 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 | ||
+ | * print for a second the " | ||
+ | |||
+ | === Control data limits === | ||
+ | |||
+ | 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 // | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | and replace the setting instruction of the deflags parameter: | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | === Configure one or more keys to exit from data entry === | ||
+ | |||
+ | To enable the output from data entry with a key You must set the // | ||
+ | |||
+ | <code QCL> | ||
+ | dvHMI: | ||
+ | </ | ||
+ | |||
+ | === Check if the introduced data is within limits === | ||
+ | |||
+ | When you exit from the data entry (then with the // | ||
+ | |||
+ | <code QCL> | ||
+ | ;Data limits control | ||
+ | IF ( dvHMI: | ||
+ | CALL ERROR ; | ||
+ | JUMP Dentry ; | ||
+ | ENDIF | ||
+ | </ | ||
+ | |||
+ | === Check the output key from data entry === | ||
+ | |||
+ | Checking the// | ||
+ | ^// | ||
+ | |0|0|Exit with confirmation by pressing the ENTER key or by //EXITDEC// command| | ||
+ | |0|1|Exit without confirmation by //EXITDE// command| | ||
+ | |!=0|X|Exit without confirmation by pressing the button identified by the value of the // | ||
+ | |||
+ | === Check if the data has been modified === | ||
+ | |||
+ | To check if the introduced data has changed, simply check the // | ||
+ | The full program will then: | ||
+ | |||
+ | <code QCL> | ||
+ | LABEL0: | ||
+ | |||
+ | dvHMI:dis6 = CHAR_C | ||
+ | dvHMI:dis5 = CHAR_P | ||
+ | dvHMI:dis4 = CHAR_ | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | DATAENTRY dvHMI | ||
+ | |||
+ | WHILE (dvHMI: | ||
+ | WAIT 1 | ||
+ | ENDWHILE | ||
+ | |||
+ | IF dvHMI: | ||
+ | ;--Output from data entry with output keys | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | IF dvHMI: | ||
+ | dvHMI: | ||
+ | ELSE | ||
+ | IF dvHMI: | ||
+ | dvHMI: | ||
+ | ENDIF | ||
+ | ENDIF | ||
+ | ELSE | ||
+ | ;--Output from data entry with confirm | ||
+ | ;--Limits control | ||
+ | IF ( dvHMI: | ||
+ | CALL ERROR ; | ||
+ | JUMP LABEL0 ; | ||
+ | ENDIF | ||
+ | ;--Checks if the data has changed | ||
+ | IF dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | tm01 = 1000 | ||
+ | WAIT tm01 | ||
+ | ENDIF | ||
+ | cntPieces = dvHMI: | ||
+ | ENDIF | ||
+ | |||
+ | MAIN: | ||
+ | WAIT 1 | ||
+ | JUMP MAIN | ||
+ | |||
+ | |||
+ | SUB ERROR | ||
+ | dvHMI:dis6 = CHAR_ | ||
+ | dvHMI:dis5 = CHAR_E | ||
+ | dvHMI:dis4 = CHAR_R | ||
+ | dvHMI:dis3 = CHAR_R | ||
+ | dvHMI:dis2 = CHAR_O | ||
+ | dvHMI:dis1 = CHAR_R | ||
+ | dvHMI:dis0 = CHAR_ | ||
+ | tm01 = 1000 | ||
+ | WAIT tm01 | ||
+ | ENDSUB | ||
+ | |||
+ | END | ||
+ | </ | ||
+ | |||
+ | ==== Create a mixed non-recursive visualization ==== | ||
+ | |||
+ | You want to create a view of a message consisting of the " | ||
+ | The code is: | ||
+ | |||
+ | <code QCL> | ||
+ | MAIN: | ||
+ | |||
+ | ;stampa " | ||
+ | dvHMI:dis6 = CHAR_C | ||
+ | |||
+ | ;Configure and enable screenA | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | |||
+ | tm01 = 5000 ;how to use the timer to cause an error | ||
+ | |||
+ | LOOP: | ||
+ | |||
+ | dvHMI: | ||
+ | |||
+ | ;Errore? | ||
+ | IF tm01 | ||
+ | ;disable screenA | ||
+ | dvHMI: | ||
+ | CALL ERROR | ||
+ | errNum = errNum + 1 | ||
+ | JUMP MAIN | ||
+ | ENDIF | ||
+ | |||
+ | WAIT 1 | ||
+ | JUMP LOOP | ||
+ | | ||
+ | SUB ERROR | ||
+ | ;print " | ||
+ | dvHMI:dis6 = CHAR_E | ||
+ | dvHMI:dis5 = CHAR_R | ||
+ | dvHMI:dis4 = CHAR_R | ||
+ | dvHMI:dis3 = CHAR_O | ||
+ | dvHMI:dis2 = CHAR_R | ||
+ | |||
+ | |||
+ | ;printing error with the ID | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | dvHMI: | ||
+ | DATAENTRY dvHMI | ||
+ | |||
+ | ;wait 2 seconds | ||
+ | tm01 = 2000 | ||
+ | WAIT tm01 | ||
+ | |||
+ | ENDSUB | ||
+ | | ||
+ | END | ||
+ | </ | ||
+ | |||
+ | ==== Diagnostic Inputs ==== | ||
+ | |||
+ | 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.\\ | ||
+ | The figure shows the assignment chose for the inputs and segments of the digits of the display: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | 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> | ||
+ | GLOBAL | ||
+ | gfInp01 F | ||
+ | gfInp02 F | ||
+ | gfInp03 F | ||
+ | gfInp04 F | ||
+ | gfInp05 F | ||
+ | gfInp06 F | ||
+ | gfInp07 F | ||
+ | gfInp08 F | ||
+ | gfInp09 F | ||
+ | </ | ||
+ | |||
+ | 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> | ||
+ | ARRGBL | ||
+ | diagnTab B 8 ; | ||
+ | </ | ||
+ | |||
+ | 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^ | ||
+ | |0|0|0| | | ||
+ | |0|0|1| | | ||
+ | |0|1|0|-| | ||
+ | |0|1|1|=| | ||
+ | |1|0|0| | | ||
+ | |1|0|1|~| | ||
+ | |1|1|0|*| | ||
+ | |1|1|1|$| | ||
+ | |||
+ | Will finally also defining some constants to be used as a mask for generic bits of a byte: | ||
+ | |||
+ | <code QCL> | ||
+ | CONST | ||
+ | |||
+ | ;-- Generic bit field mask --------- | ||
+ | B_00 & | ||
+ | B_01 & | ||
+ | B_02 & | ||
+ | B_03 & | ||
+ | B_04 & | ||
+ | B_05 & | ||
+ | B_06 & | ||
+ | B_07 & | ||
+ | </ | ||
+ | |||
+ | The complete code to obtain the diagnostic function is: | ||
+ | |||
+ | <code QCL> | ||
+ | ; | ||
+ | diagnTab[1] = CHAR_ | ||
+ | diagnTab[2] = CHAR_UP | ||
+ | diagnTab[3] = CHAR_CENTER | ||
+ | diagnTab[4] = CHAR_UPCEN | ||
+ | diagnTab[5] = CHAR_LOWER | ||
+ | diagnTab[6] = CHAR_LOWUP | ||
+ | diagnTab[7] = CHAR_LOWCEN | ||
+ | diagnTab[8] = CHAR_LOWUPCE | ||
+ | |||
+ | ;print " | ||
+ | hmi:dis6 = CHAR_I | ||
+ | hmi:dis5 = CHAR_N | ||
+ | hmi:dis4 = CHAR_P ORB CHAR_POINT | ||
+ | |||
+ | MAIN: | ||
+ | hmi:dis2 = diagnTab[(gfInp01 * B_00 + gfInp02 * B_01 + gfInp03 * B_02) + 1] | ||
+ | hmi:dis1 = diagnTab[(gfInp04 * B_00 + gfInp05 * B_01 + gfInp06 * B_02) + 1] | ||
+ | hmi:dis0 = diagnTab[(gfInp07 * B_00 + gfInp08 * B_01 + gfInp09 * B_02) + 1] | ||
+ | |||
+ | WAIT 1 | ||
+ | JUMP MAIN | ||
+ | END | ||
+ | </ |