Avtor: dr. Simon Vavpotič
Python in MikroPython sta popularna programska jezika med nadobudnimi mladimi programerji. Zakaj so lahko umetno-inteligentni modeli v veliko pomoč pri programiranju?
V preteklem nadaljevanju smo si ogledali precej uporabnih primerov v Pythonu 3, ki jih lahko poganjamo tudi v Raspberry Pi Zero, ki je uporaben za gradnjo mobilnih robotov in dronov. Znanje tako brez težav uporabimo tudi v praksi.
Tokrat se lotimo kompleksnejšega programiranja, kjer bomo v eno aplikacijo združili veliko funkcionalnosti. Slednje pogosto zahteva tudi namestitev dodatnih programskih knjižnic, za kar pa nemalokrat potrebujemo tudi navidezna okolja. Obenem bomo v Rasberry Pi Pico 2 namestili in preizkusili tudi MicroPython.
Ta vsebina je samo za naročnike
Začenjamo pa z navideznimi okolji, katerih uporaba je nujna, če želimo uporabljati nekatere programske pomembne knjižnice.
Navidezna okolja v Pythonu
Številne različice Linuxa za zaščito programov in podatkov, pa tudi jedra operacijskega sistema, uporabljajo strogo nadzorovana okolja, v katera ni mogoče neposredno namestiti novih programskih knjižnic za programski jezik Python(3) tretjih proizvajalcev, ki niso uvrščene v standardno zbirko programskih knjižnic zanje. Tej omejitvi se lahko izognemo le z izgradnjo in uporabo navideznih okolij za poganjanje aplikacij v Pythonu(3).
Navidezno okolje lahko primerjamo z navideznim računalnikom, ki nima (neposrednega) dostopa do operacijskega sistema gostiteljskega strežnika. Zato spremembe v njem praviloma ne morejo neposredno vplivati na delovanje gostiteljskega računalnika. Podobno velja tudi za navidezna okolja v Pythonu(3), ki omogočajo rabo različnih programskih knjižnic in njihovih (pod)različic za različne aplikacije. Denimo, če ena aplikacija potrebuje starejšo različico neke programske knjižnice, druga pa novejšo, lahko vsako izmed njiju poganjamo v svojem navideznem okolju.



Novemu navideznemu okolju moramo dodeliti unikatno ime, ki naj bil se praviloma začelo s piko (».«), vendar lahko ime izberemo tudi drugače, kar storimo takole: python3 -v venv . Če se držimo konvencije označevanja navideznih okolij, mora pot navideznega okolja, ki ga želimo ustvariti v mapi trenutnega uporabnika izgledati takole »~/.prog1«.
Če si nato ogledamo vsebino mape navideznega okolja, opazimo podmape in konfiguracijske datoteke. V eni od podmap (npr. bin, scripts ipd.) je tudi program activate, ki omogoča zagon navideznega okolja. Na Raspberry Pi-ju je ta v imeniku bin.
Zagon navideznega okolja izvedemo na primer z ukazom source ~/.pyenv/bin/activate, seveda če smo prej ustvarili okolje s tem imenom v svoji uporabniški mapi. Uspešen zagon obenem spremeni uporabniški prompt tako, da je spredaj v oklepajih dodano ime okolja, v našem primeru »(.pyenv) … «.
Navidezna okolja v Thonnyju
Priprava in zaganjanje navideznih okolij ter urejanje programske kode in njeno zaganjanje je v Thonnyju v veliki meri avtomatizirano. Navidezno okolje lahko vzpostavimo prek menija Run/Configure interpreter v zavihku Interpreter. V spodnjem desnem kotu pogovornega okna je besedilo New virtual environment. Če kliknemo nanj, se odpre okno z dialogom, ki nas opozori, da moramo izbrati prazno mapo, v kateri bo Thonny izdelal navidezno okolje za izbrani program. Po kliku na OK se odpre okno za izbiro datotečne mape, ki omogoča tudi ustvarjanje nove, če na levi strani izberemo glavno mapo Home.
Novo mapo ustvarimo s klikom na majhen gumb z emblemom datotečne mape s plusom, nakar lahko izberemo ime nove mape (npr. .pyenv) in kliknemo gumb Create, nato pa v desnem spodnjem kotu pogovornega okna še gumb OK. Za kratek čas se pokaže pogovorne okno z imenom Creating virtual environment, ki kmalu izgine.
Naslednji korak je namestitev vseh potrebnih programskih knjižnic v navidezno okolje, kar lahko storimo le prek ukaznega okna, do katerega pridemo prek menija Tools/Open system shell. V oknu moramo naprej aktivirati pravkar izdelano navidezno okolje, kar storimo z ukazom source (npr. source .pyenv/bin/activate). Zdaj lahko uporabimo na primer ukaz pip3 install Image, ki namesti programsko knjižnico Image.
Že ustvarjeno navidezno okolje v Thonnyju izberemo prek menija Run/Configure interpreter v zavihku Interpreter tako, da kliknemo na gumb s tremi pikicami, ki je poleg polja Pytnon executable. Nato iz pregleda datotek izberemo mapo z navideznim okoljem v mapi Home (z leve strani), kliknemo nanjo, nato odpremo mapo bin in v njej poiščemo datoteko activate. Ko jo izberemo, se pot do nje izpiše tudi v polju Python executable, le da na koncu ne piše activate ampak python3.



