KKM: ARDUINO ETHERNET SHIELD S W5100

Početnik si s Croduinom. Ili s elektronikom? Za oko ti je zapeo određeni modul, ali ne znaš kako ga koristiti? Bez brige, tu je KKM! Kako Koristiti Module (KKM) je serija blog tutorijala e-radionice na kojoj ćeš pronaći sve što ti treba kako bi započeo rad sa svojim omiljenim modulom. Tutorijali obuhvaćaju: tehničke karakteristike, princip rada, upute kako povezati modul s Croduinom te osnovni kod. Sve ostalo prepuštamo tebi na maštu.

Uvod

U ovome tutorijalu, pokazat' ćemo kako se koristi Ethernet Shield baziran na W5100 integriranom krugu. Taj integrirani krug je mozak cijelog ovog modula te je on zaslužan za svu komunikaciju s Internetom, slanje i primanje podataka, odnosno, pakiranje i raspakivanje paketa koji odakle ili dolaze od njega. Ovaj modul se može koristiti ukoliko žičano želimo povezati naš Croduino na Internet pri tome dohvaćati neke podatke poput temperature zraka u našem gradu ili postavljati neka naša mjerenja (temperatura zraka, vlaga zraka, tlak zraka, brzina vjetra, itd.) na neku Web stranicu (npr. ThingSpeak servis) ili pak želimo napraviti neku vrstu kućne automatizacije, pa želimo neke parametre namještati putem naše lokalne mreže (npr. podešavati temperaturu centralnog grijanja tako da pristupimo Croduinou preko našeg mobitela koji je spojen na isti router na koji je spojen Croduino). No, na početak idemo se pobliže upoznati s našim modulom.

Kako modul radi

Karakteristike modula:

• Napon napajanja: 5V i 3.3V

• Struja: max 183 mA

• Podržane brzine rada Ethernet veze: 10Base-T (10 Mbit/s) i 100Base-Tx (100 Mbit/s)

• Vrsta komunikacije s Croduinom: SPI (samo preko ICSP headera i koristi se za SD karticu i W5100)

• W5100 CS pin: Digitalni pin 10

• SD Card CS pin: Digitalni pin 4
 

Za početak idemo se upoznati s osnovnim pojmovima kao što su Ethernet, IP i MAC adrese, TCP i UDP protokol, HTTP i HTML.

Ethernet je tehnologija komunikacija u mrežama koja je vrlo dobro prihvaćena radi svoje robusnosti, jednostavnosti i brzine. Prve verzije Ethernet tehnologije nisu koristile Ethernet kabel kakav danas poznajemo (a to je UTP - Unshielded Twisted Pair, neoklopljena upletena parica i STP - Shielded Twisted Pair, oklopljena upletena parica, pa čak i optika), već se koristio koaksijalni kabel, kakav se danas koristi za povezivanje antene i radio uređaja. Radi velikog gušenja signala na većim udaljenostima, ograničene brzine prijenosa signala, komunikacije samo u jednom smjeru u jednom trenutku, vrlo brzo je odbačen, te se razvio Ethernet kabel kakvog danas svi poznajemo. (Na slici je prikazan današnji Ethernet kabel [gore] i koakcijalni Ethernet kabel [dolje])

 

 
Ethernet tehnologija koristi CSMA/CD protokol za prijenos podataka, a jedna od važnih karakteristika tog protokola je da može detektirati koliziju (kada dva uređaja pokušaju slati podatke u istom trenutku na istoj liniji).

 
Nakon što smo saznali nešto o samome fizičkom mediju preko kojeg se šalju podaci, možemo krenuti dalje, a to su IP adrese. IP adresa je adresa sačinjena od 4 broja koja su razdvojena točkama. Jedna od najpoznatijih je popularna 192.168.1.1 s kojom možete pristupiti vašem kućnom routeru. Adresa ima svrhu usmjeravanja paketa kroz mrežu, odnosno svaki čvor u mreži ima neku svoju adresu i da bi se znalo gdje se treba paket podataka dostaviti potrebno je znati upravo tu IP adresu odredišta. Također, potrebno je znati i adresu izvorišta da bi se, ukoliko bi došlo do neuspješne dostave paketa, moglo dojaviti izvoru. Upravo taj zadatak radi TCP protokol. TCP (Transmission Control Protocol) je vrsta protokola koja se koristi u mrežama, a zadatak mu je veliki paket razbiti u manje dijelove (jer nije baš prikladno paket od nekoliko Giga bytea poslati od jednom), svaki paket numerirati, svakom paketu dodijeliti odredišnu adresu i na kraju, na odredištu, vratiti nazad kako je sve bilo, a ukoliko dođe do gubitka paketa, javiti izvoru da ponovno pošalje taj paket. Ovaj način slanja paketa se zove slanje paketa s potvrdom ili pouzdano slanje paketa. Postoji i druga metoda gdje se samo paket dijeli na manje dijelove i šalje se kroz mrežu, bez da se provjerava da li je paket stigao. Taj protokol koji to izvodi zove se UDP (User Datagram Protocol).

 
Što se tiče MAC adresi (Media Access Control), ona se sastoji od 6 brojeva odvojenih dvotočkom i najčešće su zapisani u heksadekadskom zapisu. Onda točno definira uređaj (hadrware) s kojim se želi napraviti komunikacija, pošto na jednoj IP adresi može biti više uređaja potrebno je znati kojem uređaju proslijediti primljeni podatak. Prva tri broja označavaju proizvođača, dok druga tri broja sami uređaj.

 
Sada kada znamo kako primati, usmjeravati i slati pakete, pozabavit' ćemo se kako to sve iskoristiti da bi otvorili Web stranicu. Da bi smo prvo otvorili Web stranicu, potrebno je napraviti zahtjev za datotekom (koja je u suštini naša Web stranica), a to se izvodi pomoću HTTP (Hyper Text Transfer Protocol) protokola. On je sačinjen od zahtjeva i odgovora na zahtjev, pa tako kada se spojimo na određenu Web adresu i želimo pristupiti Web stranici, radimo zahtjev GET nakon čega ide poveznica što točno želimo (ili ako samo želimo početnu stranicu te adrese napišemo /, te na kraju ide verzija HTTP-a (HTTP 1.0 ili HTTP 1.1). Ako je to server primio on nam odgovara s 200 OK što znači da je naš zahtjev primio i ako je ispravan, on nam šalje ono što smo tražili. Ako pak to ne postoji javlja nam popularnu grešku 404 Not found.

 

 
Sada kada smo primili podatke (Web stranicu u našem primjeru) potrebno je znati kako je ona sastavljena i u kojem jeziku je pisana. Za Web stranice, najčešći korišteni jezik je HTML (HyperText Markup Language) što je ustvari više neka vrsta opisnog jezika nego što je to tipični programski jezik poput C-a. HTML kod uvijek počinje s <html>, a završava </html> i između toga se piše sam HTML kod. Ponekad sam HTML nije dovoljan da bi se napravila neka interaktivna Web stranica, stoga se koristi kombinacija HTML-a s JavaScriptom i CSSom ili pak PHP). Mi ćemo se ovdje orijentirati na HTML, te ćemo u jednom primjeru pokazati kako koristiti CSS s HTML-om da se napravi nešto kompleksnija stranica s jednostavnim grafičkim prikazom.

