7.1 Pametna meteo stanica
Ništa u ovom projektu nije novo. Senzor je onaj iz sekcije 5, ekran je onaj iz sekcije 4, a Wi-Fi je onaj iz sekcije 6. Novo je to što sva tri rade odjednom, u jednoj skripti, na jednom paru žica: pločica koja mjeri prostoriju, prikazuje vrijednost na vlastitom ekranu i te iste brojeve stavlja na internet gdje ih možeš pročitati odasvud.
Ta kombinacija je ono što ljudi misle pod IoT: mala stvar koja mjeri nešto lokalno i prijavljuje to negdje drugdje.
U ovoj dokumentaciji naučit ćeš:
- Kako staviti dva Qwiic modula na jednu sabirnicu, i zašto se međusobno ne smetaju.
- Za što služi I2C adresa, u jednoj situaciji gdje to konačno postaje važno.
- Kako poslati mjerenje web serveru pomoću HTTP POST zahtjeva.
- Zašto ekran ostaje prazan prvih trideset sekundi, i zašto to nije greška.
- Zašto je ista vrijednost u istoj skripti formatirana na tri različita načina.
- Kako napisati znak za stupnjeve na ekranu koji ne poznaje tvoj znakovni skup.
Potreban hardver:
- 1x Soldered NULA MINI pločica
- 1x Breadboard
- 1x Soldered SHTC3 senzor temperature i vlage
- 1x 16x2 LCD ekran s I2C adapterom
- 2x Qwiic kabela
- 1x USB-C kabel
Spajanje komponenti
Pet koraka, a tri od njih su samo utiskivanje kabela.
1. Umetni NULA MINI pločicu na breadboard
Utisni pločicu u jedan kraj breadboarda tako da njezina dva reda pinova sjednu s obje strane središnjeg kanala. Na fotografijama zauzima redove 25 do 30.

2. Utisni prvi Qwiic kabel u pločicu
NULA MINI ima jedan Qwiic konektor, na rubu pločice između tipki USER i RST, označen s qwiic na silkscreenu. Utisni kabel dok ne klikne.

- i +. To je konektor za bateriju, i Qwiic kabel u njega ne ulazi.Ako želiš vidjeti točno o kojem se konektoru radi na goloj pločici, ovdje je istaknut:

3. Utisni drugi kraj u SHTC3 senzor
Senzor je mala ljubičasta pločica sa silkscreenom SHTC3 BREAKOUT. Ima dva Qwiic konektora, po jedan na svakom kraju. Utisni kabel u bilo koji od njih, a drugi ostavi slobodan. Ovo je prvi put u kitu da se rezervni konektor stvarno koristi.

4. Nalančaj ekran na senzor
Uzmi drugi Qwiic kabel. Utisni jedan kraj u slobodan konektor SHTC3-a, a drugi u bilo koji od dva konektora na ljubičastom I2C LCD ADAPTER na pozadini ekrana.

To je jedina stvarno nova veza u projektu, i vrijedi biti načisto s tim što ona nije. Drugi kabel ne vodi ekran kroz senzor, tako da senzor podatke prosljeđuje dalje. Oba konektora na SHTC3 spojena su na ista četiri vodiča: to je jedno spojište s dvije utičnice. Nalančavanjem samo izbjegavaš potrebu za pločicom s tri Qwiic konektora na njoj.
5. Spoji USB-C kabel
Utisni USB-C kabel u pločicu i u računalo. Ljubičasto PWR svjetlo se upali, a i oba modula su napojena. Sve na lancu uzima što mu treba preko tih istih dvaju kabela.