Okna z dialogom
Čeprav se nam zdijo okenski programi v Windows nekaj samoumevnega v Linuxu pogosto ne vemo, kje začeti. Raspberry Pi 500+ z nameščenim operacijskim sistemom Trixie je lahko v veliko pomoč pri preizkušanju programske kode v Pythonu3, saj je ta že prednameščen. Včasih moramo dodati le še kako programsko knjižnico, kar storimo z ukazom pip install . V našem primeru potrebujemo le programsko knjižnico Tkinter, ki del standardne knjižnice Pythona 3, zato je ni potrebno nameščati. Poglejmo program:
import tkinter as tk
from tkinter import messagebox
import string
def run_dialog():
Skrije glavno okno programa
root = tk.Tk()
root.withdraw()
Odpre okno z dialogom
answer = messagebox.askyesno(»Selection«,
»Bi radi izpis abecede?«)
if answer:
Izpiši abecedo (A-Z)
print(»Alphabet:«, string.ascii_uppercase)
else:
print(»Potem pa ne…«)
Zapre program
root.destroy()
if name == »main«:
run_dialog()
Programska koda je sestavljena iz glavnega programa in podprograma run_dialog(), ki odpre okno z dialogom in zastavi vprašanje. Če se odločimo, da želimo videti abecedo, jo izpiše, sicer pa le pove, da je ne bo izpisal.
Podprogram run_dialog() skriva ključne elemente okenskega vmesnika operacijskega sistema. Glavno okno ustvarimo s klicem objekta tk.Tk(), ki smo ga uvozili iz programske knjižnice tkinter, dodatno pa smo uvozili še funkcijo messagebox, ki omogoča ustvarjanje oken s sporočili in oken z dialogom, kjer je mogočih več odgovorov.
Če z znakom »#« zakomentiramo ukaz root.withdraw(), bomo poleg okna z dialogom videli še povsem prazno osnovno okno aplikacije. Če bi ga hoteli uporabiti, bi morali definirati vsaj nekaj njegovih elementov, denimo določiti naslov okna vstaviti polje za vnos besedila in gumbe, si katerimi lahko izvajamo funkcije nad besedilom. A vse to lahko vidimo tudi iz naslednjega primera.
Urejevalnik besedil
Tkinter programsko knjižnico lahko uporabimo tudi za izgradnjo kompleksnejših aplikacij, denimo urejevalnika besedil, ki vsebuje tudi dialoga za nalaganje (filedialog.askopenfilename()) in shranjevanje (filedialog.asksavefilename()) tekstovnih datotek. Funkcije text_editor objekta, po drugi strani omogočajo pisanje in urejanje besedil. Osnovnemu oknu urejevalnika je dodana tudi menijska vrstica.
Primer urejevalnika besedil v Pythonu, ki ga lahko prenesemo iz spletne strani github.com/OpenGenus/text-editor-python, uporablja tudi programsko knjižnico Image, kar pomeni, ki jo moramo dodatno namestiti. Kar je vse sorazmerno enostavno, saj nas Python3 med poganjanjem programske kode opozori na manjkajoče programske knjižnice. Namestitev smo v našem primeru izvedli z ukazom: pip3 install Image, pri čemer je program že deloval v navideznem okolju .pyenv, brez katerega dodatne knjižnice ne bi mogli namestiti.
Urejevalnik besedil je shranjen v datoteki main.py, ki jo iz prej ustvarjenega navideznega okolja zaženemo takole: python3 main.py. Program sicer odpre glavno okno, noče pa odpreti oken za nalaganje in shranjevanje tekstovnih datotek.
Kodo moramo zato za izvajanje v novejših različicah Pythona, kakršna je v Raspberry Pi OS Trixie, še nekoliko popraviti. V glavo specifikacij funkcij, ki odpirajo okni za ustvarjanje, nalaganje in shranjevanje tekstovnih datotek, dodamo še zapis »=None«, s katerim povemo, da je prednastavljena vrednost vhodnega parametra prazno. Nato se okni normalno odpreta, pri čemer lahko nalagamo in shranjujemo datoteke. Poglejmo primer spremenjene kode za glavo funkcije, ki naloži tekstovno datoteko: »def load_file(e=None):«.
Prilagajanje polja za vnos besedila
Poglejmo, kako povečamo sorazmerno majhno okno za vnos teksta, ki je na začetku veliko le 1000 x 600 pik, oziroma 80 x 20 znakov. Najprej v 9. vrstici programa poiščemo ukaz root.geometry(»1000×600«) in ga zamenjamo z naslednjim root.geometry(»1500×900«), s čemer povečamo osnovno okno, ne pa tudi polja za vnos besedila. Slednje storimo tako, da v nadaljevanju programa poiščemo ukaz: my_text = Text(my_frame, width=80, height=20, font=(»Helvetica«, 16), … in v njem zamenjamo vrednosti širine in višine okna v znakih: my_text = Text(my_frame, width=120, height=40, font=(»Helvetica«, 16), … Tako se polje za vnos besedila povsem prilagodi novi velikosti okna. Po želji lahko zamenjamo tudi font in barvo besedila. Nastavimo lahko tudi prelom vrstic, daljših od širine okna.
Okni za izbor in shranjevanje tekstovnih datotek
V datoteki main.py so tudi podprogrami open_file, save_file in save_as_file. Najpomembnejši del prvega je klic za odpiranje okna z dialogom za izbor datoteke. Kot vidimo, lahko nastavimo tako začetno datotečno mapo (npr. »/«), ime okna z dialogom (npr. »Open File«) in tipe besedilnih datotek, ki jih je mogoče naložiti. V našem primeru so definirani štirje tipi (TXT, HTMI, PY in splošen). Slednji prikaže vse razpoložljive datoteke.
Odpiranju datoteke sledi še nekaj ukazov, med katerimi je najpomembnejši my_text.insert(END, stuff), ki v okno za urejanje besedil prenese celotno vsebino prebrane datoteke.
V oknu za shranjevanje besedila imamo nasprotno ukaz: text_file.write(my_text.get(1.0, END)), ki celotno vsebino polja za vnos besedila shrani v izbrano datoteko.
Celoten primer urejevalnika besedil je predolg, da bi ga lahko objavili v celoti, je pa na voljo iz spletne strani github.com/OpenGenus/text-editor-python.
Z manjšimi popravki bi bil čisto uporaben …
Urejevalnik teksta še ni povsem dodelan, saj mu manjka določitev robnih pogojev. Na primer, če tekst ni izbran in kliknemo na kurzivno pisavo, dobimo le napako v oknu za razhroščevanje, v tekstovnem okno pa je pisava še vedno pokončna. Kurzivno pisavo lahko naredimo samo, če najprej izberemo besedilo in nato izvedemo ukaz. Slednje velja tudi za tipke, s katerimi poravnavamo besedilo na levo, desno ali na obe strani.
Morda je celo bolje, da primer urejevalnika ni v celoti dodelan, saj nas to sili k razmišljanju in novim zamislim.
MicroPython
Medtem, ko smo že veliko povedali o Pythonu, je bil MicroPython v njegovi senci. Zato je prav, da v drugem delu tega nadaljevanja preizkusimo še slednjega. Pri tem sta v veliko pomoč Raspberry Pi Pico in Pico 2, ki sta edina Raspberry Pi-ja, ki ju navadno poganjamo brez operacijskega sistema. Programiramo ju lahko le prek gostiteljskega računalnika, kot je klasični PC ali kateri od ostalih Raspberry Pi, celo Raspberry Pi Zero (2) lahko uporabimo za ta namen, če mu dodamo monitor in drugo periferijo, kot je originalna Raspberry Pi tipkovnica z USB spojnikom, da lahko nanj povežemo še miško in Rasbperry Pi Pico (2).
Raspberry Pi Pico (2) nima priključka za monitor in se lahko z gostiteljskim računalnikov, na katerega moramo namestiti tudi ustrezno razvojno okolje, pogovarja le prek edinega priključka mikro USB, ki podpira delovanje dveh logičnih vmesnikov: CDC in MSD, ki posnemata serijski vmesnik in pogon za masovno hrambo podatkov. Medtem, ko je MSD namenjen nameščanju nove programske kode, računalnik med njenim izvajanjem praviloma komunicira prek vmesnika CDC. So pa tudi druge možnosti.
Za izvajanje programov v MikroPythonu moramo na Raspberry Pi Pico (2) najprej namestiti interpreter za MycroPython, nato pa lahko računalnik neposredno povežemo z razvojnim okoljem Thonny pred logične povezave CDC. Programska koda v Pythonu tako nastaja na gostiteljskem računalniki, izvaja pa jo vselej Raspberry Pi Pico (2).
Kako začeti?
Najprej se podamo na spletno strani micropython.org/download/RPI_PICO2, iz katere prenesemo izvedljivo datoteko z interpreterjem za MicroPython (različica Pythona je 3) za jedra ARM ali za jedra RISC-V. Mimogrede povejmo, da imajo Raspberry Pi Pico 2 štiri procesorska jedra, od katerih lahko naenkrat delujeta samo dve. MikroPython je na voljo za par jeder ARM in par jeder RISC-V. Tako lahko vselej izberemo tisto procesorsko arhitekturo, ki nam najbolj ustrezna.
Naslednji korak je zagon Raspberry Pi Pico 2 tako, da pred in med priklopom kabla USB 2.0 na gostiteljski računalnik držimo pritisnjeno tipko Boot. Raspberry Pi Pico 2 se nato zažene v načinu za programiranje, pri čemer se gostiteljskemu računalniku predstavi kot MSD enota. Na slednjo nato iz odložimo datoteko UF2 z MicroPythonom.
Po nameščanju in ponovnem zagonu je Raspberry Pi Pico 2 pripravljen za izvajanje programov v Pythonu. Gostiteljskemu računalniku se predstavi kot naprava CDC, oziroma zaporedna vrata z imenom Board in FS mode z oznako zaporednega vmesnika (npr. /dev/ttyACM0 v Linuxu ali npr. COM3 v Windows). Z ukazom help() lahko izpišemo bistvene dodatne kaze v MikroPythonu, s katerimi lahko upravljamo na primer vhodno-izhodne priključke.
Thonny razvojno okolje z Raspberry Pi Pico 2 povežemo prek menija Run/Configure interpreter v zavihku Interpreter, kjer izberemo Raspberry Pi Pico, kot ciljni interpreter programov v MicroPythonu. Tako se ob pritisku na belo puščico v zelenem krogu program v Pythonu vselej zažene v Raspberry Pi Pico 2. Preizkusili smo zelo enostaven programček: print(»Test.«) – Deluje!
Prihodnjič
Nadaljevali bomo z opisom kompleksnejših programov, ki so lahko zelo uporabni pri praktičnem delu, in načrtovanju strojne opreme, kot je izdelava drona. Videli bomo, kako upravljamo GPIO priključke in različne vgrajene komunikacijske protokole, kot so: I2C, SPI in TTL RS232 s 3,3-voltnimi nivoji.