Kako povezati

Povezivanje Croduino-a i Ethernet Shielda je jednostavno, no ipak treba obratiti pažnju na neke stvari. Iako su pinovi 10, 11, 12 i 13 na Croduino pinovi za SPI komunikaciju, na ovom Shieldu nisu, već je SPI komunikacija izvedena preko ICSP headera na Shieldu. Pinovi na Shieldu za SPI su 5V tolerantni, što znači da se Croduino i Shield spajanju bez level konvertera.

 

 
Za drugi primjer koda potrebne su LED-ice, a za treći i zadnji DHT11, odnosno DHT22 senzor, ovisno o tome što trenutno imate, samo treba imati na umu da ako ćete koristiti DHT22, to treba postaviti i u programskom kodu.

Arduino kod

U ovom dijelu tutorijala, pokazat' ćemo neke primjere koda kako da modul dohvati neku Web stranicu (HTML datoteku Web stranice), kako da modul glumi Web server pomoću kojeg možemo npr. paliti i gasiti LEDice, te kako pomoću servisa ThingSpeak možemo poslati podatke na našu stranicu kao i napraviti zahtjev za parsiranjem Web stranice (parsirarnje je postupak kojim se iz cijele Web stranice izdvaja točno određeni dio koji nas zanima, npr. neki tekst.

 
Za ove primjere nije primjere nije potrebno instalirati biblioteku za Ethernet Shield jer je ona već instalirana zajedno s Arduino IDE-om, već je samo potrebno provjeriti da li je instalirana najnovija verzija biblioteke, tako što se iz gornjeg izbornika u Arduino IDE-u odabere Sketch->Include Library->Manage Libraries, pronađete Arduino Ethernet biblioteku i vidite da li imate ponuđeno Update. Za DHT senzor ćete morati instalirati biblioteku koju možete naći ovdje. Ako ne znate kako instalirati biblioteku, pročitajte naš tutorijal.

 
Prvi primjer je kako dohvatiti Web stranicu (u ovom slučaju vremensku prognozu s stranica Državnog Hidrometeorološkog Zavoda - DHMZ). Treba imati na umu da će biti prikazana HTML datoteka zadane Web stranice.

