
Arduino Uno je známá vývojářská platforma pro ovládání a sledování zařízení, čidel atd. Spolu s přídavnou deskou pro Ethernet obsahující i slot pro SD kartu se nabízí možnost využití jako webového serveru, přes který je možné vzdáleně z jakéhokoli zařízení obsahující webový prohlížeč (tablet, mobil..) ovládat či sledovat připojené periferie.
Čistě z důvodu testování byl pro tento systém vyvinut jednoduchý program, který Arduino Uno promění ve webový server. Obsahuje jednu šablonu webové stránky uloženou na SD kartě spolu s 25 fotografiemi. Program v Arduinu funguje tak, že po připojení klienta zobrazí stránku s jednou náhodně vybranou fotografií. Po načtení (které trvá necelou minutu) začne načítat další fotku.
Konfigurace samotného Arduina je tedy:
- Arduino UNO
- Ethernet Shield
- Napájecí zdroj
- SD karta
- Připojení do Ethernetu
Parametry procesoru: 8bitový procesor Atmel ATmega328P s vnitřní flash pamětí 32kB pro program 2kB sRAM pro data. Takt procesoru 16MHz.
Přenosová rychlost, zahrnující postupné načtení dat fotografie z SD karty a odesílání přes Ethernet rozhraní, je zhruba 3KB/sec. Program v procesoru zabírá zhruba 24kB flash paměti a využívá 1,3 kB RAM paměti.
Videoukázka běhu je na tomto videu: http://youtu.be/5EPHXus89rY
Samotný program pro vývojové prostředí Arduino IDE je zde:
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#define REQ_BUF_SZ 20
// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(200, 1, 1, 210); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
File webFile; // handle to files on SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
String soubor;
word randnumber=0;
long dobabehu=0;
void setup() {
// disable Ethernet chip
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
randomSeed(analogRead(0));
if (!SD.begin(4)) {
return; // init failed
}
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
}
void loop() {
EthernetClient client = server.available(); // try to get client
if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
if (StrContains(HTTP_req, "GET / ") ||
StrContains(HTTP_req, "GET /galerie.htm")) {
client.println("Content-Type: text/html");
client.println("Connnection: close");
client.println();
webFile = SD.open("galerie.htm"); // open web page file
}else {
client.println();
randnumber = random(1,25);
String temp = "/foto/";
temp.concat(randnumber);
temp.concat(".jpg");
char filename[temp.length()+1];
temp.toCharArray(filename, sizeof(filename));
webFile = SD.open(filename); // open web page file
}
// send web page to client
if (webFile) {
while(webFile.available()) {
client.write(webFile.read());
}
webFile.close();
client.println("<p>Volna RAM");
client.println(freeRam());
client.println("bytu.<br>Minuly soubor mel cislo: ");
client.println(randnumber);
client.println(".<br>Doba behu (ms): ");
dobabehu=millis();
client.println(dobabehu);
}
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
void StrClear(char *str, char length) {
for (int i = 0; i < length; i++) {
str[i] = 0;
}
}
char 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;
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
Obsah šablony webové stránky (souboru galerie.htm) je zde:
<html><head><title>
Arduino Galerie 25 fotek (1..25 .jpg)
</title>
<meta http-equiv="refresh" content="10">
</head><body>
<h3><font color="#ff0000">Galerie 25 fotek pro Arduino</font></h3>
8 bitovy pocitac Arduino Uno s procesorem Atmel, 32kB flash, 2kB Ram na 16 MHz
<p>
Nahodny obrazek:
<p>
<img src="obrazek.jpg">
</body></html>
Soubor galerie.htm je v hlavní složce (rootu) SD karty. Samotné fotografie jsou ve složce foto a jejich jména jsou čísla od 1 do 25 doplněné příponou .jpg (např. 8.jpg). Důležité je upozornit, že knihovna, která zajišťuje načítání dat z SD karty umí pouze názvy souborů 8+3 (jako kdysi v MS-DOSu). Tedy 8 písmen jméno a 3 písmena příloha.