Programujeme Raspberry Pi Pico v jazyku MicroPython

základy práce s doskou Raspberry Pi Pico v jazyku MicroPython

Videá pre cvičenie

Motivácia

Našim cieľom na nasledujúcich cvičeniach bude vytvoriť chytrý senzor pre meranie teploty a vlhkosti. Čo je podstatné - pri návrhu a implementácii sa budeme snažiť o to, aby sa nejednalo o prvoplánové riešenie, ale budeme sa snažiť o bezpečnú a funkčnú implementáciu s ohľadom na koncového zákazníka.

Ciele

  • naučiť sa základy programovania v jazyku MicroPython na doske Raspberry Pi Pico
  • zoznámiť sa s editorom Thonny a jeho možnosťami programovania mikrokontrolérov v jazyku MicroPython

Postup

Predtým, ako naozaj začneme

Ešte predtým, ako začneme, si nainštalujte editor Thonny a do mikrokontroléra Raspberry Pi Pico nahrajte firmvér s jazykom MicroPython. Podrobnejšie pokyny nájdete na tejto stránke.

Niekoľko tipov pri práci:

  • Pico na doske neobsahuje tlačidlo RESET. Najjednoduchšie ho však môžete reštartovať odpojením a opätovným pripojením USB kábla. Nikdy ho však neodpájajte ani nepripájajte na strane dosky mikrokontroléra! Vyhnete sa tak možnosti odtrhnutia konektora na doske a tým pádom aj jeho celkovému poškodeniu. Miesto toho odpájajte USB kábel vždy na strane počítača!

  • V prípade, že chcete mikrokontrolér reštartovať softvérovo, môžete tak urobiť príkazom:

    from machine import reset; reset()
  • Softvérový reset zariadenia sa dá vykonať ešte jednoduchšie - stlačením klávesovej skratky CTRL+D v prostredí REPL (terminála) vývojového prostredia Thonny.

