Ethernet Shield - Datei von SD über Ethernet holen

Ist es möglich, bei Verwendung des Ethernet Shield eine Datei von SD übers Ethernet zu holen?
Wenn ja, wie?
Über Tipps würde ich mich freuen.
Gruß Gerd

Indirekt. Wenn du dem Arduino ein Kommando schickst, das ihm mitteilt die SD Karte zeilenweise auszulesen und zu verschicken.

Schau mal hier:

http://www.ladyada.net/learn/arduino/ethfiles.html
oder hier

Hab das mal vor einiger Zeit gemacht. Glaube, das waren die Quellen dafür.

Hallo hk007,
bin erst jetzt richtig an diesem Punkt.
Mein sketch, mit dem ich mich bisher beschäftigt habe, soll meine FB-Heizung regeln. Jeweils zum großen Teil. Die Räume und später noch einiges Andere.
Es läuft, das Messen, das Prüfen der Sensoren, das Protokollieren auf SD und Ausgabe am Terminal. Die Uhrzeit wird regelmäßig per Internet aktualisiert. Es wird regelmäßig eine neue Daten-Datei erzeugt mit Datum und lfd. Nr. Anhand von Sollwerten werden Ausgänge für die Heizkreisventile geschaltet. Dies läuft alles.
Die Hardware besteht aus einem Arduino Mega 2560 mit Ethernet Shield. Beides Ver.3. Alles wird im Keller angesiedelt sein. USB für den Zugriff auf die Daten fällt dadurch aus. Die Entnahme der SD-Karte kann nicht die Lösung sein. Also über Ethernet auf die gespeicherten Daten zugreifen, d. h. die Datendateien auslesen oder verschieben.
Der (die/das?) Sketch SDWebBrowse.iso sollte das tun. Aber erläuft bei mir nicht. Habs mit Arduino 1.0.5 und 1.5.6 probiert. Es liegt vermutlich an SDFat. Mein Sketch läuft mit SD.h. Beide können m.E. nicht miteinander.
Aber ich bekomme schon SDWebBrowse allein nicht zum laufen.
Bei 1.5.6 wird schon die Zeile Sd2Card Card; bemängelt.
Bei 1.0.5 die Zeile while (root.readDir(p) > 0) {

Nun habe ich als Neuling viele viele Fragen.
Welche Arduino Version sollte ich nehmen?
Wie kann ich SD und SDFat zusammenführen?
Wie bekomme ich das Skript zum Laufen.
Hilfe ist willkommen.
Gruß Gerd

Nachtrag:
Habe gerade gelesen, dass für Mega nur arduino-Version 1.xx verwendet werden soll. Ok. Dann trenne ich mich von 1.5.x. Schade.

So, ich versuche an das Problem heran zu kommen.
Also:
Arduino Mega,R3, Ethernet Shield, Arduino V1.0.5-r2.
Ich versuche den Sketch SDWebBrowse.ino (GitHub - adafruit/SDWebBrowse: File browsing using the Arduino Ethernet shield) vom 10.01.2012 zum Laufen zu bringen.
Ergänzt habe ich pinMode(53, OUTPUT); wegen Mega. SdFat und SdFatUtil sind vorhanden.
Folgende Fehlermeldung erscheint, und sie überfortert mich.

SDWebBrowse.ino: In function 'void ListFiles(EthernetClient, uint8_t)':
SDWebBrowse:105: error: no matching function for call to 'SdFile::readDir(dir_t&)'
C:\Program Files (x86)\Arduino\libraries\SdFat/SdBaseFile.h:325: note: candidates are: int8_t SdBaseFile::readDir(dir_t*)

Ich füge auch noch den Sketch unten ein.
Gruß Gerd

/*
 * USERS OF ARDUINO 0023 AND EARLIER: use the 'SDWebBrowse.pde' sketch...
 * 'SDWebBrowse.ino' can be ignored.
 * USERS OF ARDUINO 1.0 AND LATER: **DELETE** the 'SDWebBrowse.pde' sketch
 * and use ONLY the 'SDWebBrowse.ino' file.  By default, BOTH files will
 * load when using the Sketchbook menu, and the .pde version will cause
 * compiler errors in 1.0.  Delete the .pde, then load the sketch.
 *
 * I can't explain WHY this is necessary, but something among the various
 * libraries here appears to be wreaking inexplicable havoc with the
 * 'ARDUINO' definition, making the usual version test unusable (BOTH
 * cases evaluate as true).  FML.
 */

/*
 * This sketch uses the microSD card slot on the Arduino Ethernet shield
 * to serve up files over a very minimal browsing interface
 *
 * Some code is from Bill Greiman's SdFatLib examples, some is from the
 * Arduino Ethernet WebServer example and the rest is from Limor Fried
 * (Adafruit) so its probably under GPL
 *
 * Tutorial is at http://www.ladyada.net/learn/arduino/ethfiles.html
 * Pull requests should go to http://github.com/adafruit/SDWebBrowse
 */

#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SPI.h>

/************ ETHERNET STUFF ************/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 80 };
EthernetServer server(80);