#include "SPI.h" //Prilozi biblioteku za SPI komunikaciju (pomocu koje komuniciraju W5100 Ethernet i Croduino)
#include "Ethernet.h" //Prilozi biblioteku za upravljanje s W5100 Ethernet Shielda koja sadrzi sve bitne funkcije vezane za otvaranje WEb stranice, spajanje na internet, slanje zahtjeva, itd.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //MAC Adresa Ethernet Shielda (poneki Shieldovi imaju naljepnicu s ispisanom MAC adresom, tu adresu napisati umjesto ove.
IPAddress ip(192, 168, 0, 177); //Postavi staticnu IP adresu ukoliko DHCP ne uspije
IPAddress myDns(192, 168, 0, 1);
EthernetClient client; //Inicijalizacija biblioteke koja izvršava sve funkcije vezane za spajanje na Web stranicu, Internet, slanje i primanje podataka, itd.
void setup() {
Serial.begin(115200); //Inicijalizacija serijske komunikacije izmedju Croduina i racunala (115200 Bauda).
Ethernet.init(10); //Definiranje CS (Chip Select) pina našeg W5100 Etherneta na Croduinu. U našem slucaju to je pin 10.
Serial.println(F("Inicijalizacija Etherneta pomocu DHCPa..."));
if (Ethernet.begin(mac) == 0) {
Serial.println(F("Neuspjesno podesavanje Etherneta pomocu DHCPa."));
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("W5100 Ethernet nije pronadjen. Provjeri da li je W5100 Ethernet dobro spojen."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako nije pronadjen W5100 Ethernet.
} while (true);
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet kabel nije prikljucen! Spoji Ethernet kabel na W5100 Ehternet i restartiraj ga."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako Ethernet nije spojen s nicime.
} while (true);
}
Ethernet.begin(mac, ip, myDns); //Ako je sve prošlo ok, no nije moguce dodijeliti DHCP, radi s statickom IP adresom.
} else {
Serial.print(F("Uspjesno dodjeljena dinamicka IP adresa pomocu DHCPa: ")); //Ako je moguce, dodijeli dinamicku IP adresu preko DHCPa i ispisi ju.
Serial.println(Ethernet.localIP());
}
delay(1000); //Pricekaj malo da se Ethernet inicijalizira na novu IP adresu.
//Pokusajmo otvoriti neku Web stranicu, na primjer vremensku prognozu s www.meteo.hr
Serial.println(F("Pokusaj spajanja na www.meteo.hr ..."));
if (client.connect("www.meteo.hr", 80)) { //Pokusajmo se spojiti na meteo.hr, posto zelimo Web stranicu (koja je http), u tom slucaju trazimo port 80 (moze biti i 88, 8080 ili 8008)
client.println(F("GET /index.php?tab=prognoza&it=sutra HTTP/1.1")); //Posto zelimo otvoriti WEB stranicu, napravit cemo GET zahtjev da ju dohvatimo i zelimo da verzija HTTPa bude 1.1
client.println(F("Host: www.meteo.hr")); //Potrebno je reci tko je posluzitelj
client.println(F("Connection: close")); //I nakon sto nam posluzitelj posalje Web stranicu, prekini vezu.
client.println();
} else {
Serial.println(F("Neuspjesno spajanje na www.meteo.hr :(")); //Ukoliko se nismo mogli spojiti na zeljenu web stranicu, obavijesti korisnika.
}
while(client.connected()) { //Sve dok je posluzitelj (odnosno server na kojoj se nalazi Web stranica) spojen s nama, spremaj i ispisuj sto nam on salje
while(client.available()) { //Sve dok ima podataka, spremi ih u privremeni spremnik
uint8_t buf[100]; //Posto Croduino ima malu RAM memoriju, ne mozemo sve podatke koje nam server salje (u ovom slucaju HTML stranica) spremiti od jednom, nego moramo dio po dio
int n = client.available(); //Pregledavamo koliko je znakova/podataka jos ostalo da primimo
if(n>100) n = 100; //Ukoliko je to vise od velicine naseg spremnika, ogranici na ono koliko je nas spremnik velik (u ovom slucaju 100 znakova)
client.read(buf, 100); //Spremi podatke/znakove u nas spremnik
Serial.write(buf, 100); //Ispisi to na Serial Monitoru
}
}
client.stop(); //Nakon sto se sve primljeno, raskini vezu s serverom / posluziteljom Web stranice
}
void loop() {
// put your main code here, to run repeatedly:
}

Drugi primjer nam pokazuje kako se Croduino pomoću Ethernet Shielda može koristiti kao mali Web server kojem možemo pristupati unutar lokalne mreže. Potrebno je, nakon spajanja Ethernet Sheilda na mrežu, na računalu ili mobitelu koji su spojeni na istu mrežu kao i Croduino, otvoriti Web preglednik i upisati IP adresu koja se nalazi u primjeru koda. Trebala bi se otvoriti Web stranica koja omogućava da se pale i gase LEDice koje su spojene na Croduino.

