Arduino SD Card Web Server

Als U een gezamenlijk project wil starten of aan projecten van anderen mee wilt werken.
Berichten: 3
Geregistreerd: 11 Dec 2016, 07:58

Arduino SD Card Web Server

Berichtdoor BenVink » 11 Dec 2016, 08:38

Hallo,

Mijn naam is Ben, 49 jaar en ik kom uit de omgeving van Oss.
Sinds twee maanden ben ik nu bezig aan het stoeien met mijn Arduino Uno.
Ik moet eerlijk toegeven, ik heb echt geen kaas gegeten van electronica maar er is mij al een hoop duidelijk geworden.
Al heel wat projectjes gedaan om het 1 en ander beter te leren begrijpen en ik ben op de goede weg al zeg ik het zelf, maar ik ben er nog lang niet.
Het kost me wel slapeloze nachten hoor, als iets niet lukt dan blijft het malen en ik ga er snachts zelfs uit om een eventueel probleem op te lossen :lol:

Ik zit nu vast en mijn vraag is of er mensen mij weer op de goede weg willen zetten?

Mijn projectje is: om via een webbase pagina wat schakelaars aan en uit te zetten (KAKU)

Heel wat af Gegooled en het 1 en ander bij elkaar gezocht en volgens mij, heb ik het bijna werkend maar er zitten toch nog foutjes in. :o

Mijn vragen zijn de volgende:
- Wil er eens iemand naar het script kijken en eventueel vertellen wat er fout is?
In mijn HTML roep ik http://192.168.2.21/?schuur1on aan, maar ik krijg dan de foutmelding:
de verbinding werd geherinitialiseerd.

- Hoe krijg ik in dit script meer geheugen vrij?

- Ik heb nog een I2C EEPROM-module liggen, aansluiten is geen probleem, maar om het toepassen om het script, dat lukt me niet. Ik weet niet wat waar neer te zetten en wat verstandig is.

Mijn Script:

cpp code
#include <SPI.h>
#include <Ethernet.h>
#include <RCSwitch.h>
#include <SD.h>

// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ 20

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 2, 21 }; //ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = { 192, 168, 2, 254 }; //internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(80); //server port

File webFile;

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 readString;
RCSwitch mySwitch = RCSwitch();


void setup()
{
// disable Ethernet chip
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

Serial.begin(9600); // for debugging

// initialize SD card
Serial.println("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("ERROR - SD card initialization failed!");
return; // init failed
}
Serial.println("SUCCESS - SD card initialized.");
// check for index.htm file
if (!SD.exists("index.htm")) {
Serial.println("ERROR - Can't find index.htm file!");
return; // can't find index file
}
Serial.println("SUCCESS - Found index.htm file.");

Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients


mySwitch.enableTransmit(10); // Using Pin #10

}


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
// buffer first part of HTTP request in HTTP_req array (string)
// leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
// print HTTP request character to serial monitor
Serial.print(c);
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// open requested web page file
if (StrContains(HTTP_req, "GET / ")
|| StrContains(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("index.htm"); // open web page file
}
if (webFile) {
while(webFile.available()) {
client.write(webFile.read()); // send web page to client
}
webFile.close();
}
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
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)
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
for (int i = 0; i < length; i++) {
str[i] = 0;
}
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
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;


//controls the Arduino if you press the buttons

if (readString.indexOf("?schuur1on") >0){

mySwitch.send("000001010001010001010001");

}

if (readString.indexOf("?schuur1off") >0){

mySwitch.send("000001010001010001010100");

}
//clearing string for next read

readString="";




}




Ik hoop dat jullie tijd willen maken om een newbie verder te helpen :lol:

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Arduino SD Card Web Server

Berichtdoor Koepel » 11 Dec 2016, 11:50

Een paar dingen vallen me op.

De REQ_BUF_SZ is slechts 20 byte. Dat is maar weinig hoor. Ik weet niet of dat genoeg is.