/************ SDCARD STUFF ************/
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))

void error_P(const char* str) {
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

void setup() {
  Serial.begin(9600);
 
  PgmPrint("Free RAM: ");
  Serial.println(FreeRam());  
  
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  pinMode(53, OUTPUT);
  pinMode(10, OUTPUT);                       // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH);                    // but turn off the W5100 chip!

  if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
  
  // initialize a FAT volume
  if (!volume.init(&card)) error("vol.init failed!");

  PgmPrint("Volume is FAT");
  Serial.println(volume.fatType(),DEC);
  Serial.println();
  
  if (!root.openRoot(&volume)) error("openRoot failed");

  // list file in root with date and size
  PgmPrintln("Files found in root:");
  root.ls(LS_DATE | LS_SIZE);
  Serial.println();
  
  // Recursive list of all directories
  PgmPrintln("Files found in all dirs:");
  root.ls(LS_R);
  
  Serial.println();
  PgmPrintln("Done");
  
  // Debugging complete, we start the server!
  Ethernet.begin(mac, ip);
  server.begin();
}

void ListFiles(EthernetClient client, uint8_t flags) {
  // This code is just copied from SdFile.cpp in the SDFat library
  // and tweaked to print to the client output in html!
  dir_t p;
  
  root.rewind();
  client.println("<ul>");
  while (root.readDir(p) > 0) {
    // done if past last used entry
    if (p.name[0] == DIR_NAME_FREE) break;

    // skip deleted entry and entries for . and  ..
    if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;

    // only list subdirectories and files
    if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;

    // print any indent spaces
    client.print("<li><a href=\"");
    for (uint8_t i = 0; i < 11; i++) {
      if (p.name[i] == ' ') continue;
      if (i == 8) {
        client.print('.');
      }
      client.print((char)p.name[i]);
    }
    client.print("\">");
    
    // print file name with possible blank fill
    for (uint8_t i = 0; i < 11; i++) {
      if (p.name[i] == ' ') continue;
      if (i == 8) {
        client.print('.');
      }
      client.print((char)p.name[i]);
    }
    
    client.print("</a>");
    
    if (DIR_IS_SUBDIR(&p)) {
      client.print('/');
    }

    // print modify date/time if requested
    if (flags & LS_DATE) {
       root.printFatDate(p.lastWriteDate);
       client.print(' ');
       root.printFatTime(p.lastWriteTime);
    }
    // print size if requested
    if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
      client.print(' ');
      client.print(p.fileSize);
    }
    client.println("</li>");
  }
  client.println("</ul>");
}

// How big our line buffer should be. 100 is plenty!
#define BUFSIZ 100

void loop()
{
  char clientline[BUFSIZ];
  int index = 0;
  
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    
    // reset the input buffer
    index = 0;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        // If it isn't a new line, add the character to the buffer
        if (c != '\n' && c != '\r') {
          clientline[index] = c;
          index++;
          // are we too big for the buffer? start tossing out data
          if (index >= BUFSIZ) 
            index = BUFSIZ -1;
          
          // continue to read more data!
          continue;
        }
        
        // got a \n or \r new line, which means the string is done
        clientline[index] = 0;
        
        // Print it out for debugging
        Serial.println(clientline);
        
        // Look for substring such as a request to get the root file
        if (strstr(clientline, "GET / ") != 0) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          // print all the files, use a helper to keep it clean
          client.println("<h2>Files:</h2>");
          ListFiles(client, LS_SIZE);
        } else if (strstr(clientline, "GET /") != 0) {
          // this time no space after the /, so a sub-file!
          char *filename;
          
          filename = clientline + 5; // look after the "GET /" (5 chars)
          // a little trick, look for the " HTTP/1.1" string and 
          // turn the first character of the substring into a 0 to clear it out.
          (strstr(clientline, " HTTP"))[0] = 0;
          
          // print the file we want
          Serial.println(filename);

          if (! file.open(&root, filename, O_READ)) {
            client.println("HTTP/1.1 404 Not Found");
            client.println("Content-Type: text/html");
            client.println();
            client.println("<h2>File Not Found!</h2>");
            break;
          }
          
          Serial.println("Opened!");
                    
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/plain");
          client.println();
          
          int16_t c;
          while ((c = file.read()) > 0) {
              // uncomment the serial to debug (slow!)
              //Serial.print((char)c);
              client.print((char)c);
          }
          file.close();
        } else {
          // everything else is a 404
          client.println("HTTP/1.1 404 Not Found");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<h2>File Not Found!</h2>");
        }
        break;
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

Ändere

root.readDir(p)

in

root.readDir(&p)

oder frage dich, ob der Beispielsketch zur Library passt...