#include "SPI.h" //Prilozi biblioteku za SPI komunikaciju (pomocu koje komuniciraju W5100 Ethernet i Croduino)
#include "Ethernet.h" //Prilozi biblioteku za upravljanje s W5100 Ethernet Shielda koja sadrzi sve bitne funkcije vezane za otvaranje WEb stranice, spajanje na internet, slanje zahtjeva, itd.
#define LED_C 3 //Pin na Croduinu gdje ce biti spojena crvena LEDica
#define LED_Z 5 //Pin na Croduinu gdje ce biti spojena zelena LEDica
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //MAC Adresa Ethernet Shielda (poneki Shieldovi imaju naljepnicu s ispisanom MAC adresom, tu adresu napisati umjesto ove.
IPAddress ip(192, 168, 1, 10); //IP adresa naseg Croduino Web servera
EthernetServer server(80); //Inicijalizacija biblioteke koja izvršava sve funkcije vezane uz Web server (primanje zahtjeva, obrada zahtjeva i slanje podataka)
//80 unutar zagrada oznacava port nase web stranice (web stranice, odnosno HTTP uvijek ima port 80)
void setup() {
pinMode(LED_C, OUTPUT);
pinMode(LED_Z, OUTPUT);
Serial.begin(115200); //Inicijalizacija serijske komunikacije izmedju Croduina i racunala (115200 Bauda).
Ethernet.init(10); //Definiranje CS (Chip Select) pina našeg W5100 Etherneta na Croduinu. U našem slucaju to je pin 10.
Ethernet.begin(mac, ip); //Inicijaliziraj biblioteku i Ethernet s zadanom MAC adresom i IP adresom
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("W5100 Ethernet nije pronadjen. Provjeri da li je W5100 Ethernet dobro spojen."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako nije pronadjen W5100 Ethernet.
} while (true);
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet kabel nije prikljucen! Spoji Ethernet kabel na W5100 Ehternet i restartiraj ga."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako Ethernet nije spojen s nicime.
} while (true);
}
server.begin(); //Neka server zapocne s radom
Serial.print(F("Server je aktivan na IP adresi ")); //Ispisi preko koje IP adrese mozemo pristupiti nasem serveru
Serial.print(Ethernet.localIP());
Serial.println(F(". Upisi tu adresu u svoj preglednik za otvaranje Web servera."));
Serial.println(F("NAPOMENA! Uredjaj s kojim se pristupa Web serveru i sam Croduino Web server moraju biti spojeni na istu mrezu kako bi mogli pristupati jedan drugome!"));
}
void loop() {
EthernetClient client = server.available(); //Provjeravamo stanje servera, da li imamo nekoga tko nam se spojio na njega
if (client) { //Ako imamo, obavijesti nas preko Serial Monitora
Serial.println(F("Novi korisnik je spojen na server!"));
char req[100]; //String u kojeg cemo spremati korisnikov zahtjev (tocnije dio zahtjeva, jer nas samo zanima koji URL zeli ocitati da bi mogli paliti ili gasiti LEDice ovisno o tome sto je poslano)
char led1[7]; //String u koji spremamo stanje crvene LEDice
char led2[7]; //String u koji sprememo stanje zelene LEDice
while (client.connected()) { //Ukoliko se neki korisnik spojio na nas server, procitaj njegov zahtjev
if (client.available()) { //Sve dok je spojen citaj zahtjev i salji mu odgovor koji je u stvari nasa Web stranica napisana u HTMLu
client.read(req, 100); //Spremi korisnikov zahtjev u string (trebat' ce nam kasnije da bi zali koju LEDicu korisnik zeli upaliti ili ugasiti)
Serial.println(F("Korisnikov zahtjev")); //Ispisi nam na Serial Monitoru sto je korisnikov (klijentov) HTTP zahtjev
Serial.write(req, 100);
Serial.println();
client.println(F("HTTP/1.1 200 OK")); //Odgovori mu nazad zajedno s Web stranicom u HTMLu
client.println(F("Content-Type: text/html"));
client.println(F("Connection: close"));
client.println();
client.println(F("<!DOCTYPE HTML>"));
client.println(F("<html>"));
client.println(F("Croduino web server :)"));
client.println(F("<title>Croduino Web server</title><form action='/stanje'><fieldset><legend>Crvena LEDica</legend><input type='radio' name='led1' value='0' checked> Ugašena<br><input type='radio' name='led1' value='1'> Upaljena<br>"
"</fieldset><fieldset><legend>Zelena LEDica</legend><input type='radio' name='led2' value='0' checked> Ugašena<br><input type='radio' name='led2' value='1'> Upaljena<br></fieldset><input type='submit' value='Podesi'></form>"));
client.println(F("</html>"));
delay(1); //Pricekaj malo da koriskikov mobitel ili racunalo primi Web stranicu
client.stop(); //Prekini vezu s korisnikom / klijentom
Serial.println(F("Korisnk odspojen"));
strncpy(led1, strstr(req, "led1="), 6); //Iz ovog cijelog zahtjeva odvoji dio koji nam govori da li je LEDica upaljena ili ugasena i spremi to u string
strncpy(led2, strstr(req, "led2="), 6);
if (led1[5] == '1') { //Procitaj koji je broj poslije "led1="(6. znak po redu u stringu), ako je jedan, onda LEDica treba biti upaljena, ako je nula, LEDica mora biti ugasena
digitalWrite(LED_C, HIGH);
} else if (led1[5] == '0') {
digitalWrite(LED_C, LOW);
}
if (led2[5] == '1') { //Procitaj koji je broj poslije "led2="(6. znak po redu u stringu), ako je jedan, onda LEDica treba biti upaljena, ako je nula, LEDica mora biti ugasena
digitalWrite(LED_Z, HIGH);
} else if (led1[5] == '0') {
digitalWrite(LED_Z, LOW);
}
}
}
}
}

