2018-09-21

VIRTUINO w mikroprocesorze

Patrząc na logikę VIRTUINO chciałoby się rzec - mikrokontroler rządzi!. Ale to banalnie oczywiste stwierdzenie wynika wprost z braku nadzorującego system serwera. Kto więc ma głos decydujący w tej sieci? Nikt. VIRTUINO poradził sobie z centralnym zarządzaniem danymi - rezygnując z niego i lokując elementy serwera w poszczególnych mikroprocesorach. A że żaden z tych serwerów nie ma roli dominującej otrzymujemy, poniekąd przy okazji, rozproszoną strukturę sterowania. Genialnie proste i niezawodne rozwiązanie. Co tak naprawdę zawiera biblioteka VIRTUINO w naszym ESP8266 czy ESP32 postaram się pokazać w dzisiejszym wpisie.


Najpierw uwaga.
Opis biblioteki VIRTUNO będzie odnosił się jedynie do modułów z procesorem ESP8266. Pominę instalacje VIRTUINO na inne platformy Arduino (choć jest ona bardzo zbliżona do ESP). Używanie dwóch mikroprocesorów (jakiegoś Arduino + ESP) uważam za elektroniczny bezsens i marnotrawstwo szczególnie gdy 8 bitowy mikrus typu UNO czy NANO próbuje rządzić 32 bitową maszyną.  Należy przyjąć do wiadomości, że jedynym sensownym rozwiązaniem dla domowych modułów automatyki w systemach rozproszonych jest któryś z modułów ESP8266. A komu będzie za mało dopłaci 3$ i kupi sobie dwurdzeniowy ESP32. Od dziś (do odwołania) zapominamy na tym blogu o klasycznych płytkach ARDUINO z procesorem ATMELa pardon MICROCHIPa.

Jak już wspominałem Ilias Lamprou za podstawę swojego programu przyjął powszechnie dostępną bibliotekę obsługi TCP/IP zawierającą serwer WWW. Na jej bazie stworzył prosty protokół komunikacyjny i obudował to wszystko niewielką ilością procedur wymiany danych. Można więc rzec, iż cały program VIRTUINO w mikrokontrolerze składa się z trzech elementów:

  1. Moduł komunikacji zewnętrznej na bazie serwera WWW
  2. Pamięć pinów wirtualnych
  3. Moduł komunikacji wewnętrznej


Ad 1. Moduł komunikacji zewnętrznej na bazie serwera WWW


Ten moduł biblioteki VIRTUINO jest praktycznie niewidoczny dla użytkownika. Po zdefiniowaniu i uruchomieniu serwera WWW procedurami

WiFiServer server(8000);
Virtuino_ESP_WifiServer virtuino(&server); 
virtuino.password = "1234";            

server.begin();

moduł komunikacji z serwerem WWW działa w tle programu poprzez cyklicznie wywoływaną procedurę

  virtuino.run();

W konfiguracji serwera WWW możemy ustawić jego port  (tu 8000) oraz hasło identyfikacyjne serwera ("1234").

Moduł komunikacji zewnętrznej odbiera cyklicznie wysyłane żądania od klienta. Żądania są dwojakiego rodzaju:
- ustawienia pinu (portu) rzeczywistego lub wirtualnego
- odczytu wartości pinu rzeczywistego lub wirtualnego

Biblioteka VIRTUINO ma więc możliwość operowania na dwu rodzajach danych : pinach (portach) rzeczywistych mikrokontrolera i zmiennych zawartych w buforze pinów zwanych pinami wirtualnymi. Pierwszy sposób został przewidziany dla początkujących adeptów mikroprocesorowej elektroniki choć jego stosowanie nie jest tak łatwe i przyjemne jak np. w BLYNKu .
Jest to szczególnie atrakcyjny sposób sterowania portami mikrokontrolera gdyż nie ma wymaga dodawania kodu użytkownika poza dołączeniem biblioteki VIRTUINO.

Jednak manipulacja portami rzeczywistymi mikrokontrolera wymaga dopasowania oznaczeń przesyłanych od klienta z rzeczywistymi pinami procesora. Mapowanie tych oznaczeń definiuje się w bibliotece programu i nie jest to takie oczywiste z uwagi na odmienność numeracji portów różnych modułów zawierających ten sam procesor. Toteż najbezpieczniejszym sposobem na wymianę danych klient -,serwer jest przesyłanie ich poprzez piny wirtualne.

Ad 2. Pamięć pinów wirtualnych


Pamięć pinów wirtualnych to miejsce składowania i wymiany danych pomiędzy VIRTUINO a programem użytkownika za pomocą zmiennych. Teoretycznie dane można także przekazywać poprzez ustawianie portów procesora ale jest to ewidentnie zły sposób. Dane pinów wirtualnych od i do klienta (aplikacji telefonicznej) przechowywane są w specjalnie zarezerwowanym obszarze mikroprocesorowej pamięci. A właściwie w dwu buforach / tablicach:  jednej dla zmiennych binarnych zdefiniowanych jako integer i drugiej analogowej (liczbowej) o typie float.


Numery komórek bufora odpowiadają numeracji pinów wirtualnych używanych w programie i w aplikacji.

Przesłanie danych z widgetu do programu następuje w dwu krokach.
- Aplikacja przesyła ramkę z danymi pinów do serwera WWW VIRTUINO w mikrokontrolerze a moduł komunikacji zewnętrznej umieszcza dane w odpowiednich komórkach bufora
- Tu dane czekają spokojnie aż zostaną pobrane przez program użytkownika za pomocą procedur komunikacji wewnętrznej.

