7.1 Pametna meteo stanica
Ovo je prvi projekt, a ne vježba, i razlika je u tome što ništa u njemu 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 skici, 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 skici ispisana na tri različita načina.
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 ikakva skica progovorila. 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 se ničemu u skici ne mora reći za nalančavanje. lcd.begin() i shtc3.begin() napisani su točno kako su bili u 4.1 i 5.1.
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
Skici 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 skicu, zamijenivši tekst rezerviranog mjesta između navodnika:
const char* webhookURL = "https://webhook.site/your-unique-id";
Dok si već tu, ispuni i podatke svoje mreže:
const char* ssid = "your ssid";
const char* password = "your password";
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.Prvih trideset sekundi
U ovom projektu postoji jedan trenutak koji izgleda pokvareno a nije, pa ga vrijedi znati prije prijenosa, a ne poslije.
Kada setup() završi, skica briše ekran i ulazi u loop(). Ali vrijednost se uzima samo kada je millis(), vrijeme od uključivanja, prošao UPDATE_MS iza posljednje, a lastUpdate počinje na nuli. Zato prva vrijednost uvijek sleti trideset sekundi nakon uključivanja, kako god brzo je ostatak setupa prošao.
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 skici, i svaki ga formatira drugačije. Najbrži način da razumiješ što se stvarno šalje je vidjeti zašto.
Serial.print(temperature, 2); // 27.93
lcd.print(temperature, 1); // 27.9
String postData = "temperature=" + String(temperature, 2); // temperature=27.93
Serial Monitor 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.
Znak za stupnjeve je druga razlika:
Serial.print(" °C, Humidity: "); // pravi znak °
lcd.print((char)223); // znak broj 223 u vlastitom skupu ekrana
Tvoje računalo i HD44780 ne koriste isti znakovni skup. Pisanje ° direktno na ekran dalo bi pogrešan simbol, pa skica umjesto toga traži znak 223, gdje u ugrađenom fontu ekrana živi znak za stupnjeve.
print nastavlja gdje je prethodni stao. 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
/**
**************************************************
*
* @file 7.1_Smart_Weather_Station.ino
* @brief Projekt koji spaja tri stvari koje si već naučio odvojeno: SHTC3 senzor temperature
* i vlage iz sekcije 5, LCD ekran iz sekcije 4, i Wi-Fi vezu iz
* sekcije 6. Pločica mjeri temperaturu i vlagu, prikazuje ih na LCD-u, i šalje ih na
* webhook na internetu pa vrijednosti možeš pratiti odasvud.
* Za detalje, shemu spajanja i više, pogledaj dokumentaciju primjera na: <link placeholder>
* @author Soldered
***************************************************
*/
/*
Biblioteka WiFi sadrži sve što je potrebno za pridruživanje Wi-Fi mreži.
*/
#include <WiFi.h>
/*
Biblioteka HTTPClient omogućuje nam da govorimo HTTP, pa naše vrijednosti možemo poslati serveru.
*/
#include <HTTPClient.h>
/*
Soldered biblioteka za SHTC3 senzor temperature i vlage.
*/
#include "SHTC3-SOLDERED.h"
/*
Soldered biblioteka za LCD ekran.
*/
#include "LCD-SOLDERED.h"
/*
Ove dvije varijable drže ime tvoje Wi-Fi mreže (SSID) i njezinu lozinku. Zamijeni tekst između
navodnika svojim mrežnim podacima.
*/
const char* ssid = "your ssid";
const char* 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. Drži tu karticu preglednika otvorenom i vidjet ćeš kako se svaka
vrijednost u njoj pojavljuje.
*/
const char* webhookURL = "your unique url";
/*
Ovdje stvaramo naša dva objekta: jedan za senzor i jedan za ekran. Objekt je naš način razgovora s
uređajem: svaku funkciju koju na njemu pozovemo, pozivamo preko njegovog imena.
Senzoru ne trebaju brojevi pinova jer koristi easyC, a to je Soldered ime za I2C vezu preko jednog
kabela, a I2C uvijek koristi ista dva pina na pločici (IO6 i IO7 na NULA pločici).
*/
SHTC3 shtc3;
LCD lcd(16, 2);
/*
Ove dvije varijable drže najnovije vrijednosti. To su decimalni brojevi, i zato su float.
*/
float temperature = 0.0;
float humidity = 0.0;
/*
Ova varijabla pamti trenutak posljednje vrijednosti, a ona ispod nje definira koliko vremena prođe između dvije
vrijednosti, u milisekundama. 30000 milisekundi je trideset sekundi. Slobodno eksperimentiraj s ovom vrijednošću, ali imaj
na umu da se svaka vrijednost i šalje preko interneta.
*/
unsigned long lastUpdate = 0;
const unsigned long UPDATE_MS = 30000;
void setup() {
/*
Serial.begin() uspostavlja serijsku komunikaciju između tvoje pločice i tvog računala preko USB kabela. U projektu
ove veličine Serial Monitor je naš glavni alat za otkrivanje što je pošlo po zlu, pa ga pokrećemo prvog.
Kratka pauza nakon njega daje vezi trenutak da se smjesti, pa prve poruke nisu izgubljene.
*/
Serial.begin(115200);
delay(500);
/*
Ovdje pripremamo ekran. begin() pokreće komunikaciju s njim, backlight() pali njegovo svjetlo da tekst bude
čitljiv, a clear() briše sve što je na ekranu ostalo od prije.
setCursor() zatim odabire gdje će se sljedeći tekst pojaviti: prvi broj je stupac a drugi je red,
i oba počinju brojati od nule. Dakle (0, 0) je gornji lijevi kut a (0, 1) je početak druge linije.
Prvo prikazujemo kratak pozdrav, pa na prvi pogled možemo vidjeti da sam ekran radi.
*/
lcd.begin();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Weather Station");
lcd.setCursor(0, 1);
lcd.print("Starting...");
delay(1000);
lcd.clear();
/*
begin() na senzoru pokreće I2C komunikaciju i kaže nam je li senzor odgovorio, vraćajući true pri
uspjehu i false pri neuspjehu. "!" ispred znači "ne", pa se ovo čita kao "ako se senzor nije pokrenuo".
Ako senzora nema, ovom projektu ne ostaje što mjeriti, pa umjesto da nastavimo ispisujemo
problem i zaustavljamo se ovdje. Petlja while(1) ispod nikada ne završava, a to je jednostavan način da se kaže "dalje se ne ide".
*/
if (!shtc3.begin()) {
Serial.println("SHTC3 init failed!");
lcd.print("SHTC3 error!");
while (1) delay(100);
}
/*
WiFi.begin() pokreće pokušaj povezivanja. Funkcija samo pokreće proces, ne čeka da se dovrši,
pa korisniku govorimo što se događa i u Serial Monitoru i na ekranu.
*/
Serial.print("Connecting to Wi-Fi");
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
WiFi.begin(ssid, password);
/*
Ovdje na vezu čekamo sami. WiFi.status() nam kaže trenutno stanje a WL_CONNECTED je vrijednost koju
prijavljuje kada smo na mreži.
*/
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.setCursor(0, 1);
lcd.print(".");
}
/*
WiFi.localIP() vraća adresu koju je router dodijelio našoj pločici.
*/
Serial.println();
Serial.println("Wi-Fi connected!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
//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!");
delay(800);
lcd.clear();
Serial.println("Smart Weather Station ready!");
}
void loop() {
/*
millis() je funkcija koja vraća broj milisekundi koje su prošle od kada je pločica počela izvršavati trenutni
program. Koristimo ga umjesto delay() da pločica ostane slobodna za drugi posao između vrijednosti.
*/
unsigned long now = millis();
/*
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 (now - lastUpdate >= UPDATE_MS) {
lastUpdate = 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.readTempC();
humidity = shtc3.readHumidity();
//Ispiši vrijednosti u Serial Monitor. Broj 2 govori funkciji koliko decimalnih mjesta da prikaže.
Serial.print("Temperature: ");
Serial.print(temperature, 2);
Serial.print(" °C, Humidity: ");
Serial.print(humidity, 2);
Serial.println(" %");
/*
Sada iste vrijednosti prikazujemo na ekranu. Prvo ga brišemo, jer bi pisanje kraćeg teksta preko duljeg
ostavilo zaostale znakove za sobom.
(char)223 je kod znaka koji ekran koristi za znak za stupnjeve. Serial Monitor 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: ");
lcd.print(temperature, 1);
lcd.print((char)223);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("Hum: ");
lcd.print(humidity, 1);
lcd.print(" %");
/*
Prije nego bilo što pošaljemo, provjeravamo jesmo li još na mreži. Wi-Fi veza može pasti u svakom trenutku, a pokušaj
slanja podataka bez nje samo bi potrošio vrijeme i ispisao greške.
*/
if (WiFi.status() == WL_CONNECTED) {
/*
Ovdje stvaramo naš HTTP klijentski objekt, pripremamo zahtjev pomoću begin(), i opisujemo format naših podataka
pomoću addHeader(). Zaglavlje serveru govori nešto o samom zahtjevu.
*/
HTTPClient http;
http.begin(webhookURL);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
/*
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, a String() pretvara
naše brojeve u tekst da ih se može spojiti s ostatkom pomoću plusa.
*/
String postData = "temperature=" + String(temperature, 2) + "&humidity=" + String(humidity, 2);
/*
POST() šalje zahtjev zajedno s našim podacima i čeka odgovor. Vraća kod odgovora: brojevi
200 i više znače da je server odgovorio, dok negativan broj znači da odgovor nikada nismo dobili.
*/
int httpCode = http.POST(postData);
if (httpCode > 0) {
Serial.print("POST successful! Response code: ");
Serial.println(httpCode);
} else {
//errorToString() negativan kod greške pretvara u kratku rečenicu koju je lakše razumjeti.
Serial.print("POST failed. Error: ");
Serial.println(http.errorToString(httpCode));
}
/*
end() zatvara vezu i otpušta memoriju koju je klijent koristio. Uvijek zatvori vezu kada s njom
završiš, inače će program koji pravi mnogo zahtjeva polako ostati bez memorije.
*/
http.end();
} else {
//Ako smo izgubili vezu, pokreni novi pokušaj i probaj ponovno pri sljedećoj vrijednosti.
Serial.println("Wi-Fi disconnected. Trying to reconnect...");
WiFi.begin(ssid, password);
}
}
}
Što bi trebao vidjeti
Prenesi skicu, pa otvori Serial Monitor i postavi ga na 115200 bauda. Drži svoju karticu webhook.site otvorenom uz njega. 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 loop().
U Serial Monitoru
Čitajući prema dolje od prazne linije:
Connecting to Wi-Fi............pokazuje dvanaest točaka, po jednu svakih 500 ms, pa je ovoj pločici trebalo oko šest sekundi da se pridruži mreži. Red točaka je upotrebljiva štoperica.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 linijasetup(). Sve nakon ovoga dolazi izloop().Temperature: 27.93 °C, Humidity: 40.80 %je vrijednost, na dvije decimale. Usporedi je s fotografijom ekrana iznad:27.93prikazano kao27.9,40.80prikazano kao40.8. Isto mjerenje, dva formata.- U
POST successful! Response code: 200,200je HTTP kod za "u redu, imam ga".
Na webhook.site

Ova stranica ima više reći od Serial Monitora:
- 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 zboghttp.addHeader("Content-Type", "application/x-www-form-urlencoded"). Bez tog zaglavlja server bi 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 jepostDatabio sagrađen, i poklapa se s linijom Serial Monitora znak po znak.Size: 32 bytesje dužina tog stringa. Prebroji ako želiš:&i znakovi=također su dio tereta.user-agent: ESP32HTTPClientje kako seHTTPClientpredstavlja. Tvoja pločica najavila je što je a da je nitko nije pitao.
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.SHTC3 init failed!, skica 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 je li Soldered NULA Mini ESP32C6 odabrana pločica. Odabir bilo koje druge pločice šalje I2C promet na pogrešne pinove, a i dalje se savršeno prevodi i prenosi.CONTRAST. Okreći ga polako odvijačem dok se znakovi ne pojave. Vidi 4.1 Ispis poruke 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
postDatai 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.ino
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.