Slijedeći primjer je nešto kompliciraniji. Koristi DHT11 ili DHT22 senzor vlage i temperature. Mjerenja koja se naprave na senzoru, moguće je pristupiti preko Croduino Web servera (programskog koda) na način sličan prethodnome primjeru, a to je da se Croduino i Ethernet Shield spoje na lokalnu mrežu, te da se uređajem koji je također u lokalnoj mreži pristupi Croduino Web serveru preko Web preglednika na računalu ili mobitelu upisom IP adrese navedene u kodu. Valja napomenuti da ovaj kod ima dvije verzije Web stranice; ona koja koristi CSS za prikaz i ona koja koristi čisti HTML. Ona koja koristi CSS može grafički prikazati podatke putem bargrapha, a ona koja koristi čisti HTML, izmjerene vrijednosti prikazuje kao običan tekst. Stranice se same osvježavaju svakih 3 sekunde pri tome prikazivajući nove izmjerene podatke.

#include "SPI.h" //Prilozi biblioteku za SPI komunikaciju (pomocu koje komuniciraju W5100 Ethernet i Croduino)
#include "Ethernet.h" //Prilozi biblioteku za upravljanje s W5100 Ethernet Shielda koja sadrzi sve bitne funkcije vezane za otvaranje WEb stranice, spajanje na internet, slanje zahtjeva, itd.
#include "DHT.h"
#define DHTPIN 2 //Pin na Croduinu na koji ce biti spojen DHT
#define DHTTYPE DHT11 //Definiramo koji model DHT senzora koristimo (u ovom slucaju DHT11)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //MAC Adresa Ethernet Shielda (poneki Shieldovi imaju naljepnicu s ispisanom MAC adresom, tu adresu napisati umjesto ove.
IPAddress ip(192, 168, 1, 10); //IP adresa naseg Croduino Web servera
DHT dht(DHTPIN, DHTTYPE); //Inicijalizacija biblioteke sa zadanim modelom DHT senzora i pina na koji je DHT spojen s Croduinom
float t, h; //Varijable u koje spremamo iznos temperature zraka i vlage u zraku koje DHT11 senzor izmjeri
EthernetServer server(80); //Inicijalizacija biblioteke koja izvršava sve funkcije vezane uz Web server (primanje zahtjeva, obrada zahtjeva i slanje podataka)
//80 unutar zagrada oznacava port nase web stranice (web stranice, odnosno HTTP uvijek ima port 80)
void setup() {
dht.begin(); //Inicijalizacija biblioteke i pocetak rada DHT senzora
Serial.begin(115200); //Inicijalizacija serijske komunikacije izmedju Croduina i racunala (115200 Bauda).
Ethernet.init(10); //Definiranje CS (Chip Select) pina našeg W5100 Etherneta na Croduinu. U našem slucaju to je pin 10.
Ethernet.begin(mac, ip); //Inicijaliziraj biblioteku i Ethernet s zadanom MAC adresom i IP adresom
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("W5100 Ethernet nije pronadjen. Provjeri da li je W5100 Ethernet dobro spojen."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako nije pronadjen W5100 Ethernet.
} while (true);
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet kabel nije prikljucen! Spoji Ethernet kabel na W5100 Ehternet i restartiraj ga."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako Ethernet nije spojen s nicime.
} while (true);
}
server.begin(); //Neka server zapocne s radom
Serial.print(F("Server je aktivan na IP adresi ")); //Ispisi preko koje IP adrese mozemo pristupiti nasem serveru
Serial.print(Ethernet.localIP());
Serial.println(F(". Upisi tu adresu u svoj preglednik za otvaranje Web servera."));
Serial.println(F("NAPOMENA! Uredjaj s kojim se pristupa Web serveru i sam Croduino Web server moraju biti spojeni na istu mrezu kako bi mogli pristupati jedan drugome!"));
}
void loop() {
EthernetClient client = server.available(); //Provjeravamo stanje servera, da li imamo nekoga tko nam se spojio na njega
if (client) { //Ako imamo, obavijesti nas preko Serial Monitora
Serial.println(F("Novi korisnik je spojen na server!"));
char req[100]; //String u kojeg cemo spremati korisnikov zahtjev
while (client.connected()) { //Ukoliko se neki korisnik spojio na nas server, procitaj njegov zahtjev
if (client.available()) { //Sve dok je spojen citaj zahtjev i salji mu odgovor koji je u stvari nasa Web stranica napisana u HTMLu i CSSu
client.read(req, 100); //Spremi korisnikov zahtjev u string
h = dht.readHumidity(); //Ocitaj temperaturu s DHT11 senzora i spremi ju u varijablu
t = dht.readTemperature(); //Ocitaj vlagu zraka s DHT11 senzora i spremi ju u varijablu
Serial.println(F("Korisnikov zahtjev")); //Ispisi nam na Serial Monitoru sto je korisnikov (klijentov) HTTP zahtjev
Serial.write(req, 100);
Serial.println();
client.println(F("HTTP/1.1 200 OK")); //Odgovori mu nazad zajedno s Web stranicom u HTMLu
client.println(F("Content-Type: text/html"));
client.println(F("Connection: close"));
client.println();
client.println(F("<!DOCTYPE HTML>"));
client.println(F("<html>"));
client.println(F("<meta http-equiv='refresh' content='3'><title>Croduino Web server</title><\html>")); //Postavi da se web stranica osvjezava svakih 3 sekunde i da web stranica ima svoj naslov
client.println(F("Croduino web server :)"));
//Naredni dio koda je sama Web stranica koja je napravljena pomocu HTMLa i CSSa, te se sama osvjezava svakih 3 sekunde. Ukoliko je ovo vrlo komplicirano za pocetnika, neka se iskomentira cijeli ovaj kod i neka odkomentira donji
//koji je jednostavna Web stranica napisana u cistom HTMLu. Ovo je samo primjer da se moze napraviti i nesto kompliciranije, ako se koristi i CSS. :)
client.print(F("<style>.bargraph {list-style: none; padding-top: 20px; width:560px; }"
"ul.bargraph li.temp {background: #B40404; width:"));
client.print(t / 2, 0);
client.print(F("%; height: 35px; color: white; text-align: left; font-style: italic; font-weight:bolder; font-size: 14px; line-height: 35px; padding: 0px 20px; margin-bottom: 5px; }"
"ul.bargraph li.vlaga { background: #0000FF; width:"));
client.print(h, 0);
client.print(F("%; height: 35px; color: white; text-align: left; font-style: italic; font-weight:bolder; font-size: 14px; line-height: 35px; padding: 0px 20px; margin-bottom: 5px; }"
"</style> <html> DHT11 Senzor <ul class='bargraph'>Temperatura zraka: "));
client.print(t, 0);
client.print(F("°C<li class='temp'></li><br>Vlaga zraka: "));
client.print(h, 0);
client.println(F("%<li class='vlaga'></li> </ul> </html>"));
//Jednostavnija Web stranica napisana s cistim HTMLom. Ovo je potrebno odkomentirati, a prethodno izkomentirati ukoliko se zeli koristiti jednostavnija stranica. I ova ima mogucnost automatskog osvjezavanja nakon 3 sekunde.
// client.print(F("<html>"));
// client.print(F("<br>Temperatura: "));
// client.print(t, 0);
// client.print(F("°C<br>Vlaga: "));
// client.print(h, 0);
// client.println(F("%</html>"));
delay(1); //Pricekaj malo da koriskikov mobitel ili racunalo primi Web stranicu
client.stop(); //Prekini vezu s korisnikom / klijentom
Serial.println(F("Korisnk odspojen"));
}
}
}
}

