Search
Instalace modulů:
$ pip install pyserial matplotlib pyqt6 pysqlite3 bleak paho-mqtt numpy
V případě, že nemáte administrátorská práva na počítači:
$ pip install --user pyserial matplotlib pyqt6 pysqlite3 bleak paho-mqtt numpy
Řada aplikací bude napsána v Pythonu, flexibilním programovacím jazyku vhodném pro rychlé prototypování. Vždy bude připravena kostra programu, kterou lze přímo použít pro vlastní projekt. Pokud byste se chtěli dovědět něco víc o Pythonu, je možné využít např. podklady předmětu BAB37ZPR: 2021/22, 2020/21. Lze také doporučit volně dostupnou knihu Python Programming And Numerical Methods: A Guide For Engineers And Scientists.
Jako zdroj dat lze využít např. generátor harmonického signálu na gitlabu. Aplikace pro PC v jazyce Python jsou také k dispozici na gitlabu.
Pro UART komunikaci mezi embedded zařízením a PC použijeme knihovnu PySerial. Připojení proběhne vytvoření instance třídy, parametry konstruktoru jsou název sériového portu a rychlost komunikace. Je celkem vhodné ošetřit připojení pro případ, že spojení nelze uskutečnit. V následujícím kódo je zařízení připojeno k portu COMXXX (za XXX dosaďte podle potřeby) a komunikuje rychlostí 115200 baudů.
COMXXX
import serial try: ser = serial.Serial('COMXXX', 115200) ser.flushInput() except: print("unable to open COM port")
Se zařízením je možné komunikovat na úrovni bytů nebo znaků. Pokud zařízení posílá data ve formě znaků (tj. posílá byty s významem ASCII kódů), lze data přijmout třeba takto:
data = ser.readline().decode() print(data)
Pokud je z hlediska aplikace výhodnější používat byty ve s významem čísla (např. v rozsahu 0-255), je možné přijmout a dekódovat takto:
byte = ser.read() decoded_bytes = int.from_bytes(byte, byteorder = 'little')
Argumentem metody read() je počet bytů, které jsou najednou přečteny. Lze tedy např. předpokládat, že embedded zařízení posílá dva byty současně a tyto dva byty buď mohou reprezentovat číslo typu short, nebo dva samostatné byty a a b, které je třeba dekódovat:
read()
short
a
b
byte = ser.read(2) decoded_bytes = int.from_bytes(byte, byteorder = 'little') a = decoded_bytes & 255; b = (decoded_bytes >> 8) & 255;
Pokud bychom potřebovali přenést po UART hodnoty různých datových typů, můžeme je na straně mikrokontroléru uložit do struktury.
BufferedSerial pc(USBTX, USBRX, 115200); //-- typedef struct data { unsigned int Si7021_t; unsigned int Si7021_h; int Si7210_t; float BMP280_t; }; // --- data a; // -- pc.write(&a, sizeof(a));
V Pythonu pak lze pro dekódování dat ve struktuře využít knihovny ctypes nebo struct.
from ctypes import Structure, c_uint, c_int, c_float, sizeof class DataPoint(Structure): _pack_ = 1 _fields_ = [ ("Si7021_t", c_uint), ("Si7021_h", c_uint), ("Si7210_t", c_int), ("BMP280_t", c_float) ] # byte = ser.read(16) buffer = bytearray(byte) Point = DataPoint.from_buffer(buffer) # teplota z Si7021 je pak dostupná jako Point.Si7021_t/1000,
K vykreslení dat přicházejících po UART rozhraní použijeme knihovnu matplotlib. Data pro vykreslení jsou uložena ve vektoru vytvořeném pomocí knihovny NumPy. Vektor má délku odpovídající délce okna, a v cyklu jsou na začátek vektoru přidávána data metodou append. V cyklu jsou současně vykreslována data ze začátku vektoru.
append
import matplotlib.pyplot as plt import numpy as np plot_window = 20 y_var = np.array(np.zeros([plot_window])) plt.ion() fig, ax = plt.subplots() line, = ax.plot(y_var) ax.set_ylim([0, 255]) while True: # zde by mel byt kod pro ziskani a dekodovani dat y_var = np.append(y_var, data) y_var = y_var[1:plot_window+1] line.set_ydata(y_var) fig.canvas.draw() fig.canvas.flush_events()
Pokud bychom chtěli vykreslovat dvě křivky, je třeba v původním kódu udělat následující úpravy:
# konfigurace fig, ax = plt.subplots(2) line0, = ax[0].plot(y0_var) line1, = ax[1].plot(y1_var) ax[0].set_ylim([0, 255]) ax[1].set_ylim([0, 255]) # samotne vykreslovani y0_var = np.append(y0_var, a) y1_var = np.append(y1_var, b) y0_var = y0_var[1:plot_window+1] y1_var = y1_var[1:plot_window+1] line0.set_ydata(y0_var) line1.set_ydata(y1_var)
Pro uložení dat můžeme využít SQLite databázi. Její výhodou je, že pracuje s lokálním binárním souborem a má minimální nároky na paměť a výkon počítače - veškerá potřebná funkcionalita je totiž vytvářena knihovnou, která pracuje s binárním souborem. Pro jednoduchost můžete využít modul nsidb, který vytváří třídu pro ukládání dvou hodnot typu float reprezentující teplotu a vlhkost přečtenoou ze senzoru Si7021. Hodnoty jsou funkci pro zápis předávány jako tuple.
float
Samotný hlavní program pro uložení dat může vypadat třeba takto:
from nsidb import * conn = db_conn("iot.db") db_create(conn) db_insert (conn, (3.14, 25.5)) rows = db_fetch (conn) for row in rows: print(row)