Arduino a Tcl/Tk - časť 2 - HMI cez LAN

30.09.2023 | 08:17 | Richard | Richard

V staršom zápise sme Arduino ovládali cez grafické rozhranie vytvorené v Tcl/Tk. Dnes si spravíme HMI rozhranie z dotykovej obrazovky, Raspberry Pi a Arduina.

Obsah minulej časti

V minulej, teda prvej časti sme komunikovali s Arduinom pomocou sériového rozhrania. Toto má však niekoľko obmedzení a hlavnými sú limitujúca vzdialenosť nadradeného počítača (ktorý pôsobí ako GUI) a nízka odolnosť voči rušeniu (napr. v prostredí s frekvenčnými meničmi či inými zdrojmi vyšších harmonických frekvencií).

Existujú lepšie spôsoby, ako posielať a prijímať dáta. Napríklad zbernica RS485, alebo sieťové rozhranie, pri ktorom HMI a PLC (teda zjednodušene ovládací panel a priemyselný počítač) môžu byť od seba ľubovoľne ďaleko.

 

HMI

HMI je užívateľské rozhranie. V priemyselnej automatizácii sa takto vzletne zvyčajne označuje dotyková obrazovka, hoci by mohlo ísť aj o inú formu ovládania (napr. stroja) - napríklad myšlienkami ☺).

A to vôbec nie je lacný špás. 7" dotykové obrazovky napr. od Siemensu stoja okolo 1000 €. A je to len a len ovládací terminál, niečo o trošku chytrejšie ako LCD displej na kávomate.