Predzadnji kod bazirat' će se na servisu ThingSpeak. ThingSpeak servis je točno namijenjen za IoT (Internet on Things) da bi neke kompliciranije zadatke obavio taj servis, a zatim nama vratio samo rezultat toga. U ovom primjeru ćemo pokazati kako parsirati Web stranicu i iz nje izdvojiti samo dio teksta. U pitanju će biti vremenska prognoza za sutrašnji dan s Web stranice Hrvatskog Državnog Hidrometeorološkog Zavoda. Prvo je potrebno napraviti račun na ThingSpeaku (koji je besplatan). Zatim je potrebno iz gornjeg izbornika odabrati Apps, zatim ThingHTTP. Nakon otvaranja, kliknuti na New Thing. Otvara nam se nova stranica u kojem se stvara novi prikaz u kojem podešavamo što, kako i odakle želimo parsirati. No, krenimo od početka, točnije od imena, npr. prognoza_za_sutra, pod URL upisujemo adresu web stranice odakle želimo skinuti tekst (za ovaj primjer http://meteo.hr/index.php?tab=prognoza&it=sutra), Method mora biti podešena na GET, a HTTP Version na 1.1. Na kraju je ostalo Parse String polje. U to polje se upisuje koji točno dio stranice se želi izdvojiti. To se može izvesti na način da se u Chome pregledniku, prilikom pregledavanja željene Web stranice, na dio teksta koji se želi izdvojiti klikne desnim klikom i odabere Provjeri. Otvara se dodatni prozor koji ima označen dio koda koji nas interesira (označen plavo). Kliknuti desnim klikom na to, Copy, pa zatim Copy Xpath. Zatim to zalijepimo u Parse String (/html/body/section[3]/div[1]/div/div[3]/p za naš primjer) i kliknemo na Save ThingHTTP da bi spremili postavke. U gornjem desnom dijelu nalazi se link, koji nas dovodi do našeg izdvojenog teksta. Ukoliko ga unesemo u naš preglednik i pokušamo otvoriti, vidjet' ćemo da je od cijele Web stranice ostao samo tekst koji nas zanima i s kojim je lakše manipulirati na Croduinu. Sada slijedi kod koji ćemo ubaciti u Croduino da nam otvori Web stranicu pomoću ThingSpeaka i da sadržaj te Web stranice ispiše na Serial Monitoru.

