Avtor: dr. Simon Vavpotič
Python in MikroPython sta popularna programska jezika med nadobudnimi mladimi programerji. Kako se lotiti kompleksnejšega projekta?
V preteklem nadaljevanju smo se lotili kompleksnejšega programiranja, pri katerem smo v urejevalnik besedil, napisan v Pythonu 3 združili veliko funkcionalnosti, za kar smo morali namestiti dodatno programsko knjižnico ter namestiti in uporabiti navidezno okolje. Obenem smo MicroPython namestili in preizkusili tudi v Rasberry Pi Pico 2 W.
Tokrat bomo nadaljevali 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.
Ta vsebina je samo za naročnike
Prenos in prikaz podatkov prek zaporednega vmesnika
Tokrat smo umetni inteligenci zastavili nekoliko bolj zapleteno vprašanje: »Sestavi program za Raspberry Pi 5 z operacijskim sistemom Trixie v programskem jeziku Python 3 tako, da prek zaporednega vmesnika /dev/ttyAMA0 odda znak »?« in izpiše prejet odgovor«. Pri tem smo prej prek tega vmesnika povezali enostavno napravo, ki zgolj vrne status. Poglejmo prvi del programa, ki ga je izdelala umetna inteligenca:
import serial
import time
def main():
try:
with serial.Serial(port=’/dev/ttyAMA0′,
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1 # 1 second timeout for reading
) as ser:


Za komunikacijo prek zaporednih vrat je potrebna programska knjižnica serial, ki jo lahko namestimo z ukazom pip install pyserial. Nameščanje je v nekaterih operacijskih sistemih (npr. Raspberry Pi OS Bookworm in Trixie) dovoljeno le v navidezno okolje, o katerem ste lahko več prebrali v preteklem nadaljevanju.
Drugi del programa, ki se mora seveda poravnano (s pravilnimi zamiki vrstic) držati prvega dela, najprej preveri, ali so zaporedna vrata odprta. Če so, izpiše ime vrat in hitrost zaporedne komunikacijske povezave.
Sledi ukaz za pošiljanje ASCII znaka »?«, ki je skladen s komunikacijskim protokolom, ki ga uporablja moja naprava: ser.write(b’?’). Kot vidimo, znak »?« naprej spremenimo enobajtno število, nato pa oddamo. Sledi kratek čas čakanja na odgovor naprave (0,1 sekunda), ki ga izvedemo z ukazom time.sleep(0.1):
if ser.is_open:
print(f«Connected to {ser.port} at {ser.baudrate} baud.«)
# Send the '?' character
ser.write(b'?')
print(»Sent: ?«)
# Wait briefly for the device to process and respond
time.sleep(0.1)
Tretji del programa z ukazom ser.read.all() prebere vse v času 0,1 sekunde čakanja sprejete znake in jih shrani v spremenljivko, ki jo je umetna inteligenca poimenovala response. Odgovor je lahko tudi prazen, kar preverimo s pogojnim stavkom (if), ki sledi. Če odgovor ni prazen, ga ukaz print izpiše kot besedilo. Nastavljeni način zapisa UTF-8 je skladen z ASCII.
# Read the response
response = ser.read_all()
if response:
print(f«Received:
{response.decode(‘utf-8’,
errors=’replace’)}«)
else:
print(»No response
received.«)
V četrtem delu programa Google AI poskrbi tudi za lovljenje morebitnih nepričakovanih napak in morebitne uporabniške prekinitve delovanja s pritiskom na kombinacijo tipk za prekinitev delovanja programa (npr. »Ctrl« + »z«). Opazimo tudi, da je program napisan kot funkcija z imenom main. Lahko bi jo poimenovali tudi drugače.