Na tom redu punih blokova vrijedi se zadržati trenutak. To je ono što HD44780 ekran prikazuje kada ima napajanje ali nikada nije inicijaliziran, stanje u kojem se budi prije nego mu je bilo koji kod progovorio. Drugu verziju toga vidio si u primjeru 4.1, gdje je ekran bio upaljen ali potpuno prazan. Oba izgleda znače istu stvar: ekran ima napajanje, i ništa se iznad toga još ne može zaključiti.
Dva modula, jedan par žica
Svaki Qwiic primjer do sada koristio je jedan modul, što je značilo da adresa ispisana na tim pločicama nikada nije bila važna. Ovdje jest.
I2C je sabirnica. Dvije signalne žice dijeli sve što je u njih utisnuto, pa kada pločica pošalje bajt, primaju ga i senzor i ekran. Kaos sprječava to što svaka poruka počinje adresom, a modul reagira samo na poruke koje nose njegovu vlastitu:
| Modul | Adresa | Gdje je zapisana |
|---|---|---|
| 16x2 LCD, preko svog adaptera | 0x20 | I2C ADDR 0X20, na ljubičastom adapteru |
| SHTC3 senzor | 0x70 | nije ispisana, fiksirana unutar čipa |
0x20 i 0x70 su različite, pa ta dva modula dijele jedan par žica i nijedan nikada ne odgovara za drugi. To je cijeli trik, i zato skripta isti i2c objekt predaje oba drivera i onda na nalančavanje uopće zaboravi:
i2c = I2C(0, scl=Pin(7), sda=Pin(6))
shtc3 = SHTC3(i2c)
lcd = LCD_I2C(i2c)
Jedna veza, stvorena jednom, i oba je dijele. lcd.begin() i shtc3.begin() zatim se pišu točno kako su se pisali u 4.1 i 5.1.
I2C() linija konačno isplati. U Arduino skici svaka biblioteka poziva Wire.begin() sama i moraš vjerovati da se slažu; ovdje vidljivo postoji jedan objekt sabirnice, i možeš vidjeti kako se oba modula predaju njemu.A0, A1 i A2 na LCD adapteru: njihovo premoštavanje pomiče ekran na 0x27, pa se drugi identičan ekran može pridružiti istom kabelu. Ovdje ti ne trebaju, jer se 0x20 i 0x70 nikada nisu mogli sudariti.Postavljanje webhook.site
Skripti treba mjesto na internetu kamo će poslati svoje vrijednosti, a webhook.site daje jedno besplatno i bez računa.
- Otvori webhook.site u pregledniku (engl. browser). Generira ti jedinstveni URL u trenutku kada se stranica učita.
- Kopiraj adresu prikazanu pod Your unique URL. Izgleda kao
https://webhook.site/fce7fced-1f3b-4ea1-8ed7-498130bbe714. - Ostavi tu karticu preglednika otvorenom. Svaka vrijednost koju tvoja pločica pošalje pojavit će se u njoj.