Skąd użytkownik wie, że nowa dana została zapisana do komórki bufora? Nie wie. Program musi sprawdzać zawartość komórki i porównywać ją z wartością poprzednią. Jeśli się różnią znaczy to że odebrana została nowa wartość. Jak zareaguje program gdy do komórki zostanie zapisana ta sama wartość? Nie zauważy tego faktu uznając iż nie było żadnej transmisji danych. Skrócenie czasu reakcji na sterowanie z aplikacji wymaga sprawdzania komórek bufora z  możliwie maksymalną prędkością. Procedurę czytania i porównywania danych z bufora pinów wirtualnych należny więc umieścić w pętli głównej programu by wykonywała się jak najczęściej.

Wysyłanie zmiennej z programu ( z bufora pinów wirtualnych) do aplikacji również odbywa się w dwu krokach
- Program użytkownika zapisuje daną do odpowiedniej komórki pamięci
- Moduł komunikacji zewnętrznej czeka na odbiór ramki z zapytaniem klienta o wartość określonego pinu. Jeśli takie zapytanie nadejdzie biblioteka wysyła w odpowiedzi wartość pinu (komórki bufora) do aplikacji.

Co jeśli klient nigdy nie zapyta o wartość danego pinu lub gdy zapytanie nigdy nie zostanie odebrane? Wartość pinu nigdy nie dotrze z mikrokontrolera do aplikacji. Zapis danych do bufora może następować w dowolnym czasie ale przesył danych do klienta odbywać się będzie cyklicznie na żądanie klienta. Nie ma więc sensu zapisywać ich częściej do bufora niż okres odczytu.

Ad 3. Moduł komunikacji wewnętrznej


Biblioteka VIRTUINO zawiera specjalne procedury zapisu i odczytu danych z obu buforów - różne dla różnych typów zmiennych. Tymi procedurami program użytkownika łączy się z buforem pinów wirtualnych.


Wysyłanie / odbiór danych binarnych

Program użytkownika wysyła do aplikacji - a dokładniej  - umieszcza w tablicy danych  bitowych wartości za pomocą polecenia

   void vDigitalMemoryWrite(int digitalMemoryIndex, int value)

zaś odczytuje przesłane z telefonu dane bitowe z bufora poleceniem

   int  vDigitalMemoryRead(int digitalMemoryIndex)  

digitalMemoryIndex          to pozycja tablicy danych bitowych od 0 do 31
value                                   to wartość 0 , 1  lub  różne od 0 lub 1

Poprzez value możemy wysyłać liczby typu int  ale widgety w aplikacji potrafią wyświetlić jedynie trzy wartości: 0, 1 i inna liczba. Czemu tak ? będzie wyjaśnione przy innej okazji.

Wysyłanie / odbiór danych liczbowych

Wysłanie danych liczbowych do aplikacji następuje poleceniem

  void vMemoryWrite(int analogMemoryIndex, float value) 

zaś odbiór poleceniem

  float vMemoryRead(int analogMemoryIndex) 

Liczby przesyłane są w formacie float.  Dostępny w Arduino zakres zmiennej to
- 3.4028235E+38  do +3.4028235E+38

Typ float zawiera tylko 6 lub 7 cyfr znaczących. Jakie ma to znaczenie ?Wysyłając do aplikacji liczbę 999 999 990 na wyświetlaczu pojawi nam się okrągły miliard 1 000 000 000. Czy ma to jakieś znaczenie? Tak jeśli zależy nam na bardzo dużej dokładności lub przez liczbę przenosimy inną informacją złożoną z więcej niż z 7 cyfr. Należy o tym pamiętać i tego typu przypadki obsługiwać zmienną tekstową.


Wysyłanie / odbiór danych tekstowych

Istnieje jeszcze jeden typ zmiennych możliwych do przesłania pomiędzy urządzeniami.Są to dane tekstowe typu String. Dane przesyłane są wirtualnym kanałem wraz ze znacznikiem. Znacznik służy do identyfikacji nadawcy i odbiorcy danego komunikatu.

Teoretycznie  zmienne tekstowe przesyłane są bezpośrednio pomiędzy widgetami a zmiennymi programu. Teoretycznie, bo istnieje w programie bufor nadawania i obioru danych typu String analogiczny do bufora danych łącza szeregowego RS232. W buforze znajduje się tylko ostatnio przesłana wiadomość tekstowa wraz z numerem kanału do którego jest przypisana.
Kanał to nic innego jak etykieta dołączona do tekstu według której dowiązuje się nadawcę i odbiorcę wiadomości. Łącznie do dyspozycji mamy 100 kanałów dla obu kierunków nadawania.

Wysyłanie danych tekstowych dokonujemy poleceniem

   void sendText(byte ID, String text); 

odbiór zaś

  String getText(byte ID);       gdzie ID  jest numerem kanału

Jaka jest maksymalna długość tekstu? Tego dokładnie jeszcze nie wiem. (do sprawdzenia).

I to na razie tyle opisu co tam siedzi wewnątrz mikroprocesora po zainstalowaniu biblioteki VIRTUINO. Co z tym można zrobić - już niedługo w kolejnych odcinkach.

Przydatne linki

aktualne biblioteki VIRTUINO dla

4

Brak komentarzy:

Prześlij komentarz