This is an old revision of the document!
To understand the principles of WebHMI operation, let's analyze how its kernel works.
Schematically, the structure of the core of the system can be represented as follows:
The kernel works cyclically. This means that all actions are performed sequentially. If delays occur at some stage, this affects the execution time of the entire cycle.
Let's look at each of the blocks in this diagram.
Immediately after the system is booted up, the project is loaded into the main memory. At that moment, the values of all volatile registers are reset to zero, the state of all events is set to 'not executed'. If the user makes any change to the settings of registers, connections, events, scripts, etc. the kernel re-reads the configuration after the end of the current cycle. All the values of the registers will be reset, events will also be interrupted. Therefore, changing the configuration of the project during commercial operation can cause interruption of events and resetting of registers that are in energy-dependent memory. We do not recommend changing the project 'on the fly' without extreme need.
When the project settings are read, the kernel enters the main loop.
At the beginning of the cycle, the new values are written to the registers. The system has a special queue for writing new values to the registers. There are 2 ways to write data to the register - through the API and through scripts. In both cases, the recording does not occur when the request comes (because the system may not be ready for this, for example, the RS-485 is already exchanging with the PLC) and later, at the appropriate time. A write request is sent to the queue. All write requests will be executed at the beginning of the next main loop.
Further, the registers are read from external devices and internal registers of WebHMI. Registers are read in groups. Grouping occurs by their connection. For example, if the project has a connection to a Delta PLC, Siemens PLC and internal WebHMI registers, the reading will look like this:
Internal WebHMI registers are always read last (since they contain registers C0, C1, C2 … in which the read errors from the remaining connections are stored).
Immediately after reading, the necessary value transformations (multiplication, constant additions, casting, etc.) take place.
If there is a stabilization pause for any of the connections, then there will be a corresponding pause before reading the register group of this connection. This is sometimes necessary for the stable operation of heterogeneous devices on one RS-485 bus. Without this pause, some devices may not be able to determine the start of the message frame and skip the first packet to read the first register.
Also, the connections have a Timeout setting. This is the time that the system will wait for a response from the devices on its request. If the devices did not respond within the specified time period or answered the entire packet of data, the system will assume that the register has not been read. Its value will be set to -1, and the register status to invalid.
This means that if there is no connection with one of the external devices, the total polling time (the minimum length of the main loop) will increase by Timeout × The number of registers in this connection.
Here is an example. We have a connection to the Delta SX2 PLC via ModBus RTU. We read from it 5 registers at a speed of 115200. Timeout is set to 100 ms. The average time for reading all five registers is 30 ms (you can see it in the internal register of WebHMI T1). If the connection to the PLC is lost for any of the reasons, then the average read time of all five registers will theoretically increase to 5 × 100 ms = 500 ms (and in practice will be approximately 525 ms).
This means that if there is polling of an unconnected device in the project, then this will slow the entire cycle for a significant amount of time. If it is necessary to minimize this delay, then it is necessary to maximize the exchange rate and reduce Timeout and Stabilization pause. But the best thing is to either reconnect with the device or disconnect this connection in the settings.
After the registers have been read, the kernel executes the scripts. Scripts (or programs) are carried out very quickly and there should not be delays here with a reasonable number and complexity of scenarios. The only feature that you should pay attention to is the difference in the operation mechanism of the Set and Write operations.
The Set operation will change the value of the specified register immediately, at the same place in the main loop. And it will only change the value in the kernel's RAM. The new value will not be written to external devices and will only be available until the end of the current cycle.
The operation Write does almost everything as Set does with the only difference that it adds a command of writing a new value to the write queue. And at the beginning of the next cycle, this value will be written to the appropriate register of the external device.
Note that if there is a condition in the script and any register from this condition has not been read in the current loop, then this condition will not be handled. And, accordingly, actions from this condition will not be performed.
By this point in the main loop, the values of all the registers have already been computed and will not change later. Therefore, it is at this point that states (invalid / disabled / normal / warning / alert) are calculated for each register .
After all data is collected and prepared, the mechanism for identifying and processing events is triggered.
Event processing starts with checking the condition of the event. Similar to scripts, if any register from the condition was not read in the current loop, then this condition will not be handled. And accordingly the whole event will not be processed.
If the event does not have an extension in time, then the condition for its occurrence is checked in each cycle. And each time this condition is met, the actions for that event will be executed. In each subsequent cycle, if the condition is fulfilled again, then this will be a new occurrence of the event and the actions will be performed again.
If the event has a length in time, then it has an execution state. This is the flag that tells the kernel that the condition is met. Such an event can start executing in one cycle and will end in the other. It can last as long as you like (but with any change to the configuration of the WebHMI project, this flag will necessarily be reset).
When the condition of the event start is fulfilled, the execution flag is set to true. If the end condition (if it is set) or when the condition of the beginning is not fulfilled (if the end condition is not specified), the flag is reset to false.
While this flag is true, all actions for this event are executed. This flag can also be read from internal WebHMI registers at ESx addresses, where x is the event ID. Note that the first “true” value will be calculated in the scan followed the one in which this value was set to true.
Besides the actions available for events, there is a record of information about the event in the database. It should be understood that this operation is resource-intensive. Therefore, it is recommended to write data as rarely as possible. And collect only the necessary data. It makes no sense to write all the registers to the database in each cycle, if it is enough to collect data on the five required registers with an interval of 5 seconds. Also, enhancing too much data details will likely lead to a heavy load on the SD card and its increased wear.
So follow the common sense in data collection and gather only the data that is really needed in your project.
One of the options when saving event data is to record a slice of register values every N seconds. In fact, it is implemented so that the recording will occur no more often than every N seconds from the last record in the database. Here it is necessary to explain the peculiarity of the operation of this interval. It is best to do this with an example.
Example. The kernel reads 150 ModBus registers, the average cycle length is 1.3 seconds. The event is set to record data every 5 seconds. Assume that the event is executed for the first time in T + 0.0 seconds. The data was written to the database also in T + 0.0 seconds.
In the next cycle, the event is still running. The time from the last recording is T + 1.3 seconds. 1.3< 5 sec. so writing to the database does not happen. In the next event cycle, the event is still running. The time since the last recording is T + 2.6 seconds. 2.6 < 5 sec. so writing to the database does not happen. In the next cycle, the event is still running. The time from the last recording is T + 3.9 seconds. 3.9 < 5 sec. so writing to the database does not happen. In the next cycle, the event is still running. The time from the last record is T + 5.2 seconds. 5.2 > 5 sec. so the record in the database will occur. Next, the system will compare the time with the moment T + 5.2.
Note that the actual time between records will be 5.2 seconds and not 5. Because the system displays the time with a second accuracy, this can cause the time between records to be displayed as 6 seconds, and for some variations even 7 seconds (for example, the first record was in T + 0.9 and the second in T + 6.1).
I.e. due to the fact that the length of the cycle can be unstable, then the actual data recording interval will also depend on this length. The system will behave optimally if the specified interval of the interrogation of devices (Communication interval) exceeds the actual length of the cycle and the recording in the database is conducted with a multiple interval (Communication interval).
After processing the events, the kernel will prepare a list of all the registers, their states and values, and pass it to the API. After that, the responses from the API about the current values of the registers will contain the data obtained in the current cycle.
At this stage of the cycle, the current values of the registers are written to the log. Only those registers for which the corresponding option is included are written to the log. If the option to record graphs for the register is enabled, then data is recorded for plotting.
Recording to an SD card is a slow operation. Therefore, recording a large number of values with a high frequency of changes can take a significant amount of time and system resources. It also consumes an SD card resource.
Therefore, it is recommended to write to the log only those registers that are really needed. We also recommend writing them not too often. Recording 10-20 parameters every second can significantly load the system, reduce the responsiveness of the interface, increase the cycle length.
After all the operations have been completed, the system determines how much time was actually spent for the current cycle. If this time is less than the Communication interval setting, the system will pause for the difference [Communication interval - actual time] so that the total cycle length is exactly the time specified in the Communication interval.
This means that if the actual cycle time is greater than the Communication interval, the system will not pause and will not be able to poll the devices with the specified periodicity.
If it is necessary to “fit” the specified interval, then there are several ways of optimization:
At the time when the WebHMI was invented, it supposed to be used in relatively small projects. But with time, more and more customers installed them for quite big projects. Also, the functionality of the front-end part has been increasing constantly, so that when you're going to use it in the project with thousands of tags with the device fw above 3.5, you should remember about finite platform resources you have. Below there are several considerations you may follow to keep you project fast and responsive:
Each register in the project has a lot of configuration data associsted with it, the bigger the register tree, the more load will lay upon the system. That may slow down the response when you work with the register tree. Organize your register tree in categorites.
function UpdReg(reg, new_value) local cur_value = R(reg) if (not cur_value) or (not new_value) or (cur_value == new_value) then return false else WriteReg(reg, new_value) end end
There is a metric register in the internal register showing mean number of the processes in the queue relative to the running process. There are 1, 5, 15 minutes mean paratemer. In a steady state, you 15 minutes metric should be below 1.