Danke, dieser Fehler weg.

oder frage dich, ob der Beispielsketch zur Library passt...

Das kann ich nicht beurteilen. Ich bin ein ziemlicher Anfänger, hangle mich von Beispiel zu Beispiel.
Nach obiger Änderung gibt es Fehler beim Kompilieren:

SdFatUtil\SdFatUtil.cpp.o: In function SdFatUtil::FreeRam()': C:\Program Files (x86)\Arduino\libraries\SdFatUtil/SdFatUtil.cpp:34: multiple definition of SdFatUtil::FreeRam()'
SdFat\SdFatUtil.cpp.o:C:\Program Files (x86)\Arduino\libraries\SdFat/SdFatUtil.cpp:34: first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
SdFatUtil\SdFatUtil.cpp.o: In function SdFatUtil::print_P(Print*, char const*)': C:\Program Files (x86)\Arduino\libraries\SdFatUtil/SdFatUtil.cpp:48: multiple definition of SdFatUtil::print_P(Print*, char const*)'
SdFat\SdFatUtil.cpp.o:C:\Program Files (x86)\Arduino\libraries\SdFat/SdFatUtil.cpp:48: first defined here
SdFatUtil\SdFatUtil.cpp.o: In function SdFatUtil::SerialPrint_P(char const*)': C:\Program Files (x86)\Arduino\libraries\SdFatUtil/SdFatUtil.cpp:66: multiple definition of SdFatUtil::SerialPrint_P(char const*)'
SdFat\SdFatUtil.cpp.o:C:\Program Files (x86)\Arduino\libraries\SdFat/SdFatUtil.cpp:66: first defined here
SdFatUtil\SdFatUtil.cpp.o: In function SdFatUtil::println_P(Print*, char const*)': C:\Program Files (x86)\Arduino\libraries\SdFatUtil/SdFatUtil.cpp:57: multiple definition of SdFatUtil::println_P(Print*, char const*)'
SdFat\SdFatUtil.cpp.o:C:\Program Files (x86)\Arduino\libraries\SdFat/SdFatUtil.cpp:57: first defined here
SdFatUtil\SdFatUtil.cpp.o: In function SdFatUtil::SerialPrintln_P(char const*)': C:\Program Files (x86)\Arduino\libraries\SdFatUtil/SdFatUtil.cpp:74: multiple definition of SdFatUtil::SerialPrintln_P(char const*)'
SdFat\SdFatUtil.cpp.o:C:\Program Files (x86)\Arduino\libraries\SdFat/SdFatUtil.cpp:74: first defined here

Ich hätte auch nichts dagegen, SdFat zu ersetzen durch SD. Aber das übersteigt meine Fähigkeiten.
Kann es sein, das meine SdFat zu neu ist?
Gruß Gerd

SD benutzt intern SdFat und hat die in einem eigenen Unterverzeichnis.
( Bei mir in C:\Program Files (x86)\Arduino\arduino-1.0.5-r2\libraries\SD\utility\ )
Du hast wahrscheinlich zusätzlich libraries\sdFat... installiert,
und in einer anderen Version als dein Beispielsketch erwartet.

  • Ich finde allerdings keine, die SdFile::readDir(dir_t& dir) kennt, wie es von deiner SDWebBrowse erwartet wurde

Statt SdFat das drumherumgelegte SD zu verwenden, erfordert vermutlich einige Änderungen des Beispielsketch.
Einfacher wäre es wohl, jeweils eine der doppelten .cpp Dateien zu entfernen.
( Und zu klären, welche der .h Dateien tatsächlich verwendet werden )

Die Standard SD library brauchst du sonst nicht ?
Ich empfehle nur ungern, irgendwas zu löschen :wink:

Danke für die Hilfe.
Ich möchte als erstes verstehen, wie SDWebBrowse funktioniert bzw. wie es was macht. Die Funktionalität möchte ich haben, nämlich über Ethernat Dateien von SD holen. Dies scheint dieser Sketch zu leisten.
Dann möchte ihn mit meiner bereits fertigen Anwendung zur Heizungsregelung zusammentun. Wie, wird sich zeigen.
Mein Sketch verwendet die SD-Lib. Wenn SDWebBrowse auch diese Lib verwenden würde hätte ich kein Problem damit.
Das sind meine Gedanken.
Gruß Gerd

Die Lib will SdFat:
http://code.google.com/p/sdfatlib/

Die Standard SD Lib ist halt ziemlich limitiert in ihrer Funktionalität und verwendet noch dazu eine sehr alte Version von SdFat

Du kannst aber problemlos beide gleichzeitig installieren

Ich könnte im Moment Welt umarmen.
Habe SdFat-Libs aus dem Libraries-Ordner entfernt und Im Scatch die SdFats durch die Standard SD.h ersetzt und nun läuft das Teil. Wahnsinn.
Danke für die richtigen Stichworte.
Gruß Gerd