Inhalt aus Datei auf SD-Karte über Web (Ethernet) ausgeben

Hallo Leute,

ich bin hier am Verzweifeln, weil ich dem Fehler nicht auf die Schliche komme :confused:
Auch ein ähnlicher Thread hat mich mehr verwirrt als er mir geholfen hat:
http://forum.arduino.cc/index.php?topic=167211

Und zwar möchte ich über Web (also Ethernet) Daten von der SD auslesen. Das funktioniert auch, allerdings nur sporadisch. Wie man auf dem Serial-Monitor und dem Screenshot des Webbrowsers sehen kann. Beim ersten Hochfahren klappt das nie, dann muss ich SD-Karte ausstecken, wieder reinstecken dann direkt resetten. Dann klappt es mit Glück ("SD-Karte OK") ansonsten "Fehler: SD-Karte konnte nicht initialisiert werden". Und das ist ja kein Zustand, das System muss bei Fertigstellung durchgehend bereit sein.
Serial-Monitor:

Webbrowser:

Nun, ich dachte schon mein Ethernet-Shield hat einen Defekt, aber folgender Sketch läuft ohne Probleme:
Arduino SD-Karten Webserver - Ethernet und SD Karte gleichzeitig nutzen - mit dem Ethernetshield - #8 by jurs - Deutsch - Arduino Forum

Da ich ja ein MEGA verwende, dachte ich auch daran den SS Pin 53 zu verwenden.
Mittlerweile glaube ich, dass es egal ist ob ich Pin 53 (10 bei UNO) oder 4 anfasse. Spielt irgendwie keine Rolle, obwohl es in der Doku steht (siehe unten)
// digitalWrite(4, HIGH);
// digitalWrite(53, HIGH);

Auch habe ich es vergeblich mit einer solchen Switch-Funktion versucht:
http://forum.arduino.cc/index.php?topic=167211.msg1245797#msg1245797

Kurz: Ich weiß nicht weiter.
Ethernet-Shield ist nicht original aber baugleich.
Arduino IDE: 1.0.4

Vielen Dank für eure Mühe

