Arduino als Webserver einrichten und Webpage von SD-Karte laden

Arduino + Ethernet ShieldIn diesem Beitrag möchte ich zeigen, wie man einen Arduino als Webserver einrichtet, wie man ein Webformular von der, auf dem Ethernet Shield integrierten Micro-SD-Karte lädt und wie man über dieses Webformular Pins des Arduino steuern kann.

Für dieses Beispiel benötigen Sie auf jeden Fall einen Arduino, ein Ethernet-Shield und eine Micro-SD-Karte die in den Slot auf dem Ethernet Shield geschoben wird.

 

Arduino-Sketch

void setup()

Dieses Sketch stellt beim starten oder nach einem Reset eine Ethernet-Verbindung her und startet den Server, der über die in Zeile 7 angegebene IP aufgerufen wird. Danach wird die SD-Karte initialisiert. War diese Initialisierung erfolgreich, dann wird nach der Datei index.htm gesucht, die sich im Root-Verzeichnis auf der SD-Karte befinden muss.

void loop()

In der Funktion loop werden zwei Sachen abgearbeitet. Einerseits wird beim aufrufen der Server IP eine Website angezeigt und andererseits wird ständig auf Anfragen gelauscht die über diese Webseite gesendet werden.

Eine Anfrage wird dann empfangen, wenn Sie im Webbrowser den Server aufrufen indem Sie die oben angegebene ip aufrufen und anschließend einen Port am Arduino schalten indem Sie in dem zu sehenden Webinterface einen Button anklicken um einen Verbraucher ein- bzw. auszuschalten.

Wenn Sie auf einen der Buttons klicken, wird eine Anfrage wie “/?pinD6=1″ an den Arduino gesendet. D steht in diesem Fall für Digital. Möglich wäre auch die Angabe eines A für das schalten eines analogen Pins. Die Zahl hinter diesem Buchstaben steht für die PinNr auf dem Arduino. Die 1 hinter dem = Zeichen bedeutet dass dieser Pin auf HIGH oder bei Angabe einer 0 auf LOW geschaltet wird. Die Angabe “/?pinD6=1″ schaltet also den Digitalen Pin 6 auf HIGH.

Der Arduino durchsucht nun die Anfrage und schaut nach dem Teilstring “pin”. Wenn dieser gefunden wurde. werden die einzelnen Bestandteile der Anfrage in “typ”, “pin” und “val” gespeichert. Danach wird je nach empfangenen Typ entweder ein Digitaler oder ein Analoger Ausgang auf dem Arduino geschaltet.

#if ARDUINO > 18
#include <SPI.h> // Für Arduino Version größer als 0018
#endif
#include <Ethernet.h>
#include <TextFinder.h>
#include <SD.h>

byte mac[] = { 0x5A, 0xA2, 0xDA, 0x0D, 0x56, 0x7A }; // MAC-Adresse des Ethernet-Shield
byte ip[]  = { 192, 168, 2, 102 };                   // IP zum aufrufen des Webservers
byte sdPin = 4;                                      // Pin der SD-Karte

EthernetServer server(80);                           // Server port

File webFile;

void setup()
{  
  Ethernet.begin(mac, ip); // Client starten
  server.begin();          // Server starten
  Serial.begin(9600);
  Serial.println("ARDUINO - STEUERUNG");

  Serial.println("Initialisiere SD-Karte...");
  if (!SD.begin(sdPin)) 
  {
    Serial.println(" - Initialisierung der SD-Karte fehlgeschlagen!");
    return;
  }
  Serial.println(" - SD-Karte erfolgreich initialisiert.");

  if (!SD.exists("index.htm")) 
  {
    Serial.println(" - Datei (index.htm) wurde nicht gefunden!");
    return;
  }
  Serial.println(" - Datei (index.htm) wurde gefunden.");

  Serial.println();
  Serial.println("Verbraucher schalten");
}