except serial.SerialException as e:
print(f«Error opening serial port: {e}«)
except KeyboardInterrupt:
print(»\nScript stopped by user.«)
if name == »main«:
main()
Ko smo program dejansko preizkusili, je deloval povsem pravilno in izpisal status z Raspberry Pi 5 povezane naprave.
Igranje z osvetlitvijo tipkovnice Raspberry Pi 500+
Osvetljena tipkovnica na klik daje Raspberry Pi 500+ poseben čar, vendar le malo kdo ve, da jo lahko upravljamo tudi programsko in ne le prek funkcijskih tipk. Tako lahko s poljubnima barvo in svetlostjo osvetlimo skoraj katerokoli tipko, razen tiste za vklop, ki med delovanjem vedno sveti zeleno.
Vendar moramo pred tem namestiti programsko orodje rpi-keyboard-config, s katerim lahko upravljamo osvetlitev in ostale funkcije tipkovnice tudi prek ukaznega okna. To v ukaznem oknu storimo z ukazoma sudo apt update in sudo apt install rpi-keyboard-config.
Google AI na zahtevo, naj ustvari program v Pythonu 3, ki na Raspberry Pi 500+ z Raspberry Pi OS Trixie modro osvetli črko A s polovično intenziteto, generira programsko kodo z drobnima napakama, zaradi katerih osvetli napačno tipko, obenem pa se osvetlitev obdrži le za hip, nakar se samodejno povrne morebiti shranjeno stanje (če tega ni, osvetlitev v celoti ugasne).
Poglejmo popravljeno programsko kodo, v kateri je nepotreben ukaz zakomentiran, napačna koda tipke pa je zamenjana s pravilno:
import subprocess
def set_key_color(key_index, color_hex):
try:
subprocess.run([»rpi-keyboard-config«, »leds«, »clear«], check=True)
subprocess.run([
»rpi-keyboard-config«, »led«,
»set«, str(key_index),
»–colour«, color_hex
], check=True)
# subprocess.run([»rpi-keyboard-config«, »leds«, »load«], check=True)
print(f«Key {key_index} set to {color_hex} at half intensity.«)
except subprocess.CalledProcessError as e:
print(f«Error controlling keyboard LEDs: {e}«)
if name == »main«:
set_key_color(47, »#000080«)
Programček na začetku naloži standardno python programsko knjižnico subprocess, ki mu omogoča klice drugih programov na enak način, kot če bi jih klicali iz ukaznega okna. Z enostavno predelavo, da lahko spremenimo v orodje, ki lahko na enak način kot iz ukazne vrstica pokliče katerikoli program.
Program definira funkcijo set_key_color, ki sprejme 2 parametra: kodo tipke A ter kodo barve, ki vsebuje tudi svetlost. Koda tipke je v originalnem programu napačno zapisana kot 31, pravilno je 47, kot je prikazano v že popravljenem programu. Komentar v rešitvi Google AI sicer poudari, da je koda verjetno 31, a ni. Koda barve je določena z intenzitetami kanalov R,G in B (R = rdeča, G = zelena, B = modra). Vsak kanal lahko krmilimo z 256 vrednostmi, ki določajo svetlost barvnega kanala. V našem primeru smo od Google AI zahtevali polovično svetlost modre barve, kar je enako vrednosti 128 modrega (B) kanala, medtem ko sta vrednosti rdečega in zelenega kanala 0.
Program za klic programa rpi-keyboard-config uporablja funkcijo subprocess.run, ki izbrani aplikaciji posreduje tudi vhodne parametre. V našem primeru najprej pokliče rpi-keyboard-config leds clear, s čemer izključi morebitne prejšnje osvetlitve tipk, nato pa nastavi osvetlitev z ukazom rpi-keyboard-config led set 47 –colour »#000080«.
Vzdušje pokvari ukaz subprocess.run([»rpi-keyboard-config«, »leds«, »load«], check=True), za katerega ni jasno, zakaj ga je Google AI sploh dodal. Verjetno ni prebral ali pa razumel navodil za uporabo programa rpi-keyboard-config, ki se izpišejo, če ga zaženemo brez prametrov. Ukaz povrne prejšnje stanje osvetlitve, ki je bilo shranjeno z ukazom save. Če tega ukaza niste uporabili že kdaj prej, bo tipkovnica seveda ugasnila, saj kar je tudi prednastavljeno stanje. V našem programčku shranjevanja osvetlitve ne potrebujemo, prav tako pa tudi ne njegovega vračanja, zato smo ukaz preprosto zakomentirali.
Krmiljenje digitalnih izhodov
Prižiganje LED ali krmiljenje relejev je v Pythonu in MikroPythonu je zelo enostavno, ne glede na to, ali uporabljamo miniaturni Raspberry Pi Pico (2) ali Raspberry Pi Zero (2), ali najzmogljivejšega Raspberry Pi 500+. V Pythonu lahko uporabimo različne programske knjižnice, ali pa enako tehniko kot pri prižiganju osvetlitve tipk na Raspberry Pi 500+, s pomočjo knjižnice subprocess in programčka pinctrl, ki ga lahko poganjamo iz ukaznega okna.
Tokrat bomo raje uporabili programsko knjižnico gpiozero, ki je deluje samo v Raspberry Pi Zero (2), ampak tudi v vseh ostalih, razen v Raspberry Pico. Uporabili iz knjižnice signal, ki omogoča upravljanje programskega toka, bomo uporabili ukaz pause, ki zaustavi izvajanje programa dokler, ga na prekinemo s kombinacijo tipk »Ctrl« + »c«.
Povejmo še, da se splača na 40-polno razširitveno vtičnico Raspberry Pi (Zero, 1, 2, 3/CM3, 4/400/CM4, 5/500/500+/CM5) prek upora s 330 Ohmi tudi dejansko povezati svetlečo diodo, saj tako nazorno vidimo, ali program deluje.
Izbrali smo digitalni vhod-izhod GPIO2, ki je na priključku 3, obenem pa so katodo modre LED povezali še s priključkom 9, na katerem je masa (GND).
Google AI je na vprašanje, naj izdela program v Pythonu 3 za Raspberry Pi 5, ki postavi GPIO2 na 1 vrnil povsem delujočo programsko kodo, ki pa smo jo še nekoliko dodelali, saj lahko tako pokažemo še nekatere funkcionalnosti programskih knjižnic Pythona 3:
from gpiozero import DigitalOutputDevice
from signal import pause
import time
GPIO2 is BCM pin 2
pin = DigitalOutputDevice(2)
Set pin to 1 (High)
pin.on()
print(»GPIO2 is now set to 1.«)
time.sleep(2)
pin.off()
print(»GPIO2 is now set to 0. Press Ctrl+C to exit.«)
pause()
Vključili smo knjižnico time z zakasnitvenimi funkcijami, med katerimi je tudi sleep, ki izvajanje programa zaustavi za navedeno število sekund. V našem primeru smo izbrali 2. Za upravljanje GPIO priključkov potrebujemo funkcijo DigitalOutputDevice iz knjižnice gpiozero. DigitalOutputDevice ima en vhodni parameter, s katerim izberemo priključek, ki ga želimo krmiliti kot izhod. Povratna vrednost je objekt, s katerim lahko upravljamo izbrani priključek. V našem primeru smo definirali objekt pin, ki omogoča upravljanje priključka, za kar uporabljamo funciji on in off.
Ko namestimo LED in zaženemo program, se ta najprej zasveti in nato po dveh sekundah ugasne. Program se zaradi klica funkcije pause zaključi šele, ko pritisnemo kombinacijo tipk »Ctrl« + »c«.
Krmiljenje GPIO z MycroPythonom
Raspberry Pi Pico (2) je še malenkost manjši od Raspberry Pi Zero (2), GPIO priključke pa ima na obeh daljših robovih. Čeprav MicroPython vseeno uporablja druge programske knjižnice od Pythona 3, je programska koda vseeno zelo podobna. Kljub temu pa ni čisto vseeno, ali uporabljamo Raspberry Pi Pico (2) z brezžičnim komunikacijskim modulom ali brez njega. Pri osnovnem testiranju pogosto uporabljamo vgrajeno LED, vendar je ta pri Picih brez brezžičnega modula povezana na GPIO25, pri tistih z brezžičnim modulom pa je slednji uporabljen za komunikacijo z njim. Zato je LED povezana s priključkom WL_GPIO0 na brezžičnem modulu. Zato bo pravilno delovala le, če naložimo različico ustrezni MicroPythona: za Raspberry Pi W ali Raspberry Pi 2W, odvisno od tega katero ploščico uporabljamo. Denimo MicroPython za Raspberry Pi 2 bo sicer deloval tudi na Raspberry Pi 2W, vendar ne bomo mogli uporabljati brezžičnega modula niti uporabniške LED.
Ali lahko preverimo, ali je v Raspberry Pi Pico (2)(W) naložen prava podrazličica MicroPythona? Seveda! V razvojnem okolju Thommy lahko v konzolo neposredno vnesemo ukaz machine.Pin(»LED«, machine.Pin.OUT). Če vrne vrednost 25, je nameščena različica MicroPythona za Raspberry Pi Pico 2 (brez W).
Poglejmo še program s katerim prižigamo in ugašamo LED v enakomernem ritmu:
import machine
import time
Use »LED« or »WL_GPIO0« for Pico 2W
led = machine.Pin(»LED«, machine.Pin.OUT)
while True:
led.on()
time.sleep(0.5)
led.off()
time.sleep(0.5)
GPIO priključke Raspberry Pi Pica (2)(W) krmilimo s pomočjo programske knjižnice machine, ki določa strojno arhitekturo. Uporabljamo tudi prek omenjeno knjižnico time. Zelena uporabniška LED, ki je prispajkana na miniaturno tiskanino ob priključku mikro USB, utripa že, ko naložimo binarno datoteko s podporo za MicroPython. Za njeno uporabo v programu, moramo najprej pridobiti njen objekt, kar storimo s klicem funkcije machine.Pin z dvema vhodnima podatkoma, oznako ali številko GPIO priključka in način delovanja le tega. V našem primeru želimo priključek uporabljati kot digitalni izhod, zato smo izbrali način machine.Pin.OUT. Za konstantno utripanje LED potrebujemo še neskončno programsko zanko, v kateri LED najprej z ukazom led.on prižgemo, nato z ukazom time.sleep(0.5) počakamo pol sekunde, z ukazom led.off LED ugasnemo in pred ponovitvijo zanke z ukazom time.sleep(0.5) počakamo še pol sekunde. Tako LED vsako sekundo enkrat utripne.
Izvajanje programa v Raspberry Pi Pico (2)(W) lahko v razvojnem okolju Thonny prekinemo s pritiskom na rdečo tipko s kvadratkom. Dodajmo še, da v MictoPythonu sprogramiran Rapsberry Pi Pico (2)(W) seveda shrani tudi zadnji program, ki smo ga v njem poganjali. Slednji oživi takoj, ko ta miniaturni računalnik povežemo z napajanjem, pri čemer ne potrebuje gostiteljskega računalnika. Slednji je potreben le pri programiranju.
Prihodnjič
Tokrat smo videli, da lahko s Pythonom 3 in MicroPythonom učinkovito upravljamo GPIO priključke in drugo strojno opremo. Uporabili smo tudi zaporedno komunikacijo.
Prihodnjič se lotimo zahtevnejšega programiranja, pri katerem bomo uporabili brezžične komunikacije, vzpostavili komunikacijski strežnik in krmilili dron, kot obljubljeno. Zanimala nas bo tudi neposredna komunikacija s tipali, kot je BMP280, ki meri temperaturo in zračni tlak.
