Arduino Shield – Ethernet W5100 – Webserver via SD kaart (dynamisch)
Dit voorbeeld laat zien hoe je pagina en plaatjes kan tonen via een webbrowser vanaf de SD Kaart, het shield functioneert dan als een webserver, in deze versie van de webserver hoeven de bestandsnamen niet “hardcoded” in de arduino verwerkt te worden!
Hardware: Arduino + Ethernet shield (W5100)
Wat heb je nodig?
1) Standaard wordt de ethernet bibliotheek al meegeleverd met de Arduino IDE.
2) SD Kaart geformatteerd FAT16/32.
Script
Ik heb hieronder het script voorbeeld van deze website een beetje aangepast, vereenvoudigd en de commentaar regels vertaald.
Wat doet het script?
Het script geeft een pagina (index.html) weer met een PNG plaatje, en een link naar een “2e pagina”, maar deze bestandsnamen staan niet meer “hardcoded” in de code, in de aanvraag wordt de aanvraag van het bestand eruit gefilterd en op de SD kaart geopend.
Ps. onderaan deze pagina zijn de bestanden te downloaden die je op de SD kaart kan zetten.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
#include <SPI.h> // Importeer de SPI bibliotheek. #include <Ethernet.h> // Importeer de ehternet bibliotheek. #include <SD.h> // Importeer de SD kaart bibliotheek. // [INSTELLINGEN] byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // Vul het MAC address van de shield in (deze mag je ook verzinnen). IPAddress ip(192, 168, 0, 177); // Kies een vast IP adres in de range van je subnet. int poort = 80; //80 is standaard HTTP. String rootBestand = "index.htm"; // [VARIABELEN] #define REQ_BUF_SZ 80 // Buffergrootte voor HTTP aanvragen. File webFile; char HTTP_req[REQ_BUF_SZ] = {0}; // gebufferde HTTP aanvraag opgeslagen als een 'null terminated' string. char req_index = 0; // index naar HTTP_req buffer. int vlag = 0; String bestand; EthernetServer server(poort); // Intialiseer de ethernet server bibliotheek met de poort om te gebruiken. void setup() { pinMode(10, OUTPUT); digitalWrite(10, HIGH); // Schakel Ethernet chip uit. Serial.begin(9600); // Start de seriele poort. // Initialiseer SD Kaart Serial.print("- Initialiseren SD kaart..."); if (!SD.begin(4)) { Serial.println("GEFAALD!"); return; } else { Serial.println("OK"); } // Controleer of het bestand index.htm bestaat. Serial.print("- Bestand index.htm aanwezig..."); if (!SD.exists("index.htm")) { Serial.println("NEE!"); return; } else { Serial.println("OK"); } Ethernet.begin(mac, ip); // Start de Ethernet connectie. server.begin(); // Start de server. Serial.print("[-- De server is actief op IP: "); Serial.print(Ethernet.localIP()); Serial.println(" --]"); } void loop() { EthernetClient client = server.available(); // Luister naar aanvraag van clienten. if (client) { // Er is een nieuwe client aanvraag. Serial.println("[-- Nieuwe client --]"); // Elke HTTP aanvraag eindigd in een lege lijn. boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // Er is client data aanwezig. char c = client.read(); // Lees 1 byte van de client data. // Buffer het eerste gedeelte van de HTTP aanvraag in de string "HTTP_req array". // Laat het laaste element in de array als 0 om de string te beeindigen met "null" (REQ_BUF_SZ - 1) if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // Bewaar de de eerste HTTP aanvraag karakters in een array (buffergrootte) req_index++; } Serial.write(c); // Print het karakter naar de seriele monitor. if ((c == '\n') && (vlag == 0)) { // lees de eerste regel in en haal de bestandsnaam eruit! int lengte = strlen(HTTP_req); // verkrijg de lengte van de 1e regel. bestand = String(HTTP_req); // Zet de Char array om in een string. bestand = bestand.substring(5, lengte - 11); // Verkrijg de bestandsnaam door te knippen, -11 = stringlengte van "GET / " & " HTTP" Serial.print("[-- Gevraagd bestand: "); Serial.print(bestand); Serial.println(" --]"); vlag = 1; // zet de vlag op 1 we hebben de bstandsnaam uit de 1e regel gehaald. } if (c == '\n' && currentLineIsBlank) { // We hebben hier een nieuwe lijn ontvangen en de volgende lijn is leeg, // het verzoek is beeindigd, we kunnen nu een reactie terugsturen. // INDEX.HTM if (strstr(HTTP_req, "GET / ") || strstr(HTTP_req, "GET /index.htm")) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connnection: close"); client.println(); webFile = SD.open(rootBestand.c_str()); // SD kaart handelingen alleen in Char array, deze string omzetten naar Char met ".c_str()" } // OVERIGE BESTANDEN else { client.println("HTTP/1.1 200 OK"); // Bestandstypen definieren. if (strstr(HTTP_req, ".htm")) {client.println("Content-Type: text/html");} if (strstr(HTTP_req, ".css")) {client.println("Content-Type: text/css");} if (strstr(HTTP_req, ".png")) {client.println("Content-Type: image/png");} if (strstr(HTTP_req, ".jpg")) {client.println("Content-Type: image/jpeg");} if (strstr(HTTP_req, ".gif")) {client.println("Content-Type: image/gif");} if (strstr(HTTP_req, ".ico")) {client.println("Content-Type: image/x-icon");} if (strstr(HTTP_req, ".3gp")) {client.println("Content-Type: video/mpeg");} if (strstr(HTTP_req, ".pdf")) {client.println("Content-Type: application/pdf");} if (strstr(HTTP_req, ".zip")) {client.println("Content-Type: application/zip");} if (strstr(HTTP_req, ".xml")) {client.println("Content-Type: application/xml");} if (strstr(HTTP_req, ".js")) {client.println("Content-Type: application/javascript");} client.println("Connnection: close"); client.println(); webFile = SD.open(bestand.c_str()); // SD kaart handelingen alleen in Char array, deze string omzetten naar Char met ".c_str()" } if (webFile) { while(webFile.available()) {client.write(webFile.read());} // Stuur de gegevens naar de client. webFile.close(); } // Reset buffer index en alle buffer elementen naar 0. req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); break; // Dit is nodig om de connectie te beeindigen. } if (c == '\n') {currentLineIsBlank = true;} // Laatste karakter ontvangen van de client, start een nieuwe lijn met volgende karakters. else if (c != '\r') {currentLineIsBlank = false;} // Je hebt een nieuw karakter ontvangen van de client. } } vlag = 0; // zet de vlag op 0 zodat de bestandnaam uit de voglende oproep gehaald wordt. delay(1); // Geef de browser wat tijd om de data te ontvangen. client.stop(); // Sluit de connectie. Serial.println("[-- Client verbroken --]"); Serial.println(""); } } // Zet elk element van str naar 0 (maak de array leeg) void StrClear(char *str, char length) { for (int i = 0; i < length; i++) {str[i] = 0;} } |
Laadtijden
De laattijd van een plaatje is aanzienlijk (11KB = 3 SEC), het is raadzaam om (kleine) PNG bestanden te laden vanaf de SD kaart
Resultaat browser:
Resultaat Seriele monitor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
- Initialiseren SD kaart...OK - Bestand index.html aanwezig...OK [-- De server is actief op IP: 192.168.0.177 --] [-- Nieuwe client --] GET /index.htm HTTP/1.1 [-- Gevraagd bestand: index.htm --] Host: 192.168.0.177 Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4 [-- Client verbroken --] [-- Nieuwe client --] GET /plaatje.png HTTP/1.1 [-- Gevraagd bestand: plaatje.png --] Host: 192.168.0.177 Connection: keep-alive Accept: image/webp,image/*,*/*;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Referer: http://192.168.0.177/index.htm Accept-Encoding: gzip, deflate, sdch Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4 [-- Client verbroken --] [-- Nieuwe client --] GET /pagina2.htm HTTP/1.1 [-- Gevraagd bestand: pagina2.htm --] Host: 192.168.0.177 Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Referer: http://192.168.0.177/index.htm Accept-Encoding: gzip, deflate, sdch Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4 [-- Client verbroken --] |
[#/arduino/arduino_ethernet_w5100_webserver_sdkaart_bestanden” ]