#include <SPI.h> //Prilozi biblioteku za SPI komunikaciju (pomocu koje komuniciraju W5100 Ethernet i Croduino)
#include <Ethernet.h> //Prilozi biblioteku za upravljanje s W5100 Ethernet Shielda koja sadrzi sve bitne funkcije vezane za otvaranje WEb stranice, spajanje na internet, slanje zahtjeva, itd.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //MAC Adresa Ethernet Shielda (poneki Shieldovi imaju naljepnicu s ispisanom MAC adresom, tu adresu napisati umjesto ove.
IPAddress ip(192, 168, 0, 177); //Postavi staticnu IP adresu ukoliko DHCP ne uspije
IPAddress myDns(192, 168, 0, 1);
EthernetClient client; //Inicijalizacija biblioteke koja izvršava sve funkcije vezane za spajanje na Web stranicu, Internet, slanje i primanje podataka, itd.
void setup() {
Serial.begin(115200); //Inicijalizacija serijske komunikacije izmedju Croduina i racunala (115200 Bauda).
Ethernet.init(10); //Definiranje CS (Chip Select) pina našeg W5100 Etherneta na Croduinu. U našem slucaju to je pin 10.
Serial.println(F("Inicijalizacija Etherneta pomocu DHCPa..."));
if (Ethernet.begin(mac) == 0) {
Serial.println(F("Neuspjesno podesavanje Etherneta pomocu DHCPa."));
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("W5100 Ethernet nije pronadjen. Provjeri da li je W5100 Ethernet dobro spojen."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako nije pronadjen W5100 Ethernet.
} while (true);
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet kabel nije prikljucen! Spoji Ethernet kabel na W5100 Ehternet i restartiraj ga."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako Ethernet nije spojen s nicime.
} while (true);
}
Ethernet.begin(mac, ip, myDns); //Ako je sve prošlo ok, no nije moguce dodijeliti DHCP, radi s statickom IP adresom.
} else {
Serial.print(F("Uspjesno dodjeljena dinamicka IP adresa pomocu DHCPa: ")); //Ako je moguce, dodijeli dinamicku IP adresu preko DHCPa i ispisi ju.
Serial.println(Ethernet.localIP());
}
delay(1000); //Pricekaj malo da se Ethernet inicijalizira na novu IP adresu.
//Pokusajmo otvoriti Web stranicu pomocu ThingSpeaka
Serial.println(F("Pokusaj spajanja na api.thingspeak.com ..."));
if (client.connect("api.thingspeak.com", 80)) { //Pokusajmo se spojiti na api.thingspeak.com, posto zelimo Web stranicu (koja je http), u tom slucaju trazimo port 80 (moze biti i 88, 8080 ili 8008)
//Ovdje je potrebno zalijepiti link koji se dobije od ThingSpeaka, tocnije ThingHTTPa (API key). Inace ovaj kod NECE raditi!
client.println(F("GET https://api.thingspeak.com/apps/thinghttp/send_request?api_key=XXXXXXXXXXXXXXXX HTTP/1.1"));
client.println(F("Host: api.thingspeak.com")); //Potrebno je reci tko je posluzitelj
client.println(F("Connection: close")); //I nakon sto nam posluzitelj posalje Web stranicu, prekini vezu.
client.println();
} else {
Serial.println(F("Neuspjesno spajanje na api.thingspeak.com :(")); //Ukoliko se nismo mogli spojiti na zeljenu web stranicu, obavijesti korisnika.
}
while(client.connected()) { //Sve dok je posluzitelj (odnosno server na kojoj se nalazi Web stranica) spojen s nama, spremaj i ispisuj sto nam on salje
while(client.available()) { //Sve dok ima podataka, spremi ih u privremeni spremnik
uint8_t buf[100]; //Posto Croduino ima malu RAM memoriju, ne mozemo sve podatke koje nam server salje (u ovom slucaju HTML stranica) spremiti od jednom, nego moramo dio po dio
int n = client.available(); //Pregledavamo koliko je znakova/podataka jos ostalo da primimo
if(n>100) n = 100; //Ukoliko je to vise od velicine naseg spremnika, ogranici na ono koliko je nas spremnik velik (u ovom slucaju 100 znakova)
client.read(buf, 100); //Spremi podatke/znakove u nas spremnik
Serial.write(buf, 100); //Ispisi to na Serial Monitoru
}
}
client.stop(); //Nakon sto se sve primljeno, raskini vezu s serverom / posluziteljom Web stranice
}
void loop() {
}