Gebruik je een Arduino Uno ? Het geheugen van de Arduino Uno is al snel te klein als je zowel de Ethernet als de SD library gebruikt. Een Arduino Mega 2560 of een Arduino Due is beter.

Volgens sommigen kun je beter geen String object gebruiken in de eenvoudige Arduino boards zoals de Uno. Vanwege het kaboom scenario: https://learn.adafruit.com/memories-of-an-arduino/solving-memory-problems.

Pin 10 is de ChipSelect voor Ethernet, en die gebruik je ook voor rcswitch. Dat gaat niet samen. De Ethernet library gebruikt pin 10 voor communicatie met de Ethernet chip.

De StrContains() functie onderaan de sketch hoort alleen maar te kijken of dat stukje tekst in de string zit. De code om iets te versturen via rcswitch hoort daar niet.

Voor rcswitch gebruik je het String object 'readString'. Maar je doet verder niets met 'readString', het is een lege String die nooit wordt gevuld.

Ik verwijs regelmatig naar de code van SurferTim, omdat die wel werkt en een goede basis is : http://playground.arduino.cc/Code/WebServerST.

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Arduino SD Card Web Server

Berichtdoor Gij Kieken » 11 Dec 2016, 17:20

Klopt de byte
gateway[] = { 192, 168, 2, 254 }; //internet access via router
zou eerder 192.168.2.1 verwachten, maar moet wel mogelijk zijn.

Berichten: 3
Geregistreerd: 11 Dec 2016, 07:58

Re: Arduino SD Card Web Server

Berichtdoor BenVink » 11 Dec 2016, 18:50

Hallo Koepel en Gij Kieken,

Ik gebruikte inderdaad een Uno, maar ik heb nu een Cloon Mega aan gehangen, tjeetje dat scheelt een hoop geheugen :D, we kunnen weer even vooruit.
rcswitch heb ik nu op pin 11 gezet, dom he?

De gateway klopt echt ;)


Mijn project is ontstaan door:
http://randomnerdtutorials.com/arduino-webserver-with-an-arduino-ethernet-shield/
Leuk project en die had ik ook helemaal werkend met dat script en dezelfde instellingen die ik nu gebruik.
Alleen de pagina die tevoorschijn kwam, was niet veel en ik wilde daarom een andere htm maken, en ik kwam die van EngineerAtHome.com tegen.
Een mooie en overzichtelijk look.


Vandaag heb ik mijn bestand aangepast volgens de site:
http://domoticx.com/arduino-shield-ethernet-w5100-webserver-via-sd-kaart-simpel/