void loop()
{
  EthernetClient client = server.available(); // Auf Anfrage warten

  if(client)
  {
    /*****************************************
      Ausgänge über das Webformular steuern  *
    *****************************************/
    TextFinder finder(client);

    if(finder.find("GET"))
    {
      while(finder.findUntil("pin", "\n\r"))
      {
        char typ = client.read();
        int  pin = finder.getValue();
        int  val = finder.getValue();

        if(typ == 'D')
        {
          pinMode(pin, OUTPUT);
          digitalWrite(pin, val);
          Serial.print(" - D"+String(pin));
        }
        else if(typ == 'A')
        {
          analogWrite(pin, val);
          Serial.print(" - A"+String(pin));
        }
        else Serial.print(" - Falscher Typ");

        if(val==1) Serial.println(" ein"); else Serial.println(" aus");
      }
    }

    /************************
      Webformular anzeigen  *
    ************************/
    boolean current_line_is_blank = true;       // eine HTTP-Anfrage endet mit einer Leerzeile und einer neuen Zeile

    while (client.connected()) 
    {
      if (client.available())                   // Wenn Daten vom Server empfangen werden
      {
        char c = client.read();                 // empfangene Zeichen einlesen
        if (c == '\n' && current_line_is_blank) // wenn neue Zeile und Leerzeile empfangen
        { // Standard HTTP Header senden
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println();

          // Website von SD-Karte laden
          webFile = SD.open("index.htm");  // Website laden
          if (webFile)
          {
            while(webFile.available())
            {
              client.write(webFile.read()); // Website an Client schicken
            }
            webFile.close();
          }
          break;
        }
        if (c == '\n') 
        {
          current_line_is_blank = true;
        } 
        else if (c != '\r') 
        {
          current_line_is_blank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

 

ArduinoWebServerPage

test.htm

Diese Datei kopieren Sie einfach ins Root-Verzeichnis auf der SD-Karte. Die SD-Karte können Sie anschließend in den Micro-SD-Slot auf dem Ethernet-Shield stecken.

<!DOCTYPE html>
<html>
<head>
  <title>Arduino Steuerung</title>
  <style type="text/css">
    h2 { margin-bottom:5px; }
  </style>
</head>
<body>

  <h1>Heizungssteuerung</h1>

  <h2>Digital Pin3:</h2>
  <a href="/?pinD3=1" target="ifr">Ein</a>
  <a href="/?pinD3=0" target="ifr">Aus</a>
  <br>
  <br>        
  <h2>Digital Pin6:</h2>
  <a href="/?pinD6=1" target="ifr">Ein</a>
  <a href="/?pinD6=0" target="ifr">Aus</a>

  <iframe name="ifr" style="display:none;" width="0" height="0"></iframe>
</body>
</html>

Über profwebapps

Programmierer, Webdesigner, Grafiker, Mac-User, Blogger, Screencaster. profwebapps ist auch bei Google+ vertreten

8 Kommentare zu “Arduino als Webserver einrichten und Webpage von SD-Karte laden

  1. Vielen Dank für diese Erklärung.

    Die Übertragung via PHP an den Arduino verstehe ich.
    Diese Schaltung habe ich mir eben nachgebaut und das läuft.
    Aber um eine echte Heizungsanlage z.B. Umlaufpumpen bzw. alle Geräte mit 230 V zu steuern bedarf es einer echten Statusabfrage mit einem Rückkanal I/O auf der PHP-Seite, sonst wird kann es im Ernstfall richtig Gefährlich werden. Leider habe ich das auch noch nicht raus, wie man den Status via PHP abfragen kann.

    … Zum üben ist der Blog wirklich Gut !

  2. Was genau meinst Du?
    Ich denke eh, das man sicherheitsrelevante Dinge nicht direkt vom Internet aus steuern dürfen sollte. Man kann ja einen Wert über die Website an den Arduino senden der diesen prüft und gegebenenfalls schaltet. Immer mit ein paar Sicherheitsabfragen wie maxTemp, minTemp. Das müsste man eben noch im Arduino deklarieren.

  3. Moin!

    bei mir läuft es noch nicht ganz rund

    ich bekomme
    ARDUINO – STEUERUNG
    Initialisiere SD-Karte…
    – SD-Karte erfolgreich initialisiert.
    – Datei (index.htm) wurde gefunden.

    Verbraucher schalten

    Ich kann auch die Index.htm im Browser anschauen… aber nichts anderes.
    eine index2.htm oder test.htm zeigt vom Inhalt immer die index.htm an

    wenn ich deine test.htm gleich als index.htm speichere geht es… ich kann dann halt keine andere htlm datei ansehen

    Unterschiede zu deiner Hardware? ich habe einen mega2560 mit einem ethernet-shield 5.0

    Ach ja :-) und die Buttons in bunt hätte ich auch gerne

    Gruß
    Thomas

  4. Das passt schon so. Ein Arduino ist ja kein Browser, woher soll er also wissen welche Seite er aufrufen soll? Das muss natürlich erst mal programmiert werden. Die Buttons kannst du ganz einfach in der html Datei mit CSS anpassen. Auch dazu gibt es hier ein Tutorial.

  5. >woher soll er also wissen welche Seite er aufrufen soll?
    hmm “er” braucht es ja nicht wissen. Es reicht ja wenn ich es weis :o)
    durch ” webFile = SD.open(“index.htm”);” wird ja festgelegt dass die Index.htm angezeigt werden soll.
    Ich dachte dass das wie bei einem klassischen Webserver nur initial gilt und ich auch auf andere html Dateien zugreifen kann die ich zuvor auf die Karte lege…
    …so dass mit http://meineIP/wunschseite.htm auch andere Seiten als index.htm in meinem Browser aufgerufen werden können.

    gibts da auch ein Turorial? bei einem Mega mit vielen I/O und Aufruf auf einem Minibildschirm eines Smartphone wünsche ich mir etwas mehr Diversität :o)

    Gruß
    Thomas

  6. Ja da hast Du Recht, es reicht wenn Du das weißt nur dann musst damit leben dass er nur die index.htm anzeigt,

    Du kannst auf beliebig viel Dateien zugreifen wenn Du Deine SD-Karte in den Rechner steckst. Der Arduino kann es nicht weil der weiß ja nichts von den anderen Dateien wenn Du ihn nur die index.htm öffnen lässt.

    Sicher gibt’s da eine ganze Menge an Tutorials zu. Auf dieser Seite gibt’s noch keins.
    Nur als Tipp. Versuchs mal damit.


    //Webpage senden
    if ((HTTP_req.indexOf("GET / ") > -1) || (HTTP_req.indexOf("GET /index.htm") > -1))
    {
    webFile = SD.open("index.htm");
    }
    else if (HTTP_req.indexOf("GET /page2.htm") > -1)
    {
    webFile = SD.open("page2.htm");
    }

    Vielleicht schaffst es ja dass Du damit etwas mehr “Diversität” rein bekommst.

  7. Ja sicher geht das, ist ja nichts anderes wie wenn man über eine Weboberfläche eine LED oder ein Relais ansteuert.

Kommentar verfassen