Arduino termometar može biti korišten i za upravljanje digitalnim izlazima. Znači da posjetilac Arduino web stranice, pored očitavanja izmjerene temperature, može uključivati i isključivati Arduino digitalne izlaze.
Na slici ispod je primjer Arduino termometra sa termistorom u AREF spoju koji izmjerenu temperaturu prikazuje na vastitom web serveru koji omogućava i upravljanje digitalnim izlazima.

Budući da su izmjerene temperature prikazane na web serveru, to je potrebno izvršiti spajanje Arduino ploče na LAN mrežu. U primjeru iznad je to izvršeno pomoću LAN shield-a (mrežni modul sa RJ45 konektorom), ali je princip rada isti i za slučaj WiFi konekcije.
Za ostvarivanje mrežne komunikacije putem ethernet shield-a, u sketch je potrebno uključiti biblioteku Ethernet.h
Ispod je kôd sketch-a koji vrši mjerenje temperature pomoću termistora u AREF spoju prikaz mjerenih vrijednosti na vlasitom web serveru (kopirajte kompletan kôd ispod u Arduino IDE prozor i upload-ujte ga na Arduino) :
/////////////////////////////////////////////////////// Arduino web server na SD kartici sa prikazom //// slika i temperature koja se mjeri pomoću //// termistora. //// Pored toga, web server omogućava upravljanje sa //// četiri Arduino digitalna izlaza pomoću četiri //// tipke na prikazanoj web stranici. //// //// Arduino je, u LAN mrežu spojen pomoću ethernet //// shield-a. //// //// Autor: Samir Gutić, http://amicus.ba //// 27. decembar 2017. ///////////////////////////////////////////////////////
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#define REQ_BUF_SZ 60 // Veličina buffer-a za HTTP zahtjeve
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC adresa za Ethernet shieldIPAddress ip(192, 168, 1, 100); // IP adresa za Ethernet shieldEthernetServer server(80); // Kreiranje servera na portu 80File webFile; // Dokument web stranice na SD karticichar HTTP_req[REQ_BUF_SZ] = {0}; // Buffer-ovani HTTP zahtjev smješten u null terminiran stringunsigned char req_index = 0; // index u HTTP_req bufferboolean LED_state[4] = {0}; // Smiješta stanja LED diodaunsigned char c;
// Deklaracije za termometarfloat floatSuma;float floatProsjek;float floatOtpor;float floatTemperatura;
//Vrijeme refreširanja prikaza temperature#define intOdgoda 1000
//Pin za analogno očitavanje#define pinAnalogTerm A1
//Vrijednost rednog otpornika u omima#define redniOtpor 9900
//Broj očitavanja za računanje prosječne vrijednosti#define intBrCitanja 5
//Otpor na 20.6 stepeni C#define intTermistorNa25 12080
//Nominalna temperatura #define intNominalnaTemp 20.6
//Beta koeficijent termistora (obično 3000-4000)#define intBetaKoeficijent 4016.032// Kraj deklaracija za termometar
void setup(){ // Inicijalizacija digitalnih izlaza pinMode(2, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT);
// Onemogući Ethernet čip pinMode(10, OUTPUT); digitalWrite(10, HIGH);
// Za termometar //Spojiti AREF na 3.3V i koristiti za napajanje (manje smetnji nego na 5V) analogReference(EXTERNAL); // Kraj za termimetar
// Inicijalizacija SD kartice if (!SD.begin(4)) { return; // Inicijalizacija NIJE uspjela }
if (!SD.exists("index.htm")) // Traženje index.htm na SD kartici { return; // Na SD kartici nije moguće pronaci index.htm }
Ethernet.begin(mac, ip); // Inicijalizacija Ethernet uređaja server.begin(); // Početak osluškivanja konekcija klijenata}
void loop(){ // Za termometar //Očitavanje vrijednosti sa termistora floatSuma = 0; for (int i=0; i<intbrcitanja; i++)<br="">
{ floatSuma = floatSuma+analogRead(pinAnalogTerm); delay(10); }
//Računanje prosječne vrijednosti u zadnjih intBrCitanja očitavanje floatProsjek = floatSuma/intBrCitanja;
//Konverzija vrijednosti u otpor floatOtpor = redniOtpor*floatProsjek/(1023-floatProsjek);
// Steinhart-Hart metod računanja floatTemperatura = floatOtpor / intTermistorNa25; // (R/Ro) floatTemperatura = log(floatTemperatura); // ln(R/Ro) floatTemperatura = floatTemperatura/intBetaKoeficijent; // 1/B * ln(R/Ro) floatTemperatura = floatTemperatura+1.0 / (intNominalnaTemp + 273.15); // + (1/To) floatTemperatura = 1.0 / floatTemperatura; // Invertovati vrijednost floatTemperatura = floatTemperatura-273.15; // Konverzija u stepene C
// Kraj za termometar
EthernetClient client = server.available(); // Pokušaj konekcije sa klijentom
// Upravljanje pomoću tipki if (client) { // Dobijen klijent? boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // Podaci od klijenta su dostupni za čitanje c = client.read(); // Pročitaj 1 byte (znak) od klijenta
// Limitiraj veličinu sačuvanog primljenog HTTP zahtjeva // Buffer-uj prvi dio HTTP zahtjeva u HTTP_req niz (string) // Zadnji element postavi na 0 za null terminisranje stringa (REQ_BUF_SZ - 1) if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // Sačuvaj znak HTTP zahtjeva req_index++; }
// Zadnja linija zahtjeva od klijenta je prazna i završava sa \n // Odgovori klijentu samo nakon prijema zadnje linije if (c == '\n' && currentLineIsBlank) { client.println("HTTP/1.1 200 OK"); // Pošalji standardno zaglavlje http odgovora
// Ostatak zaglavlja slijedi ispod, odvisno od toga da li je web ili XML zahtjev // Za Ajax zahtjev - pošalji XML dokument if (StrContains(HTTP_req, "ajax_inputs")) { // Pošalji ostatak HTTP zaglavlja client.println("Content-Type: text/xml"); client.println("Connection: keep-alive"); client.println(); SetLEDs();
// Pošalji XML dokument koji sadrži stanja ulaza XML_response(client); }
// Za web zahtjev - pošalji index.htm else if (StrContains(HTTP_req, "GET / ") || StrContains(HTTP_req, "GET /index.htm")) { // Pošalji ostatak HTTP zaglavlja client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println();
// Pošalji web stranicu webFile = SD.open("index.htm"); // Otvori dokument web stranice if (webFile) { while(webFile.available()) { client.write(webFile.read()); // Pošalji web stranicu klijentu } webFile.close(); } }
// Resetuj buffer indeks i sve elemente buffer-a na 0 req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); break; }
// Svaka linija teksta primljena od klijenta završava sa \r\n if (c == '\n') { // Zadnji znak u primljenoj liniji teksta // Startanje nove linije pročitanim znakom currentLineIsBlank = true; } else if (c != '\r') { // Od klijenta je primljen znak teksta currentLineIsBlank = false; } } }
delay(0.5); // Daj web pregledniku vrijeme da primi podatke client.stop(); // Zatvori konekciju }}
// Provjera da li je primljeni HTTP zahtjev ukjučivanje/isključivanje digitalnih izlaza// Takođe sačuvati trenutna stanja digitalnih izlazavoid SetLEDs(void){ // LED 1 (pin 2) if (StrContains(HTTP_req, "LED1=1")) { LED_state[0] = 1; // Sačuvaj stanje digitalnog izlaza digitalWrite(2, HIGH); // Uključi digitalni izlaz } else if (StrContains(HTTP_req, "LED1=0")) { LED_state[0] = 0; // Sačuvaj stanje digitalnog izlaza digitalWrite(2, LOW); // Isključi digitalni izlaz } // LED 2 (pin 6) if (StrContains(HTTP_req, "LED2=1")) { LED_state[1] = 1; // Sačuvaj stanje digitalnog izlaza digitalWrite(6, HIGH); // Uključi digitalni izlaz } else if (StrContains(HTTP_req, "LED2=0")) { LED_state[1] = 0; // Sačuvaj stanje digitalnog izlaza digitalWrite(6, LOW); // Isključi digitalni izlaz } // LED 3 (pin 7) if (StrContains(HTTP_req, "LED3=1")) { LED_state[2] = 1; // Sačuvaj stanje digitalnog izlaza digitalWrite(7, HIGH); // Uključi digitalni izlaz } else if (StrContains(HTTP_req, "LED3=0")) { LED_state[2] = 0; // Sačuvaj stanje digitalnog izlaza digitalWrite(7, LOW); // Isključi digitalni izlaz } // LED 4 (pin 8) if (StrContains(HTTP_req, "LED4=1")) { LED_state[3] = 1; // Sačuvaj stanje digitalnog izlaza digitalWrite(8, HIGH); // Uključi digitalni izlaz } else if (StrContains(HTTP_req, "LED4=0")) { LED_state[3] = 0; // Sačuvaj stanje digitalnog izlaza digitalWrite(8, LOW); // Isključi digitalni izlaz }}
// Pošalji XML dokument sa podacima i stanjima digitalnih izlazavoid XML_response(EthernetClient cl){ float analog_val; // Sadrži vrijednosti varijabli za slanje int count; // Brojač za FOR petlje // int sw_arr[] = {3, 4, 5}; // Pinovi prekidača
cl.print(""); cl.print("");
// Slanje vlastitih varijabli na web stranicu analog_val = floatTemperatura; cl.print(""); cl.print(analog_val); cl.println("");
// Setovanje stanja digitalnih izlaza // LED1 cl.print(""); if (LED_state[0]) { cl.print("on"); } else { cl.print("off"); } cl.println("");
// LED2 cl.print(""); if (LED_state[1]) { cl.print("on"); } else { cl.print("off"); } cl.println("");
// LED3 cl.print(""); if (LED_state[2]) { cl.print("on"); } else { cl.print("off"); } cl.println("");
// LED4 cl.print(""); if (LED_state[3]) { cl.print("on"); } else { cl.print("off"); } cl.println(""); cl.print("");}
// Postavljanje svih elemenata niza na 0 (nuliranje niza)void StrClear(char *str, char length){ for (int i = 0; i < length; i++)
{ str[i] = 0; }}
// Traženje stringa sfind u stringu str// Vraća 1 ako je string pronađen a 0 ako nije pronađenchar StrContains(char *str, char *sfind){ char found = 0; char index = 0; char len;
len = strlen(str);
if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0;}
Više datalja o termistoru možete pronaći u članku Arduino termistor termometar (AREF) sa upisom na SD karticu.
Budući da sam već objašnjavao princip rada termometra sa termistorom u AREF spoju, kao i korištenju ethernet shield-a, ovdje neću govoriti o tome. Novost je korištenje opcija upravljanja digitalnim izlazima putem web stranice na Arduino web serveru.
U ovom primjeru je web server na standardnom portu 80, mada je moguće podesiti i port po želji.
Za prikaz web stranice kao na slici ispod, na root SD kartice je potrebno iskopirati sljedeći idex.htm file:

Na slici lijevo je screenshot posjete arduino web serveru sa mobitela (browser Firefox).
U web browser je potrebno upisati IP Arduino servera definisanog na početku sketch-a (u ovom primjeru 192.168.1.100) nakon čega će, ako je Arduino uspješno povezan na istu LAN mrežu na kojoj je mobitel, biti prikazan sadržaj kao na slici lijevo.
Napominjem još jednom da Arduino i mobitel/računar kojim pristupamo web serveru moraju biti u istoj LAN mreži. Ako nisu, jedini način da se pristupi Arduino web serveru je putem rutiranja između dvije mreže. U primjeru iznad je Arduino ethernet shield, UTP kablom, spojen na RJ45 port WiFi router-a dok su mobitel i računar, na isti router, konektovani preko WiFi konekcije.
Drugi način je da se Arduino web serveru omogući pristup sa interneta tako da se na router-u, koji je gateway za internet, kreira redirekt porta 80 na IP adresu koju ima Arduino ethernet shield čime će svako ko poznaje WAN IP vašeg router-a, putem interneta moći pristupiti Arduino web serveru i očitati izmjerenu temperaturu.
Pored prikaza izmjerene temperature, na slici lijevo se vide i četiri tipke za upravljanje sa četiri Arduino digitalna izlaza. Na digitalne izlaze 2, 6, 7 i 8 sam spojio LE diode (preko otpornika od 200Ω) da je moguće vidjeti kada je digitalni izlaz uključen ili isključen.
U suštini, moguće je spojiti releje ili tranzistore koji će igratu ulogu prekidača.
Pritiskom na tipku na prikazanoj web stranici, šalje se komanda Arduinu. Na osnovu primljene komande Arduino uključuje/isključuje digitalne izlaze te na web stranici prikazuje uključenu ili isključenu sijalicu (odvisno od stanja digitalnog izlaza) i na pritisnutoj tipki prikazuje tekst da je odgovarajući digitalni izlaz uključen ili isključen.
To znači, da pored mogućnosti slanja komande, postoji i mogućnost provjere stvarnog stanja digitalnog izlaza.
Ovim se već otvara široko polje upotrebe Arduino mikrokontrolera za dvosmjernu komunikaciju i izgradnju smart uređaja u kući.
Na slici iznad su prikazane i sličice uključene i isključene sijalice a na SD kartici je samo index.htm file. 
Slike su base64 enkodirane i 'ugrađene' u sam index.htm tako da ih nije potrebno posebno kopirati niti svaki puta čitati sa SD kartice. Zbog toga je prikaz web stranice dosta brži (Arduino ima ograničenu procesorsku moć).
Princip rada
Arduino kreira web server na portu 80 pomoću instrukcije server.begin();
Sa SD kartice pročita index.htm file i tu stranicu prikaže na zahtjev klijenta (PC ili mobilni browser). Prikazana web stranica, na vrhu ispisuje temperaturu koju je izmjerio Arduino kao i 4 dugmeta i 4 sličice sijalica koje su uključene ili isključene odvisno od trenutnog stanja digitalnih izlaza 2, 6, 7 i 8.
Ako želite promijeniti stanje neko od četiri pomenuta digitalna izlaza, potrebno je kliknuti na odgovarajuće dugme nakon čega će Arduino primiti komandu kao: LED1=1
Ova komanda će izvršiti uključivanje digitalnog izlaza na koji je spojena LED1 (digitalni izlaz 2). U slučaju da je poslata komanda LED1=0 Arduino bi isključio digitalni izlaz 2. Nakon toga, na prikazanoj web stranici će biti promijenjet tekst na pritisnutom dugmetu i izvršena zamjena sličice sijalice što će označiti trenutno stanje digitalnog izlaza.
Base64 enkodiranje slika
Za enkodiranje ove dvije sličice sam koristio stranicu base64-image.de U suštini, moguće je koristiti bilo koju stranicu ili program koji vrši base64 enkodiranje slika. Na slici ispod je početna stranica sa već učitanom slikom ukljuc.png
Slika ispod prikazuje screenshot rezultata enkodiranja. Moguće je izabrati jedan od dva rezultata: za korištenje u <img> tagu ili kao CSS pozadina.

U ovom primjeru sam koristio kod za <img> tagove i on izgleda kao jaaaako veliki niz slova i brojeva. Djelić tog niza izgleda kao:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAABNCAYAAADjCemwAAAAVXpUWHRSYXcgcHJvZmlsZSB09
Kako izgleda kompletna slika, i kako se koristi možete pogledati ako, u nekom tekstualnom editoru, otvorite index.htm koji je dostupan za download sa linka iznad.
Šeme spoja
Šema spoja elemenata kreirana u Fritzing programu je na slici ispod (Arduino ploča je ispod ethernet shield-a).

Električna šema spoja je na sljedećoj slici.

Potrebne komponente:
1 x Arduino UNO
1 x Breadboard (mala)
1x NTC termistor 12.08KΩ na 25ºC
1x otpornik 9900Ω
1 x Ethernet shield sa microSD modulom
1x microSD kartica (max 2GB)
4x LED
4x otpornik 200Ω
Žice za spajanje
9V napajanje