I zadnji kod koji ćemo ovdje pokazati je kako pomoću ThingSpeaka postaviti neke podatke na Internet (npr. mjerenja temperature i vlage). Otvorimo ThingSpeak i iz gornjeg izbornika odaberemo Channels, pa zatim My Channels. Pošto nemamo još niti jedan, moramo ga napraviti, stoga kliknemo na New Channel. Otvara nam se nova stranica u kojoj podešavamo naš novi kanal u kojeg ćemo upisivati podatke s Croduina na Internet. Pod Name stavimo ime kanala (npr. Temperatura i vlaga zraka), zatim pod Description stavimo opis, kakva vrsta podataka se prikazuje, zašto baš ti podaci i sl. (npr. Mjerenje temperature i vlage zraka pomoću Croduino Basica, DHT11 senzora i Ethernet W5100 Shielda). U naredna polja stavljamo nazive pojedinih podataka koja mjerimo (npr. u Field 1 napišemo Temperatura, a u Field 2 Vlaga). Nakon toga, odemo na dno stranice i kliknemo Save Channel. Zatim iz izbornika trenutnog kanala odaberemo API keys. To su ključevi (kombinacije brojeva i slova pomoću kojih možemo dodati nove podatke. Ti ključevi moraju biti tajni, inače nam bilo tko može izmjenjivati podatke. Otvaranjem te stranice, sa desne strane se nalazi URL iznad kojeg piše Update a Channel Feed. Taj link nam je potreban u Arduino kodu da bi uspjeli poslati željene podatke. Ispod ovoga teksta se nalazi kod koji se postavlja na Croduino.

#include "SPI.h" //Prilozi biblioteku za SPI komunikaciju (pomocu koje komuniciraju W5100 Ethernet i Croduino)
#include "Ethernet.h" //Prilozi biblioteku za upravljanje s W5100 Ethernet Shielda koja sadrzi sve bitne funkcije vezane za otvaranje WEb stranice, spajanje na internet, slanje zahtjeva, itd.
#include "DHT.h" //Prilozi biblioteku za komunikaciju s DHT senzorom vlage i temperature
#define DHTPIN 2 //Pin na Croduinu na koji ce biti spojen DHT
#define DHTTYPE DHT11 //Definiramo koji model DHT senzora koristimo (u ovom slucaju DHT11)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //MAC Adresa Ethernet Shielda (poneki Shieldovi imaju naljepnicu s ispisanom MAC adresom, tu adresu napisati umjesto ove.
IPAddress ip(192, 168, 0, 177); //Postavi staticnu IP adresu ukoliko DHCP ne uspije
IPAddress myDns(192, 168, 0, 1);
EthernetClient client; //Inicijalizacija biblioteke koja izvršava sve funkcije vezane za spajanje na Web stranicu, Internet, slanje i primanje podataka, itd.
DHT dht(DHTPIN, DHTTYPE); //Inicijalizacija biblioteke sa zadanim modelom DHT senzora i pina na koji je DHT spojen s Croduinom
float t, h; //Varijable u koje spremamo iznos temperature zraka i vlage u zraku koje DHT11 senzor izmjeri
void setup() {
Serial.begin(115200); //Inicijalizacija serijske komunikacije izmedju Croduina i racunala (115200 Bauda).
Ethernet.init(10); //Definiranje CS (Chip Select) pina našeg W5100 Etherneta na Croduinu. U našem slucaju to je pin 10.
Serial.println(F("Inicijalizacija Etherneta pomocu DHCPa..."));
if (Ethernet.begin(mac) == 0) {
Serial.println(F("Neuspjesno podesavanje Etherneta pomocu DHCPa."));
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("W5100 Ethernet nije pronadjen. Provjeri da li je W5100 Ethernet dobro spojen."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako nije pronadjen W5100 Ethernet.
} while (true);
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet kabel nije prikljucen! Spoji Ethernet kabel na W5100 Ehternet i restartiraj ga."));
do {
//Beskonacna petlja, ne vrijedi ici dalje s programom ako Ethernet nije spojen s nicime.
} while (true);
}
Ethernet.begin(mac, ip, myDns); //Ako je sve prošlo ok, no nije moguce dodijeliti DHCP, radi s statickom IP adresom.
} else {
Serial.print(F("Uspjesno dodjeljena dinamicka IP adresa pomocu DHCPa: ")); //Ako je moguce, dodijeli dinamicku IP adresu preko DHCPa i ispisi ju.
Serial.println(Ethernet.localIP());
}
delay(1000); //Pricekaj malo da se Ethernet inicijalizira na novu IP adresu.
}
void loop() {
//Pokusajmo otvoriti Web stranicu pomocu ThingSpeaka
Serial.println(F("Pokusaj spajanja na api.thingspeak.com ..."));
if (client.connect("api.thingspeak.com", 80)) { //Pokusajmo se spojiti na api.thingspeak.com
h = dht.readHumidity(); //Ocitaj temperaturu s DHT11 senzora i spremi ju u varijablu
t = dht.readTemperature(); //Ocitaj vlagu zraka s DHT11 senzora i spremi ju u varijablu
//Ovdje je potrebno zalijepiti link koji se dobije od ThingSpeaka, tocnije ThingHTTPa (API key). Inace ovaj kod NECE raditi!
client.print(F("GET https://api.thingspeak.com/update?api_key=xxxxxxxxxxxxxxxx&field1=")); //Nakon filed1= ide vrijedost koju zelimo upisati u prvo polje naseg kanala (temperatura zraka)
client.print(t, 0);
client.print(F("&field2=")); //Zatim vrijednost koju zelimo upisati u drugo polje (u nasem slucaju vlaga zraka)
client.print(h, 0);
client.println(F("HTTP/1.1"));
client.println(F("Host: api.thingspeak.com")); //Potrebno je reci tko je posluzitelj
client.println(F("Connection: close")); //I nakon sto nam posluzitelj posalje Web stranicu, prekini vezu.
client.println();
client.stop(); //Nakon sto se sve primljeno, raskini vezu s serverom / posluziteljom Web stranice
Serial.println(F("Nova vrijednost temperature i vlage zraka je dodana na ThingSpeak!"));
} else {
Serial.println(F("Neuspjesno spajanje na api.thingspeak.com :(")); //Ukoliko se nismo mogli spojiti na zeljenu web stranicu, obavijesti korisnika.
}
delay(10000); //Pauza od 10 sekundi. Ne treba toliko često postavljati nove podatke na internet!
}
Leave a Reply