Ik heb er wat voutjes uit kunnen halen, ik vraag mijn eigen af waar ik nu het beste if (readString.indexO f("?schuur1on") >0){ mySwitch.send("000001010001010001010001"); neer kan zetten?

Ik heb al een hoop geprobeerd, serile monitor geeft het volgende aan:
[-- Nieuwe client --]
GET /?schuur1on HTTP/1.1
Host: 192.168.2.21
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: nl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.2.21/
Connection: keep-alive
Upgrade-Insecure-Requests: 1

[-- Client verbroken --]

Hoewel ik 1 druk op de button op de index.htm, geeft de monitor 10x bovenstaand bericht.



Ik heb mijn code veranderd aan de hand van 1 van de linken, zodat het duidelijker is wat er allemaal gebeurd

Code: Alles selecteren
#include <SPI.h>
#include <Ethernet.h>
#include <RCSwitch.h>
#include <SD.h>

// [Instellingen]
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  //Mac Adres mag je ook zelf verzinnen
byte ip[] = { 192, 168, 2, 21 };                      //In browser invullen
byte gateway[] = { 192, 168, 2, 254 };                //internet access via router
byte subnet[] = { 255, 255, 255, 0 };                 //subnet mask
   
// [VARIABELEN]
#define REQ_BUF_SZ   20  //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
EthernetServer server(80);       //Intialiseer de ethernet server bibliotheek met de poort om te gebruiken.

String readString;
RCSwitch mySwitch = RCSwitch();


void setup() {
    // disable Ethernet chip
    pinMode(10, OUTPUT); digitalWrite(10, HIGH); //Schakel Ethernet chip uit.
   
    Serial.begin(9600);   //Start de seriele poort.
   
    // Initialiseer SD Kaart
    Serial.println("Initialiseren SD kaart...");
    if (!SD.begin(4)) {
        Serial.println("FOUT - SD card initialiseren mislukt!");
        return;    // init failed
    }
    Serial.println("SUCSES - SD card gevonden.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("FOUT - index.htm bestand niet gevonden!");
        return;  // can't find index file
    }
    Serial.println("SUCSES - Index.htm bestand gevonden.");
   
    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(" --]");


  mySwitch.enableTransmit(11);  // Using Pin #11

}


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 HTTP aanvraag karakters in een array.
                    req_index++;
                }
                // Print het karakter naar de seriele monitor.
                Serial.write(c);
                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.
                 
                // Open de gevraagde pagina of bestand.
                if (StrContains(HTTP_req, "GET / ") || StrContains(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("index.htm");        // open web page file
                    }
                   
                 
                    if (webFile) {
                        while(webFile.available()) {client.write(webFile.read());} // Stuur de gegevens naar de client
                        webFile.close();
                    }
                   
 //controls the Arduino if you press the buttons

         if (readString.indexOf("?schuur1on") >0){

               mySwitch.send("000001010001010001010001");

         }

         if (readString.indexOf("?schuur1off") >0){

             mySwitch.send("000001010001010001010100");

        }                   



                   
                    // 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.
             }
               
                // Laatste karakter ontvangen van de client, start een nieuwe lijn met volgende karakters.
                if (c == '\n') {currentLineIsBlank = true;}
                else if (c != '\r') {currentLineIsBlank = false;} // Je hebt een nieuw karakter ontvangen van de client.
             }
           }
        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;
    }
}


// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
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;
   
 }

 
 //controls the Arduino if you press the buttons

//         if (readString.indexOf("?schuur1on") >0){

//               mySwitch.send("000001010001010001010001");
//
//         }
//
//         if (readString.indexOf("?schuur1off") >0){

//             mySwitch.send("000001010001010001010100");
//
//        }
//  clearing string for next read

//          readString=""; 
 
// }

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Arduino SD Card Web Server

Berichtdoor Koepel » 12 Dec 2016, 04:30

Je hebt verschillende door elkaar heen.

Het is me ook niet helemaal duidelijk wat je wilt met het HTML bestand op de SD kaart.

De sketch van http://www.randomnerdtutorials.com begrijp ik. Die creëert zelf in de sketch een HTML pagina met knoppen. De aanvraag van de browser wordt met een String object ingelezen, en dan wordt getest of dat String object de code van een knop heeft.

De sketch van http://www.engineerathome.com zit niet zo fraai in elkaar. De structuur van de sketch is onduidelijk. Het HTML bestand staat op de SD kaart, en in dat HTML bestand zit een speciaal teken, waar de sketch iets voor kan invullen. Op die manier kunnen er verschillende plaatjes of de temperatuur in de webpagina geïnjecteerd worden. De aanvraag van de browser wordt byte voor byte verwerkt, zonder buffer en zonder String object.

De sketch van http://www.domoticx.com begrijp ik ook. Daar wordt inderdaad een buffer van slechts 20 byte gebruikt. Dat gaat goed, omdat niet verder wordt gekeken naar de rest van de regel van de browser aanvraag. De buffer is een character array, en geen String object.

Jij hebt nu de regel van de browser aanvraag in een character array staan (zoals domoticx) en vervolgens wil je testen met een String object (zoals engineerathome).
Als je naar het voorbeeld van domoticx kijkt, dan zie dat de strstr() functie wordt gebruikt om te kijken naar welke knop wordt ingedrukt.