Ak chcete vedieť, aké moduly sú dostupné na zariadení, napíšte príkaz help('modules). Výsledkom bude zoznam zabudovaných modulov jazyka MicroPython:

>>> help('modules')
__main__          asyncio/__init__  hashlib           requests/__init__
_asyncio          asyncio/core      heapq             rp2
_boot             asyncio/event     io                select
_boot_fat         asyncio/funcs     json              socket
_onewire          asyncio/lock      lwip              ssl
_rp2              asyncio/stream    machine           struct
_thread           binascii          math              sys
_webrepl          bluetooth         micropython       time
aioble/__init__   builtins          mip/__init__      tls
aioble/central    cmath             neopixel          uasyncio
aioble/client     collections       network           uctypes
aioble/core       cryptolib         ntptime           urequests
aioble/device     deflate           onewire           vfs
aioble/l2cap      dht               os                webrepl
aioble/peripheral ds18x20           picosleep         webrepl_setup
aioble/security   errno             platform          websocket
aioble/server     framebuf          random
array             gc                re
Plus any modules on the filesystem

Funkčné minimum

V prvom kroku vytvoríme veľmi jednoduchú a prvoplánovú implementáciu (budúceho) chytrého senzora. Vytvoríme základné zapojenie a vytvoríme základnú kostru kódu, pomocou ktorej odmeriame aktuálne hodnoty zo senzora a vypíšeme ich do terminálu.

Task

K vašej doske pripojte senzor, tlačítko a LED diódu.

Task

Vytvorte fragment kódu, pomocou ktorého prečítate aktuálne hodnoty zo senzora a vypíšete ich do terminálu.

Na zariadení vytvoríme súbor s názvom (napr.) device.py a za predpokladu, že je senzor DHT11 pripojený ku pin-u č. 27, bude výsledný kód vyzerať nasledovne:

# device.py
from dht import DHT11
from machine import Pin

pin = Pin(27, Pin.IN)
sensor = DHT11(pin)

sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()

print(temp, hum)

Task

Číslo pin-u, na ktorý je pripojený senzor, uložte do globálnej premennej DHT_PIN a uložte ju do modulu boot.py.

Modul boot.py má v jazyku MicroPython špeciálne využitie. Je to totiž prvý súbor, ktorý sa spustí po zapnutí zariadenia a všetky vytvorené premenné, objekty a zadefinované funkcie budú dostupné v globálnom kontexte. Nie je teda potrebné objekty z modulu boot.py importovať v našom module. Aby však k ich načítaniu došlo, je potrebné mikrokontrolér reštartovať (napr. stlačením skratky CTRL+D v REPL režime).

# boot.py
DHT_PIN = 27
# device.py
from dht import DHT11
from machine import Pin

pin = Pin(DHT_PIN, Pin.IN)
sensor = DHT11(pin)

sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()

print(temp, hum)

Konfiguračný súbor

Vlastnosti chytrého zariadenie budeme potrebovať meniť za behu. V našom prípade vytvárame chytrý teplomer. Ten v našom regióne bude napr. hodnotu teploty vracať ako hodnotu v stupňoch celzia. V prípade ale, že expandujeme a začneme naše chytré teplomery predávať napr. aj v USA, budeme potrebovať, aby teplomer meral v stupňoch fahrnhejta.

A práve túto funkcionalitu zabezpečíme pomocou konfiguračného súboru, kde sa budú nachádzať nastavenia správania chytrého zariadenia. V tomto prípade to bude zatiaľ len jednotka teploty. Pre reprezentáciu konfiguračného súboru použijeme formát JSON, pretože vieme údaje do neho jednoducho serializovať a deserializovať pomocou modulu json.

Task

V module boot.py vytvorte premennú CONFIG_FILE, ktorá bude obsahovať názov a umiestnenie konfiguračného súboru.

Názov konfiguračného súboru bude config.json.

# boot.py
DHT_PIN = 27
CONFIG_FILE = 'config.json'

Task

Vytvorte funkciu read_config(), ktorá načíta konfiguračný súbor zo súborového systému mikrokontroléra a vráti ho ako objekt typu dictionary. V prípade, že sa súbor nepodarí načítať, vytvorte jeho predvolenú podobu.

Predvolenú podobu súboru zatiaľ uložíme ako slovník do globálnej premennej DEFAULT_CONFIG do modulu boot.py. Konfiguračný súbor bude mať zatiaľ len kľúč units, ktorého prípustné hodnoty budú:

  • standard - ak chceme teplotu merať v Kelvinoch
  • metric - ak chceme teplotu merať v stupňoch Celzia, alebo
  • imperial - ak chceme teplotu merať v stupňoch Fahrnheita.

Predvolená konfigurácia bude zatiaľ vyzerať takto:

{
  "units": "standard"
}
# device.py
import json

def read_config():
  try:
    with open(CONFIG_FILE, 'r') as file:
      return json.load(file)
  except OSError:
    print('Error: Config file not found. Creating default one.')
    with open(CONFIG_FILE, 'w') as file:
      json.dump(DEFAULT_CONFIG, file)
      return DEFAULT_CONFIG

Task

Overte vytvorenú implementáciu.

Ak ste postupovali správne, predvolený súbor sa vytvorí automaticky v prípade, ak chýba v súborovom systéme mikrokontroléra.

Meriame teplotu v správnych jednotkách

Zo senzora DHT11 získame teplotu ako celé číslo v stupňoch Celzia. V tomto kroku teda aktualizujeme kód tak, aby sme vedeli hodnotu teploty zobraziť v správnych jednotkách vzhľadom na aktuálnu konfiguráciu.

Task

Vytvorte funkciu convert_temp(), ktorá prevedie hodnotu teploty do správnych jednotiek.

Funkcia bude mať tieto parametre:

  • value - nameraná hodnota v stupňoch Celzia, ktorá bude typu int
  • units - reťazec, ktorého hodnota môže byť jedna z hodnôt standard | metric | imperial

Funkcia vráti hodnotu typu float, ktorá bude reprezentovať hodnotu teploty v jednotkách zadaných v parametri units. V prípade, že hodnota parametra units nebude správna, vráťte teplotu v Kelvinoch.

def convert_temp(value: float, units: str) -> float:
    if units == 'metric':
        return value

    if units == 'imperial':
        return value * 9/5 + 32

    return value + 273.15

Task

Overte vytvorenú implementáciu.

Ak ste postupovali správne, zmenou hodnoty kľúča v konfiguračnom súbore dostanete nameranú hodnotu teploty v rozdielnych jednotkách.

Ďalšie úlohy

  1. Súbor s konfiguráciou nemusí byť valídny. V prípade, že sa tak stane, dôjde pri jeho načítaní k výnimke. Aktualizujte preto funkciu read_config() tak, aby v prípade pokusu o načítanie nevalídneho konfiguračného súboru tento súbor prepísala predvolenou konfiguráciou.

  2. Jazyk MicroPython nemá k dispozícii modul na logovanie. Preto vytvorte samostatný modul log.py, ktorý chýbajúcu funkcionalitu poskytne. V tomto module vytvorte (minimálne) tieto funkcie:

    • debug() - Funkcia na vypísanie logovacích správ úrovne DEBUG.
    • info() - Funkcia na vypísanie logovacích správ úrovne INFO.
    • warning() - Funkcia na vypísanie logovacích správ úrovne WARNING.
    • error() - Funkcia na vypísanie logovacích správ úrovne ERROR.
    • critical() - Funkcia na vypísanie logovacích správ úrovne CRITICAL.

    Pre potreby logovania vytvorte globálnu premennú LOG_LEVEL, pomocou ktorej bude možné nastaviť úroveň logovania globálne pre celé zariadenie. To znamená, že ak bude nastavená vyššia úroveň logovania (napr. úroveň ERROR), nebudú sa zobrazovať logovacie správy nižších úrovní (napr. v prípade úrovne logovania ERROR sa nebudú zobrazovať správy úrovní DEBUG, INFO a WARNING).

Ďalšie zdroje