Doku (Quelle: http://arduino.cc/de/Main/ArduinoEthernetShield):
Die Kommunikation zwischen dem Mikrocontroller und der SD Karte nutzt SPI, das sich an den Pins 11, 12 und 13 (auf den meisten Arduino Boards) oder 50, 51 und 52 (Arduino Mega), befindet. Zusätzlich muss ein anderer Pin genutzt werden um die SD Karte auszuwählen. Dafür kann der Hardware SS Pin (Pin 10 auf den meisten Boards) oder Pin 53 (beim Mega) - oder ein anderer Pin genutzt werden. Der zu erwendende Pin muss beim Aufruf von SD.begin() festgelegt werden. Achtung: Auch wenn der Hardware SS Pin nicht genutzt wird, muss er als Output festgelegt werden, da die SD Library sonst nicht funktionieren wird.

Anbei der Code bis zur Überprüfung:

/* Include the serial library for communicating with the COM port */
#include <SPI.h>
/* Include the standard Ethernet library */
#include <Ethernet.h>

#include <Time.h>

/* Include the standard SD card library */
#include <SD.h> 

/* DIO pin used to control the modules CS pin */
#define SD_CARD_CD_DIO 4

File SDFileData;

/* ******** Ethernet Card Settings ******** */
// Set this to your unique Ethernet Card Mac Address
byte mac[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };

/* ******** NTP Server Settings ******** */
/* de.pool.ntp.org NTP server 
   (Set to your time server of choice) */
//IPAddress timeServer(85, 25, 151, 30); <-- offline?
//RWTH Aachen:
IPAddress timeServer(134, 130, 4, 17);

/* Set this to the offset (in seconds) to your local time
   This example is GMT + 2 */
const long timeZoneOffset = +7200L;   

/* Syncs to NTP server every 15 seconds for testing, 
   set to 1 hour or more to be reasonable */
unsigned int ntpSyncTime = 15;

//Var für die aktuelle Laufzeit
unsigned long runtime;
//unsigned int runtime_helper;
long day_ = 86400000; // 86400000 milliseconds in a day
long hour_ = 3600000; // 3600000 milliseconds in an hour
long minute_ = 60000; // 60000 milliseconds in a minute
long second_ =  1000; // 1000 milliseconds in a second


/* ALTER THESE VARIABLES AT YOUR OWN RISK */
// local port to listen for UDP packets
unsigned int localPort = 8888;
// NTP time stamp is in the first 48 bytes of the message
const int NTP_PACKET_SIZE= 48;      
// Buffer to hold incoming and outgoing packets
byte packetBuffer[NTP_PACKET_SIZE];  
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;                    
// Keeps track of how long ago we updated the NTP server
unsigned long ntpLastUpdate = 0;    
// Check last time clock displayed (Not in Production)
time_t prevDisplay = 0;

//EthernetServer starten auf Port80
EthernetServer server(80);


//RELAY stuff
#define RELAY1 7
#define RELAY2 8


//PushButton
// this constant won't change:
const int buttonPin = 2;        // the pin that the pushbutton is attached to
const int ledPin_Rdy = 9;       // the pin that the "Board is Ready"-LED is attached to
const int ledPin_SD = 11;       // the pin that the "SD is Ready"-LED is attached to
const int FME = 3;              // Auslöser_FME
// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

int FME_State = 0;           // current state of the FME

int DHCP = 0;                // Ethernet shield and Setup

// Parse variable
boolean incoming = 0;


void setup() {
   pinMode(ledPin_SD, OUTPUT);
   //pinMode(53, OUTPUT); //Uncomment this line if using a Mega
   
   //RELAY stuff  
   //Relais als Output konfigurieren
   pinMode(RELAY1, OUTPUT);       
   pinMode(RELAY2, OUTPUT);
   digitalWrite(RELAY1,HIGH);
   digitalWrite(RELAY2,HIGH);

   //PushButton
   //initialisiere buttonPin und FME als inputs;
   pinMode(buttonPin, INPUT);
   pinMode(FME, INPUT);
   
   // initialize the LED as an output:
   pinMode(ledPin_Rdy, OUTPUT);   
   
   // initialize serial communication:
   Serial.begin(9600);
   Serial.println("Setup startet");
   
   
   //selETH();
   
   // Ethernet shield und NTP Setup
   int i = 2;
   Serial.println("DHCP Versuch 1 ...");
   DHCP = Ethernet.begin(mac);
   //3 DHCP Versuche, dann aufgeben und weiter im Programm
   while( DHCP == 0 && i < 3){
     delay(1000);
       Serial.print("DHCP Versuch ");
       Serial.print(i);
       Serial.println(" ...");
     DHCP = Ethernet.begin(mac);
     i++;
   }
   if(!DHCP){
    Serial.println("DHCP FAILED");
   //    for(;;); //Schleife unendlich
   } else {
     Serial.println("DHCP Success");
   }
   
   
   /* Initialisiere SD Karte */
   /* Die Kommunikation zwischen dem Mikrocontroller und der SD Karte nutzt SPI, 
   das sich an den Pins 11, 12 und 13 (auf den meisten Arduino Boards) oder 
   50, 51 und 52 (Arduino Mega), befindet. Zusätzlich muss ein anderer Pin genutzt 
   werden um die SD Karte auszuwählen. Dafür kann der Hardware SS Pin (Pin 10 auf den meisten Boards) 
   oder Pin 53 (beim Mega) - oder ein anderer Pin genutzt werden. Der zu verwendende Pin muss beim 
   Aufruf von SD.begin() festgelegt werden. Achtung: Auch wenn der Hardware SS Pin nicht genutzt wird, 
   muss er als Output festgelegt werden, da die SD Library sonst nicht funktionieren wird. */

//   pinMode(10, OUTPUT);
//   digitalWrite(4, HIGH);

//selSD();

   if (!SD.begin(SD_CARD_CD_DIO))
   {
      /* Bei einem Fehler erfolgt eine Ausgabe, es geht aber trotzdem weiter */
      Serial.println("Fehler: SD-Karte konnte nicht initialisiert werden");
      digitalWrite(ledPin_SD, HIGH);
      }else
        {
            Serial.println("SD-Karte OK");
        }    
}

rancor187:
Nun, ich dachte schon mein Ethernet-Shield hat einen Defekt, aber folgender Sketch läuft ohne Probleme:
Arduino SD-Karten Webserver - Ethernet und SD Karte gleichzeitig nutzen - mit dem Ethernetshield - #8 by jurs - Deutsch - Arduino Forum

Das soll mit dem von mir geposteten Test-Code häufiger mal vorkommen. :wink:

Ohne mir jetzt Deinen Code im Detail angesehen zu haben, was vielleicht sonst noch daneben sein könnte, die Initialisierung für UNO-Boards ist so korrekt, wenn Du ein Ethernet-Shield verwendest und SD-Karte und Ethernet abwechselnd im selben Sketch verwenden möchtest:

pinMode(10, OUTPUT);                       // set the SS pin as an output (necessary!)
digitalWrite(10, HIGH);                    // but turn off the W5100 chip!

Und für MEGA-Boards so:

pinMode(53, OUTPUT);                       // set the SS pin as an output (necessary!)
digitalWrite(53, HIGH);                    // but turn off the W5100 chip!

Außerdem achtest Du am besten darauf, dass die Reihenfolge der Library-Einbindung so ist:

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>

Wenn Du durch andere "Wildwuchsprogrammierung" bei gleichzeitiger Verwendung von Ethernet- und SD-Libraries innere Kurzschlüsse in Deinem MEGA programmiert hast: Mache den Mega für 10 Minuten stromlos, nimm das Ethernet-Shield ab (damit bei vorhandenem Sketch beim Einschalten nicht gleich wieder derselbe innere Kurzschluss auftritt, lade dann den richtigen Sketch hoch (Mit UNO und Pin-10 bzw. MEGA und Pin-53 in der Initialisierung), Board wieder Stromlos machen, Ethernet-Shield wieder aufstecken und los geht's.

Viel Erfolg!

Hallo, ich habe ganz ähnliche Probleme:

Bekomme einfach SD und Ethernet nicht zusammen zu laufen.
Ich habe hier einen UNO, einen Due, zwei verschiedene Ethernetshields (orginal und sainsmart).

Ich habe alle tutorials ausprobiert, die ich gefunden habe und keines funktioniert.

Einzel geht beides, SD, Ethernet.. Zusammen nicht.

Gibt es EINE Beispielcode, der vernünftig läuft? Bin völlig am Verzweifeln.. bin schon am Aufgeben, nachdem ich schon seit ca 15h an dem Problem rumdoktor..

jcee:
Gibt es EINE Beispielcode, der vernünftig läuft? Bin völlig am Verzweifeln.. bin schon am Aufgeben, nachdem ich schon seit ca 15h an dem Problem rumdoktor..

Dass rancor187 hier einen Link zu meinem Beispiel-Sketch "Arduino SD-Karten Webserver" gepostet hat und ich diesen Link in meinem letzten Posting auch nochmal zitiert habe, hast Du aber vielleicht gesehen:
http://forum.arduino.cc/index.php?topic=167211.msg1246736#msg1246736
Das funktioniert bei Dir auch nicht nach dem Anpassen der IP-Adresse?

So wie der Code da von mir gepostet wurde, läuft er auf einem UNO mit Ethernet-Shield und dem darauf enthaltenen SD-Kartenschacht (SD-Karte mit FAT-Formatierung!). Für einen MEGA ist eine kleine Änderung im Setup notwendig. Für einen Due - keine Ahnung.

Danke @jurs, ich schaue mir das nach dem Urlaub mal an.

Jesus Christ ....
endlich habe ich den Fehler gefunden. Darauf wäre ich ja nie gekommen.

Also ich kann die SD-Karte nur nicht verwenden weil ich die IP über DHCP bekomme. Denn wenn ich den Code ändere, von

Ethernet.begin(mac);

in

Ethernet.begin(mac, ip);

dann kann ich Ethernet + SD benutzen ansonsten nur Ethernet ... verrückt o_O

Wenn ich aber nun eine Gateway-IP eintragen möchte, habe ich wieder den gleichen Fehler:

Ethernet.begin(mac, ip, dnsServer, gateway);

bis zum DNS-Server funtzt es aber noch.

Ethernet.begin(mac, ip, dnsServer);
  1. Kann ich mir keinen Reim darauf machen, warum das so ist.
  2. Wie kann ich die IP trotzdem per DHCP beziehen?

Danke sehr.

Ich habe den Code mal auf ein Minimum gekürzt:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#define SD_CARD_CD_DIO 4 
File SDFileData;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 55 );
EthernetServer server(80);
 
void setup()
{  
  pinMode(53, OUTPUT); //Uncomment this line if using a Mega
  Ethernet.begin(mac, ip);
  server.begin();
  
  Serial.begin(9600);
 
  if (!SD.begin(SD_CARD_CD_DIO)) 
  {    
    Serial.println("ERROR: SD card failed to initialise");
    while(1);
  }else
  {
    Serial.println("SD Card OK");
  } 
}

rancor187:

  1. Kann ich mir keinen Reim darauf machen, warum das so ist.

Anyway!

rancor187:
2. Wie kann ich die IP trotzdem per DHCP beziehen?

Wenn die SD-Karteninitialisierung abhängig von der vorherigen Ethernet-Initialisierung mit/ohne DHCP mal funktioniert und mal nicht funktioniert, wäre mein Ansatz: Immer erst die SD-Karteninitialisierung machen. Und danach die Ethernet-Initialisierung.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#define SD_CARD_CD_DIO 4 
File SDFileData;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 55 );
EthernetServer server(80);
 
void setup()
{  
  pinMode(53, OUTPUT); //Use 53 with MEGA and 10 with UNO
  digitalWrite(53, HIGH); //Use 53 with MEGA and 10 with UNO
  
  Serial.begin(9600);
 
  if (!SD.begin(SD_CARD_CD_DIO)) 
  {    
    Serial.println("ERROR: SD card failed to initialise");
    while(1);
  }else
  {
    Serial.println("SD Card OK");
  } 

//  Ethernet.begin(mac, ip);
  Ethernet.begin(mac);
  Serial.print("Local IP: ");
  Serial.println(Ethernet.localIP());
  server.begin();
  
}

void loop()
{
  EthernetClient client = server.available();
  if (client) {
    while (client.available() > 0) {
    char thisChar = client.read();
    Serial.write(thisChar);
    }
    client.println("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nEs funktioniert.");
    delay(1);
    client.stop();
  }
}

Und: Ruhe bewahren, wenn der Bezug der IP-Adresse per DHCP nicht in Nullzeit passiert, sondern 3 bis 4 Sekunden dauert!