Zatim je zalijepi u skriptu, zamijenivši tekst rezerviranog mjesta između navodnika, ali dok to radiš promijeni https na početku u http:
webhook_url = "http://webhook.site/your-unique-id"
Promijeni https u http, ili će se projekt činiti zamrznutim. Adresa koju ti webhook.site pokaže počinje s https, a na ovoj pločici https zahtjev nikada ne završi: pločica otvori vezu, započne kriptirani handshake, i onda ga čeka zauvijek. Nema greške i nema isteka vremena. Skripta se jednostavno zaustavi na prvom pozivu urequests.post(), pa u konzoli dobiješ jednu liniju s temperaturom, ništa na webhook.siteu, i nikakve daljnje vrijednosti, dok ekran nastavlja prikazivati to prvo mjerenje.
Izbacivanje s umjesto toga šalje vrijednost nekriptirano, što webhook.site savršeno veselo prihvaća, i onda sve radi kako je opisano niže. To je ograničenje MicroPython builda na pločici, a ne bilo što vezano za tvoje spajanje ili tvoju webhook stranicu.
https je ono što štiti lozinku ili broj kartice, a pravom proizvodu koji šalje prave podatke on bi morao raditi.Dok si već tu, ispuni i podatke svoje mreže:
ssid = "your ssid"
password = "your password"
https zaustavlja skriptu mrtvu na prvoj vrijednosti, kako je opisano iznad. Jedino ti senzor jasno kaže kada nije u redu.7d uz URL, i drži ih 50, a to je brojač 0/50. Pri jednoj vrijednosti svakih trideset sekundi, pedeset zahtjeva je oko 25 minuta prije nego tiho prestane bilježiti nove.Zaustavljanje kada senzora nema
Ova skripta radi jednu stvar koju nijedna ranija ne radi. Ako senzor ne odgovori, odbija nastaviti:
if not shtc3.begin():
print("SHTC3 init failed!")
lcd.print("SHTC3 error!")
while True:
time.sleep(0.1)
Ta posljednja petlja ne radi ništa zauvijek. To je namjeran zastoj: nema smisla povezivati se na Wi-Fi i slati vrijednosti kada nema što čitati, pa skripta kaže što je pošlo po zlu na oba izlaza i parkira se.
while True s malim sleepom u njemu je MicroPython način pisanja "dalje se ne ide". Sleep je važan: potpuno prazna petlja vrtjela bi procesor punom brzinom za ništa.Prvih trideset sekundi
U ovom projektu postoji jedan trenutak koji izgleda pokvareno a nije, pa ga vrijedi znati prije nego pokreneš, a ne poslije.
Kada je pokretanje završeno, skripta briše ekran i ulazi u petlju. Ali vrijednost se uzima samo kada je time.ticks_ms() prošao UPDATE_MS iza posljednje, a last_update počinje na nuli. Zato prva vrijednost uvijek sleti trideset sekundi nakon što se skripta pokrene, kako god brzo je ostalo prošlo.
U međuvremenu je ekran upaljen i potpuno prazan. Izgleda točno kao greška kontrasta iz primjera 4.1. Nije. Pričekaj, i Temp: i Hum: pojavljuju se zajedno.
UPDATE_MS na nešto kao 5000. Vrati ga ipak prije nego pločicu ostaviš da radi: pri vrijednosti svakih pet sekundi besplatna webhook stranica napuni svojih pedeset mjesta u oko četiri minute.Ista vrijednost, tri načina
Jedno mjerenje odlazi s pločice trima različitim putovima u ovoj skripti, i svaki ga formatira drugačije:
print("Temperature: {:.2f} °C, Humidity: {:.2f} %".format(temperature, humidity))
lcd.print("Temp: {:.1f}\xDFC".format(temperature))
post_data = "temperature={:.2f}&humidity={:.2f}".format(temperature, humidity)
Konzola dobiva dvije decimale, jer prostora ne manjka. Ekran dobiva jednu, jer red od 16 znakova mora držati Temp: , broj, znak za stupnjeve i C. POST dobiva dvije, jer ti brojevi idu računalu a ne osobi, i mogu doći u punoj točnosti.
{:.2f} i {:.1f} su isti specifikator formata s drugačijom točnošću: decimalni broj s ovoliko cifara nakon točke. To je isti mehanizam kao {:02d} koji se koristi za dopunjavanje nulama u budilici, što vrijedi primijetiti: jedna sintaksa pokriva oba posla.Znak za stupnjeve
Druga razlika je to što jedna linija piše ° a druga piše \xDF:
print("Temperature: {:.2f} °C, ...") # konzola
lcd.print("Temp: {:.1f}\xDFC".format(temperature)) # ekran
Tvoje računalo i HD44780 ne koriste isti znakovni skup. Pisanje ° direktno na ekran dalo bi pogrešan simbol, pa skripta umjesto toga traži znak 0xDF, gdje u ugrađenom fontu ekrana živi znak za stupnjeve.
\xDF unutar stringa znači "znak s kodom 0xDF", što je 223 u običnim brojevima. Arduino verzija ovog projekta istu stvar radi pozivom lcd.write(223) kao zasebnom izjavom; u Pythonu to može sjediti unutar samog stringa.print(".", end="") nastavlja gdje je posljednja stala. Na ekranu ne, jer lcd.setCursor(0, 1) svaki put vraća kursor na početak reda, pa dobiješ jednu točku koja tamo sjedi i nikada se ne pomiče.Kod
# I2C je ono što Qwiic konektor nosi, a i senzor i ekran su Qwiic moduli.
from machine import I2C, Pin
# Soldered driveri za SHTC3 senzor i LCD ekran, oba se nalaze u lib folderu repozitorija
# primjera.
from SHTC3 import SHTC3
from LCD import LCD_I2C
# Modul network pridružuje se Wi-Fi mreži, a urequests nam omogućuje da govorimo HTTP.
import network
import urequests
import time
# Ove dvije varijable drže ime tvoje Wi-Fi mreže (SSID) i njezinu lozinku.
ssid = "your ssid"
password = "your password"
# Ova varijabla drži adresu na koju šaljemo naše vrijednosti. Otvori https://webhook.site u pregledniku, kopiraj jedinstveni
# link koji ti pokaže, i zalijepi ga između navodnika ispod.
webhook_url = "your unique url"
# Ovdje postavljamo I2C vezu. Na NULA MINI, I2C koristi IO6 za liniju podataka (SDA) i IO7 za liniju
# takta (SCL), a to su pinovi na koje je Qwiic konektor spojen. Primijeti da oba modula dijele ovu jednu
# vezu: to je ono što ti dopušta da nalančaš nekoliko Qwiic modula a da za njih ne definiraš nikakve pinove.
i2c = I2C(0, scl=Pin(7), sda=Pin(6))
# Ovdje stvaramo naša dva objekta, jedan za senzor i jedan za ekran, i oba predajemo istu I2C
# vezu.
shtc3 = SHTC3(i2c)
lcd = LCD_I2C(i2c)
# Ove dvije varijable drže najnovije vrijednosti, a dvije ispod njih upravljaju koliko vremena prođe između
# vrijednosti. 30000 milisekundi je trideset sekundi.
temperature = 0.0
humidity = 0.0
last_update = 0
UPDATE_MS = 30000
# Ovdje pripremamo ekran. begin() pokreće komunikaciju i mora doći prvi. backlight() zatim pali
# svjetlo iza ekrana, i mora doći nakon begin(), koji bi ga inače ponovno ugasio.
lcd.begin()
lcd.backlight()
lcd.clear()
lcd.setCursor(0, 0)
lcd.print("Weather Station")
lcd.setCursor(0, 1)
lcd.print("Starting...")
time.sleep(1)
lcd.clear()
# begin() na senzoru priprema ga za upotrebu i kaže nam je li odgovorio, vraćajući True pri uspjehu i False
# pri neuspjehu. Ako senzora nema, ovom projektu ne ostaje što mjeriti, pa umjesto da nastavimo
# ispisujemo problem i zaustavljamo se ovdje. Petlja while True ispod nikada ne završava, a to je jednostavan način da se kaže "dalje se
# ne ide".
if not shtc3.begin():
print("SHTC3 init failed!")
lcd.print("SHTC3 error!")
while True:
time.sleep(0.1)
# Ovdje stvaramo naš mrežni objekt i uključujemo Wi-Fi hardver, pa pokrećemo pokušaj povezivanja. connect()
# ne čeka da se povezivanje dovrši, pa korisniku govorimo što se događa i u konzoli i na
# ekranu.
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
print("Connecting to Wi-Fi", end="")
lcd.setCursor(0, 0)
lcd.print("Connecting WiFi")
wlan.connect(ssid, password)
# Ovdje na vezu čekamo sami. isconnected() nam kaže jesmo li već na mreži.
while not wlan.isconnected():
time.sleep(0.5)
print(".", end="")
lcd.setCursor(0, 1)
lcd.print(".")
# ifconfig() kao svoju prvu vrijednost vraća adresu koju je router dodijelio našoj pločici.
print()
print("Wi-Fi connected!")
print("IP:", wlan.ifconfig()[0])
# Daj korisniku znati da smo na mreži, pa očisti ekran da vrijednosti počnu na praznom ekranu.
lcd.clear()
lcd.print("WiFi Connected!")
time.sleep(0.8)
lcd.clear()
print("Smart Weather Station ready!")
while True:
# time.ticks_ms() vraća broj milisekundi koje su prošle od uključivanja pločice. Koristimo ga umjesto
# običnog sleepa da pločica ostane slobodna za drugi posao između vrijednosti.
now = time.ticks_ms()
# Ovdje provjeravamo koliko je vremena prošlo od posljednje vrijednosti. Novu uzimamo samo kada prođe
# UPDATE_MS milisekundi, i odmah pamtimo trenutno vrijeme kao novu početnu točku.
if time.ticks_diff(now, last_update) >= UPDATE_MS:
last_update = now
# sample() govori senzoru da obavi svježe mjerenje, a dvije funkcije čitanja nam zatim predaju
# rezultate. Moramo prvo pozvati sample(), inače bismo stalno dobivali prethodno mjerenje.
shtc3.sample()
temperature = shtc3.readTemperature()
humidity = shtc3.readHumidity()
# Ispiši vrijednosti u konzolu. ":.2f" govori Pythonu da broj prikaže s dvije decimale.
print("Temperature: {:.2f} °C, Humidity: {:.2f} %".format(temperature, humidity))
# Sada iste vrijednosti prikazujemo na ekranu. Prvo ga brišemo, jer bi pisanje kraćeg teksta preko duljeg
# ostavilo zaostale znakove za sobom.
# "\xDF" je kod znaka koji ekran koristi za znak za stupnjeve. Konzola i LCD ne koriste
# isti znakovni skup, i zato znak za stupnjeve pišemo na jedan način iznad a na drugi ovdje.
lcd.clear()
lcd.setCursor(0, 0)
lcd.print("Temp: {:.1f}\xDFC".format(temperature))
lcd.setCursor(0, 1)
lcd.print("Hum: {:.1f} %".format(humidity))
# Prije nego bilo što pošaljemo, provjeravamo jesmo li još na mreži. Wi-Fi veza može pasti u svakom trenutku.
if wlan.isconnected():
# Ovdje gradimo podatke koje ćemo poslati. Format "name=value&name=value" isti je onaj koji
# preglednik koristi kada predaješ jednostavnu web formu: ampersand ("&") odvaja jednu vrijednost od sljedeće.
post_data = "temperature={:.2f}&humidity={:.2f}".format(temperature, humidity)
# Zahtjev omotavamo u try blok jer sve što ide preko mreže može pasti.
try:
# post() šalje zahtjev zajedno s našim podacima i čeka odgovor. Zaglavlje koje prilažemo
# opisuje format u kojem su naši podaci napisani, da server zna kako ih pročitati.
response = urequests.post(
webhook_url,
data=post_data,
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
print("POST successful! Response code:", response.status_code)
# close() otpušta memoriju koju je odgovor koristio. Uvijek zatvori odgovor kada završiš.
response.close()
except Exception as e:
print("POST failed. Error:", e)
else:
# Ako smo izgubili vezu, pokreni novi pokušaj i probaj ponovno pri sljedećoj vrijednosti.
print("Wi-Fi disconnected. Trying to reconnect...")
wlan.connect(ssid, password)
# Vrlo kratka pauza ostavlja procesoru trenutak da obavi svoj posao u pozadini.
time.sleep_ms(10)
Što bi trebao vidjeti
Pritisni Run i drži karticu webhook.site otvorenom uz editor. Postoje tri mjesta koja treba gledati, i trebala bi se međusobno slagati.
Na ekranu
Nakon pozdrava Weather Station / Starting..., poruke Connecting WiFi i tridesetsekundnog čekanja, vrijednosti se pojavljuju:

Nježno dahni na senzor s nekoliko centimetara udaljenosti i vrijednost vlage poraste u sekundu ili dvije, ali vidjet ćeš to samo pri sljedećoj vrijednosti, do trideset sekundi kasnije. To zaostajanje je najjasniji podsjetnik da ekran nije spojen na senzor u nikakvom živom smislu: prikazuje ono što je tamo stavio posljednji krug petlje.
U konzoli
Connecting to Wi-Fi....
Wi-Fi connected!
IP: 192.168.75.75
Smart Weather Station ready!
Temperature: 27.65 °C, Humidity: 44.13 %
POST successful! Response code: 200
Temperature: 28.20 °C, Humidity: 43.77 %
POST successful! Response code: 200
Čitajući prema dolje:
Connecting to Wi-Fi....pokazuje četiri točke, po jednu svakih 500 ms, pa je ovoj pločici trebalo oko dvije sekunde da se pridruži mreži. Red točaka je upotrebljiva štoperica, a broj se malo mijenja od jednog pokretanja do drugog. Sve od oko četiri do osam točaka je normalno.IP: 192.168.75.75je adresa koju je tvoj router dodijelio pločici. To je privatna adresa, smislena samo unutar tvoje vlastite mreže.Smart Weather Station ready!je posljednja linija prije nego petlja počne. Sve nakon ovoga se ponavlja.Temperature: 27.65 °C, Humidity: 44.13 %je vrijednost, na dvije decimale. Tvoji brojevi bit će naravno drugačiji. Konzola uvijek daje dvije decimale gdje ekran daje jednu, pa je linija konzole27.65isto mjerenje koje ekran piše kao27.6.- U
POST successful! Response code: 200,200je HTTP kod za "u redu, imam ga". - Zatim iste dvije linije ponovno, trideset sekundi kasnije. Taj par je cijela petlja, i ponavlja se dokle god je pločica ostavljena da radi.
Na webhook.site

Ova stranica ima više reći od konzole:
- Vremenske oznake su
10:58:40i10:59:10: točno trideset sekundi razmaknute. To je daleko bolji dokaz daUPDATE_MSradi svoj posao od bilo čega ispisanog na samoj pločici. Form valuesnavoditemperatureihumiditykao odvojena imenovana polja. Razložena su tako samo zbog zaglavljaContent-Type. Bez njega bi server primio iste znakove i ne bi imao pojma da su bili zamišljeni kao forma.Raw Contentpokazuje što je stvarno poslano:temperature=27.93&humidity=40.80. To je točno string iz kojeg jepost_databio sagrađen: ista dva broja koja je konzola ispisala u tom izvođenju, spojena s&. (Ovaj screenshot je iz drugog izvođenja od ispisa konzole iznad, pa se vrijednosti s njim ne poklapaju; na tvojoj pločici će se.)Size: 32 bytesje dužina tog stringa. Prebroji ako želiš:&i znakovi=također su dio tereta.
Host na ovom screenshotu je namjerno posivljeno. Prikazuje javnu adresu routera za kojim pločica stoji, a ne 192.168.75.75 koju je pločica ispisala. Oboje je ispravno: tvoj router privatnu adresu na izlasku zamjenjuje svojom javnom, a taj proces se zove NAT, i server na drugoj strani može vidjeti samo router. Webhook.site uz to stavlja Whois i Shodan linkove, što je pošten podsjetnik da s javnim IP-om treba biti pažljiv.webhook_url još počinje s https. Promijeni ga u http i pokreni ponovno. Cijelo objašnjenje je u odsjeku o webhook.site iznad. Znak koji odaje je to što ekran posve veselo nastavlja prikazivati to prvo mjerenje: pločica se nije srušila, zaglavila se čekajući unutar zahtjeva.SHTC3 init failed! a na ekranu SHTC3 error!, skripta se tamo namjerno zaustavlja i nikada ne dođe do Wi-Fi dijela. Provjeri jesu li Qwiic kabeli do kraja utisnuti na sva četiri kraja, pa provjeri scl=Pin(7), sda=Pin(6) u liniji I2C().CONTRAST. Okreći ga polako odvijačem dok se znakovi ne pojave. Vidi 4.1 Prikaz poruke na LCD-u za cijeli opis te greške, ali zapamti da prvo treba isključiti tridesetsekundno čekanje.Kamo dalje s ovim
Sve u ovom projektu je jednu varijablu daleko od toga da bude nešto drugo:
- Promijeni
UPDATE_MSi mijenjaš kako često se prostorija mjeri. - Zamijeni dvije
lcd.printlinije i ekran prikazuje prvo vlagu. - Dodaj treće ime i vrijednost u
post_datai webhook stranici naraste treće form polje.
Jedno što odavde ne možeš jest pročitati podatke natrag: webhook.site ti pokazuje zahtjeve kako dolaze, ali nije mjesto gdje ih se drži. Slanje istog POST-a servisu za tablice ili bazi podataka umjesto toga je prirodan sljedeći korak, a ništa oko pločice ili spajanja ne bi se moralo promijeniti.
Cijeli primjer
Pogledaj cijeli kod primjera na linku ispod:
7.1_Smart_Weather_Station.py
Projekt koji mjeri temperaturu i vlagu pomoću SHTC3 senzora, prikazuje vrijednosti na 16x2 LCD-u i šalje ih na webhook.site svakih 30 sekundi.