WebHMI operuje na 8-, 16- lub 32-bitowych zmiennych. Zdarza się, że sterowniki PLC lub mierniki energii wykorzystują 64-bitowe zmienne typu Long Real, czy też zwane inaczej liczby zmiennoprzecinkowe podwójnej precyzji. Jak na to popatrzymy to można stwierdzić, że po prostu się nie da odczytać takich zmiennych. Jednak kilka sprytnych funkcji zapisanych w skryptach LUA pozwolą na odczytanie zmiennych Long Real. W tym artykule pokażemy przykład odczytu zmiennej LReal ze sterownika Siemens S7-1200. Podobny sposób można wykorzystać także przy innych protokołach komunikacyjnych.
Zmienna 32-bitowa vs zmienna 64-bitowa
Jakie są różnice między tymi dwoma typami ? Najważniejszą z nich jest liczba bitów. Liczba 64-bitowa (8 bajtów) posiada 1 bit znaku, 11 bitów wykładnika oraz 52 bity mantysy. Dzięki większej liczbie bitów zakres i dokładność podawanej zmiennej rzeczywistej zdecydowanie wzrasta.
Odczyt liczby zapisanej w taki sposób jest możliwe dzięki zależności:
Liczba 32-bitowa (4 bajty) posiada 1 bit znaku, 8 bitów wykładnika i 23 bity mantysy. W przeciwieństwie do zmiennych rzeczywistych typu LReal posiada mniejszy zakres. Jednak liczby 32-bitowe są najczęściej wykorzystywane. Dzięki ich optymalizacji są one szybciej przetwarzane, zapisywanie i odczytywane przez procesory.
Zależność odczytywania liczby 32 wygląda następująco:
Przykład obliczania liczny za pomocą powyższego wzoru:
Jak połączyć się ze sterownikiem S7-1200?
Cała instrukcja komunikacji WebHMI ze sterownikiem Siemens S7-1200 znajduje się tutaj. Została stworzona zmienna Liczba typu LReal (64-bitowa) w Data Block (DB1). To właśnie ją będziemy odczytywać za pomocą naszego WebHMI.
Zmienne w WebHMI
W naszym panelu WebHMI tworzymy 2 nowe połączenia wchodząc w zakładkę Ustawienia → Zmienne. Jedno połączenie ze sterownikiem Siemens, gdzie model urządzenia ustawiamy na Siemens Siematic S7, zmieniamy protokół na S7 Comm (TCP) oraz wprowadzamy adres IP urządzenia. Drugim dodanym połączeniem jest połączenie zmiennych wewnętrznych WebHMI, w którym model urządzenia to Internal WebHMI Registers, a protokół WebHMI.
Aby odczytać zmienną 64-bitową o nazwie Liczba za pomocą WebHMI musimy odczytać 2 zmienne 32-bitowe. W połączeniu S7-1200 zostały stworzone 2 zmienne o nazwie DB1.DB0 oraz DB1.DB4. Do ułatwienia dalszej pracy w skryptach ustawiono ich aliasy na Liczba1 oraz Liczba2.
Trzecia i ostatnia zmienna, która jest nam potrzebna, będzie wyświetlać wynik całej operacji. Dodajemy w połączeniu WebHMI nową zmienną o nazwie wynik, podajemy jej adres (D0) oraz (opcjonalnie) alias używany w skryptach (wynik).
Wszystkie dodane połączenia i zmienne prezentują się następująco:
Skrypty WebHMI
Aby uprościć korzystanie z przedstawionych poniżej funkcji wykorzystamy bibliotekę Lua.
W pierwszej kolejności musimy przygotować bibliotekę, w której będą znajdować się funkcje realizujące naszą konwersję. W tym celu wchodzimy w Ustawienia → Skrypty i dodajemy nowy skrypt o nazwie Zmienne64.lib i typie Biblioteka dla innych programów. Jej treść prezentuje się tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
function Hex2Bin(s) -- s -> hexadecimal string local ret = "" local i = 0 local hex2bin = { ["0"] = "0000", ["1"] = "0001", ["2"] = "0010", ["3"] = "0011", ["4"] = "0100", ["5"] = "0101", ["6"] = "0110", ["7"] = "0111", ["8"] = "1000", ["9"] = "1001", ["a"] = "1010", ["b"] = "1011", ["c"] = "1100", ["d"] = "1101", ["e"] = "1110", ["f"] = "1111" } for i in string.gfind(s, ".") do i = string.lower(i) ret = ret..hex2bin[i] end return ret end function LReal2Real(id1_in, id2_in, id_out) local a, b, test_bity, rejestr, value; --odczyt rejestrów 32bitowych i zamiana na stringi jako hex a = string.format("%x", GetReg(id1_in)); b = string.format("%x", GetReg(id2_in)); -- wykorzystanie symbolu .. połączy oba stringi w jeden, dodatkowe zera są potrzebne przy konwersji liczb -- z mniejszą ilością miejsc po przecinku rejestr = a .. b .. "00000000"; -- zamiana stringu hex na string z bitami test_bity = Hex2Bin(rejestr); -- podział na znak, wykładnik i mantysę sign = string.sub(test_bity,1,1) exponent = string.sub(test_bity,2,12) mantissa = string.sub(test_bity,13) -- obliczanie wartości wykładnika local exp_value = -1023; for i = 1,11 do exp_value = tonumber(string.sub(exponent,i,i),2)*2^(11-i) + exp_value; end -- obliczanie wartości mantysy local mantissa_value = 0; for i = 1,52 do mantissa_value = tonumber(string.sub(mantissa,i,i),2)*(2^(-i)) + mantissa_value; end -- obliczenie ostatecznej wartości z uwzględnieniem znaku if tonumber(sign,2) == 0 then value = (mantissa_value+1)*2^exp_value; else value = -1*(mantissa_value+1)*2^exp_value; end -- zapis wartości do nowej zmiennej WriteReg(id_out, value); --(@WebHMI) end |
1 |
DEBUG(rejestr); |
Teraz dodajemy skrypt, w którym wywołamy stworzoną funkcję o nazwie LReal2Real(). Nazwa utworzonego skryptu to Główny, a jego typ Wykonaj w każdym cyklu urządzenia. Pamiętajmy, aby na samym początku dołączyć stworzoną bibliotekę.
1 2 3 4 5 6 |
include "Zmienne64.lib" function main (userId) -- Add your code here LReal2Real('Liczba1','Liczba2','wynik'); end |
Po zapisaniu skryptów WebHMI odczyta, przetworzy i zapisze otrzymaną zmienną w zmiennej wynik. Musimy jednak pamiętać o tym, że WebHMI przechowuje odczytaną wartość jako zmienna 32-bitowa, zatem precyzja takiej zmiennej może być niższa.