IndustrialShields (ale aj iní) majú ceny prijateľnejšie (napr. https://www.industrialshields.com/shop/touchberry-pi-10-1-1478), ale je to de-facto schované Raspberry Pi v tele dotykovej obrazovky.
To je z hľadiska používania zrejme komplikovanejšie, ako používať out-of-box uzavreté riešenia.
Ale na druhej strane, existencia počítača ako ho poznáme, nám dáva nekonečné možnosti…

Možnosti pripojenia, konfigurácie, rozšírenia, trápenia i hrania. Niečo, čo v mnohom presahuje použitie klasického komerčného HMI.
A to nehovorím o vzdialenom prístupe - takto je to úplna pohoda, cez služby ako dwservice.net či iné. Nie je potrebné platiť nemalé peniaze pre služby ako Ewon.

 

Testované riešenie

Jeden HMI panel od IndustrialShields mám aj doma - avšak ten je zabudovaný v nejakej skrinke a nechcelo sa mi s ním laborovať.
Našťastie sa ku mne dostala HMI dotyková obrazovka od Waveshare, aj s obalom (https://www.waveshare.com/wiki/7inch_HDMI_LCD_(H)_(with_case), predávajú tiež len sólo samotný displej).
Je to pekné zariadenie s vyvedenými konektormi na VGA, HDMI, napájanie a dotykovú vrstvu. Tá sa správa pri pripojení k počítaču ako myš, bez potreby špeciálnych ovládačov. Obrazovka má natívne rozlíšenie 640×480 bodov, ale cez xrandr (resp. arandr) mu môžeme nanútiť i iné.

Na ilustračnom obrázku beží nejaký obskurný operačný systém, my si ju ale pripojíme k Raspberry Pi.


Obr. 0: 7" HMI od Waveshare - promo obrázok


Obr. 1: 7" HMI od Waveshare - s pripojeným Raspberry Pi


Aby sme nemuseli pozerať do malej obrazovky, tak si v Raspberry pustíme VNC server a cez klienta pristupujeme k ploche. A ostatnú prácu obstaráme cez ssh v emulátore terminálu.
 


Obr. 2: Prístup v rámci lokálnej siete cez VNC


Samozrejme, postupy ako to či ono urobiť v Raspbian-e by presahovalo rozsah tohto blogu. Ale skúsení i menej skúsení linuxáci GNU/linuxáci 😉 si dajú rady…

 

Arduino Mega + Ethernet Shield

Mojou motiváciou bolo používanie PLC automatov od IndustrialShields, ktoré sú, vo vyššej výbave, vybavené komunikáciou napr. cez ethernet alebo Wi-Fi či Bluetooth (Dali, RoLa,…). (https://www.industrialshields.com/industrial-plc-based-on-arduino-original-boards-automation-solutions-202209-lp)
Opäť platí, že sa mi nechcelo demontovať niečo (teda PLC) - aktuálne bežiace - tak som siahol po klone Arduino Mega 2560 s ethernetovým "shieldom" Wiznet 5100. Sú to bežné a cenovo nenáročné zariadenia, ktoré takýmto testovaniam plne vyhovujú. Navyše sú oba osadené práve v spomínaných IndustrialShields, takže kód je plne prenositeľný do spoľahlivého a otestoveného zariadenia.


Obr. 3: Arduino Mega s pripojeným shieldom Wiznet 5100


Zariadenie je pripojené sieťovým káblom k routeru/switchu, napájané je cez USB. Niektorí užívatelia reportovali, že pre spoľahlivých chod 500mA z USB portu nestačí, mne to vždy fungovalo v poriadku (teda len kombinácia týchto dvoch komponentov, bez žiadnych ďalších spotrebičov na výstupoch Arduina).
 

Program bežiaci v Arduine Mega 2560 (firmvér)

Program je jednoduchý - počúva na jednom UDP porte a na iný voľačo posiela.
Presnejšie: ak je na porte 8888 nejaký packet, tento prečíta a podľa správy rozsvieti alebo zhasne vstavanú LED na pine č. 13 arduina. Následne na port 8889 pošle reťazec s časom (millis() - čas od spustenia arduina), aby sme mali informáciu, že nám to teda obojsmerne funguje.


Relevantné riadky kódu sú uvedené nižšie, celý program je k dispozícii na stiahnutie v závere.

 

Časti kódu

Potrebujeme štandardné knižnice Arduina SPI, Ethernet a jeho rozšírenie EthernetUdp. SPI preto, lebo Wiznet je pripojený práve cez SPI protokol mikrokontroléra.

Súčasne si zadefinujeme IP adresu nášho arduina a portov a vytvoríme si objekt triedy EthernetUDP.
 

#include <SPI.h>          
#include <Ethernet.h>
#include <EthernetUdp.h>  

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 105);     
unsigned int localPort = 8888;      
unsigned int remotePort = 8889;     

EthernetUDP Udp;


Niekde v setup() si dáme

Ethernet.begin(mac, ip);
Udp.begin(localPort);

 

Zistíme si vzdialenú adresu, vypíšeme su ju do sériovej konzoly, a naplníme zásobník prichádzajúcou správou. A pokiaľ obsahuje 1, tak LED-ku rozsvietime, ak 0, tak ju zhasneme. Samozrejme, v reálnom svete to bude niečo sofistikovanejšie.
 

IPAddress remote = Udp.remoteIP();
for (int i = 0; i < 4; i++)  {
  Serial.print(remote[i], DEC);
  if (i < 3) Serial.print(".");
}
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
if (String(packetBuffer) == "1") digitalWrite(pinLED, HIGH);
if (String(packetBuffer) == "0") digitalWrite(pinLED, LOW);


A následne arduino pošle na port 8889 práve dosiahnutú hodnotu času v ms od svojho spustenia:

convertString = String(millis());
convertString.toCharArray(replyBuffer, 10); 
Udp.beginPacket(Udp.remoteIP(), remotePort);
Udp.write(replyBuffer);
Udp.endPacket();


 

 

A teraz program v Tcl/Tk

 

Inštalácia Tcl/Tk a potrebných knižníc

Na Raspberry Pi, s bežiacim upraveným Debianom, využijeme osvedčený spôsob:

sudo apt install tcl wish tcl-udp

Wish je vlastne s sústava grafických Tk knižníc. Je pravdepodobné, že apt ponúkne jeho skutočné meno: tk8.6.

 

Samotný program sa dá rozdeliť do 2 častí: grafického dizajnu a výkonnej časti.

 

Grafický dizajn

Dizajn vyzerá takto:


Definovanie dizajnu - len pár riadkov, všetko je v súbore na stiahnutie:
 

button .btnStart     -text  " OUTPUT HIGH " -font $pismoTlacid -bg green -command outHigh
button .btnStop      -text  " OUTPUT LOW  " -font $pismoTlacid  -bg red1 -command outLow
button .btnInterval  -text  " OUTPUT BLINK" -font $pismoTlacid  -bg $btnIntervalFarba -command outBlink
button .btnKoniec  -text  "QUIT" -font $pismoTlacid  -command quitProgramm
label .lblTextStav -text "STATE" -font $pismoTlacid 
label .lblStavHlav -textvariable stav  -font $pismoTlacid
label .lblTextInterval -text "INTERVAL" -font $pismoTlacid 
spinbox .spinInterval -from 1 -to 30 -textvariable pauza -width 2


Samotný jazyk je veľmi opisný. Ako je vidieť, práca s premennými je podobná ako je tomu v bash-i. Button je tlačidlo, label nápis a spinbox je dialóg na zadanie čísla, alebo jeho zmenu tlačidlami na jeho okraji. Žiadna veda.
 

Práca s UDP portom

Poznámka na okraj

Zacitujem z minulého článku: "Ako bolo povedané, Tcl/Tk je akýsi wrapper nad iným príkazmi, programami. Takže ak by nemal v základe podporu pre prácu s portami, vedeli by sme to obísť napr. príkazmi bash-u."

Napr. na poslanie reťazca na UDP port by sme zadali:

echo "1" > /dev/udp/192.168.1.105/8888

A na čítanie napr.

nc -u -l -k -p 8889
 

(nc a.k.a. netcat je (supersilný) nástroj na čítania a zapisovanie na porty s využitím protokolu TCP a/alebo UDP.)

Zase a znovu vidíme fantastickú architektúru GNU/linuxového operačného systému, jeho utilít, vzájomných prepojení a významnej šance na pochopenie, ako veci fungujú.
 

Tcl má na prácu s UDP vlastné príkazy/nástroje

Zadefinujeme si pár potrebných premenných:

set sockArduino [udp_open]
set sockHMI [udp_open]
set IP_HMI "192.168.1.104"
set IP_ARDUINO "192.168.1.105"
set PORT_HMI "8889"
set PORT_ARDUINO "8888"


A vytvoríme procedúry na vytvorenie spojenia a posielanie a čítanie z portov:
 

proc udpOtvor {} {
    global sockArduino sockHMI IP_HMI IP_ARDUINO PORT_HMI PORT_ARDUINO
    fconfigure $sockArduino -buffering none -translation binary -remote [list $IP_ARDUINO $PORT_ARDUINO]
    puts "Settings: [fconfigure $sockArduino]"
}

proc udpEventHandler {sock} {
    global arduinoMillis
    set sprava [read $sock]
    puts "Received from Arduino: $sprava"
    set arduinoMillis $sprava
    return
}

proc outHigh {} {
    global stav sockArduino srv
    set stav "1" 
    puts  $sockArduino $stav
    flush $sockArduino  
}

proc outBlink {} {
    global stav sockArduino pauza .btnInterval
    outHigh
    .btnInterval configure -background "gray"
    after [expr {$pauza * 1000}] {
        .btnInterval configure -background "lightgreen"
        outLow
    }
}

proc outLow {} {
    global stav sockArduino
    set stav "0" 
    puts  $sockArduino $stav
    flush $sockArduino
}


A spustenie programu je wish arduino_RPi_LAN.tcl
 

Záver

Zacitujem z minulej časti: "Osobne si myslím, že práca s Tcl/Tk je rýchla a príjemná. Isteže, grafický dizajn sa nedá "uplácať" naťahaním komponentov ako to poznáme z niektorých iných jazykov. Ale zameranie Tcl/Tk je iné - rýchle grafické nadstavby tam, kde textové (ncurses) rozhranie nestačí".

Samotný výrobca IndustrialShields pre svoje HMI tvorí programy v Node-RED. Je akiste výborný nástroj, ale aj s vysokou dávkou abstrakcie, tak ako je dnes bežné. Je to balík rôznych služieb, démonov, serverov a protokolov…

Na jednoduchý interfejs napr. na riadenie nejakého stroja je to nemotorné, veľké, priam monštrózne. Bez kontroly, hlbšieho pochopenia. Programovanie je formou spájania grafických elementov, a to nemusí byť pre každého.

A hlavne - a to je moje mentálne nastavenie z pracovnej praxe - nemám rád, ak niekam umiestnime stroj, aj pár tisíc kilometrov od domova - a v ňom má bežať niečo, čo je komplikovanejšie ako je nevyhnutne nutné.
Máme skúsenosti, kde rôzne automatické updaty znefunkčnili stroj (niekedy aj banalita, ako kupované termotransferové tlačiarne, ktoré robia popisky na výrobky), alebo ich sústavu, a ktoré nezniesli dlhšie prestoje. A vtedy nastupuje ten pravý stres 😉. Ale to je už iný príbeh(y).
 

Odkaz na stiahnutie spomínaných programov: https://gitlab.com/tcl-tk-public/arduino-hmi-lan

 

Poznámky

Pozn. č. 1: Jasné, sú to malé programy s malými nárokmi, preto mi hádam budú odpustené globálne premenné ☺.

Pozn. č. 2: V Emacse je na prácu s Tcl vytvorený mód. Ale ak používate etags na vytvorenie TAG-ov na skákanie medzi definíciami, tak etags defaultne nepozná kľúčové slová jazyka Tcl.
Pomôže tento trik

etags -l none -r '/proc[ \t]+\([^ \t]+\)/\1/'  <súbor.tcl>


Pozn. č. 3: A ako zadávať čísla alebo text? Pomocou niektorých balíkov je možné zobraziť virtuálnu klávesnicu (to bude v inom blogu), ale v tomto príklade som to nerobil (keďže máme len tlačidlá a spinbox).
Ďalšou možnosťou je pripojenie klasickej klávesnice, alebo nejakej super mini bluetooth klávesnice.

    • RE: Arduino a Tcl/Tk - časť 2 - HMI cez LAN 30.09.2023 | 11:25
      Avatar redhawk1975 Windows 11 nonsystemd edition  Používateľ

      pekne.

      ja mam tak nejake rpi a pristupujem na ne cez dwservice na 10" tablete.

      toto je ale elegantus

      Do or do not. There is to no try.​
      • RE: Arduino a Tcl/Tk - časť 2 - HMI cez LAN 30.09.2023 | 13:02
        Avatar Richard Antix  Používateľ

        Dwservice je šikovný nástroj, preto ich finančne podporujem predplatným. Napr. ročná licencia na spomínaný Ewon (máme to v pár strojoch) je cca 1000 €/rok. A klienti to musia platiť, resp. prvé roky je to schované v cene (hovoríme o strojoch v cene cca 300 tis. €).

        Vtip je v tom, že sú prípady, keď k stroju vzdielene nepristúpime aj celý rok, poneváč nie je prečo.