Zou je het inspringen op steeds dezelfde manier willen doen ? Dan is namelijk de structuur van de sketch veel beter te lezen. Je kunt beginnen met op Ctrl+T te drukken.

Berichten: 3
Geregistreerd: 11 Dec 2016, 07:58

Re: Arduino SD Card Web Server

Berichtdoor BenVink » 13 Dec 2016, 18:54

Hallo Koepel,

Koepel schreef: Het is me ook niet helemaal duidelijk wat je wilt met het HTML bestand op de SD kaart.


Ik heb begrepen dat als je een htm bestand op een SD-kaartje zet dat dat ten goede komt aan het geheugen van je Arduino Mega.
Het is bedoeling dat ik straks alles via het wifi netwerk kan bedienen, ik heb meerdere schakelaars liggen waar ik de verlichting kan bedienen.
Maar laat ik er maar eerst eens eentje aan de gang krijgen :D


Koepel schreef: De sketch van http://www.randomnerdtutorials.com begrijp ik. Die creëert zelf in de sketch een HTML pagina met knoppen. De aanvraag van de browser wordt met een String object ingelezen, en dan wordt getest of dat String object de code van een knop heeft.


Die sketch had ik helemaal werkend, en door het html bestand op een SD kaart te zetten hoop ik geheugen vrij te houden om later wat andere dingen toe te voegen zoals een temperatuur meter. Dus ik ben nu bezig om aan die sketch te sleutelen zodat hij de index.htm bestand kan lezen van een SD kaartje.


Koepel schreef:De sketch van http://www.engineerathome.com zit niet zo fraai in elkaar. De structuur van de sketch is onduidelijk. Het HTML bestand staat op de SD kaart, en in dat HTML bestand zit een speciaal teken, waar de sketch iets voor kan invullen. Op die manier kunnen er verschillende plaatjes of de temperatuur in de webpagina geïnjecteerd worden. De aanvraag van de browser wordt byte voor byte verwerkt, zonder buffer en zonder String object.


Die sketch gebruik ik ook niet hoor, was voor mij echt te moeilijk, maar het htm bestand wat hij gebruikt vindt ik mooi en overzichtelijk en die heb ik wel aangepast naar mijn wensen.


Koepel schreef: Jij hebt nu de regel van de browser aanvraag in een character array staan (zoals domoticx) en vervolgens wil je testen met een String object (zoals engineerathome).
Als je naar het voorbeeld van domoticx kijkt, dan zie dat de strstr() functie wordt gebruikt om te kijken naar welke knop wordt ingedrukt.


Hier zal ik zeker even verder in moeten duiken, ik heb hier te weinig ervaring mee maar ik wil zeker leren.


Koepel schreef: Zou je het inspringen op steeds dezelfde manier willen doen ? Dan is namelijk de structuur van de sketch veel beter te lezen. Je kunt beginnen met op Ctrl+T te drukken.


Dank je wel voor deze gouden tip, ik zal dit zeker gaan gebruiken, ik wil geen ergenis veroorzaken bij de ervaren mannen. :D

Is het antwoorden van mij zo een bezwaar of hebben jullie het liever anders?

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Arduino SD Card Web Server

Berichtdoor Koepel » 13 Dec 2016, 19:19

Je kunt de sketch van domoticx.com als basis nemen. Dan gaan er wel een paar dingen uit je sketch verdwijnen die daar niet gebruikt worden.

Het inspringen op steeds dezelfde manier, dat doe je in de eerste plaats voor jezelf :!:
In de tweede plaats voor dit forum, zodat wij het gemakkelijk kunnen lezen ;)

De antwoorden met de quotes is prima, het hoeft niet, maar het is wel duidelijk.

Terug naar Gezamenlijke projecten

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 5 gasten