SD-Karte auslesen via Ethernet Shield

Hallo,

ich wollte mit einem Laptop über ein Ethernet Shield auf die SD-Karte meines Arduinos zugreifen. Ist das prinzipiell möglich? Am liebsten wäre es mir, wenn ich die Daten wie auf einem USB-Stick sehen könnte.

Kennt jemand ein gutes Beispiel welches vielleicht einen Teil meines Projekts schon umgesetzt hat?

Würde gerne mit LabVIEW auf die Daten zugreifen. Nur als Info falls einer vielleicht einen komplett neuen Denkansatz hat.

Danke schon mal.

Note that because the W5100 and SD card share the SPI bus, only one can be active at a time. If you are using both peripherals in your program, this should be taken care of by the corresponding libraries. If you're not using one of the peripherals in your program, however, you'll need to explicitly deselect it. To do this with the SD card, set pin 4 as an output and write a high to it. For the W5100, set digital pin 10 as a high output.

Das habe ich bei meiner Recherche gefunden. Sicher das ich die Daten von der SD-Karte via Ethernet auslesen kann?

Das ist mir bisher noch nicht untergekommen. Lösungen waren immer über Webserver und dann Dateidown-/upload.

Und Arduino uno und mega können sich nicht ohne Verrenkungen als usb-Stick ausgeben. Weiss nicht, ob das überhaupt irgendwie geht über die Umprogrammierung des Atmel16au

ElEspanol:
Das ist mir bisher noch nicht untergekommen. Lösungen waren immer über Webserver und dann Dateidown-/upload.

Und Arduino uno und mega können sich nicht ohne Verrenkungen als usb-Stick ausgeben. Weiss nicht, ob das überhaupt irgendwie geht über die Umprogrammierung des Atmel16au

Ja wollte schon den Ethernetport zur Übertragung auswählen da ist mit 4m USB-Kabel nicht weit komme.

noiasca:
Du musst vice versa die CS-Leitung von SD vs. Ethernet umschalten.

Damit ist klar, dass es so nicht gehen kann. Was du meinst, ist einen Arduino als NAS oder SAN zu verwenden.
Es gibt ja alles mögliche, aber ich zumindest kann mir das nicht vorstellen.

Die Leute von adafruit haben da mal ein Tutorial mit einer neuen Ethernet2 Lib rausgebrach. Die haben aber noch einen neueren Ethernet Chip auf ihren Platinen WIZ5500. Weiß nicht genau wo da die unterschiede sind aber ich gucke mir die Spur erstmal an.

Mit dem Arduino Yùn hat auch noch keiner so etwas versucht zu realisieren oder?

So jetzt habe ich mir mal ein Beispiel herausgesucht welches wie ein FTP-Server funktioniert.

Ich habe meine MAC-Adresse und die IP-Adressen angepasst. Meinen Rechner habe ich aus Server eingetragen. Von meinem Rechner kann ich das Arduino anpingen.

/*
   FTP passive client for IDE v1.0.1 and w5100/w5200
   Posted October 2012 by SurferTim
   Modified 6 June 2015 by SurferTim
*/

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
// comment out next line to write to SD from FTP server
#define FTPWRITE

// this must be unique
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x25, 0x66 };

// change to your network settings
IPAddress ip( 169, 254, 155, 2 );
IPAddress gateway( 169, 254, 155, 1 );
IPAddress subnet( 255, 255, 0, 0 );

// change to your server
IPAddress server( 169, 254, 155, 167 );

EthernetClient client;
EthernetClient dclient;

char outBuf[128];
char outCount;

// change fileName to your file (8.3 format!)
char fileName[13] = "test.txt";

void setup()
{
  Serial.begin(9600);

  digitalWrite(10, HIGH);
  Serial.println("test");
  if (SD.begin(4) == 0)
  {
    Serial.println(F("SD init fail"));
  }

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  digitalWrite(10, HIGH);
  delay(2000);
  Serial.println(F("Ready. Press f or r"));
}

void loop()
{
  byte inChar;

  inChar = Serial.read();

  if (inChar == 'f')
  {
    if (doFTP()) Serial.println(F("FTP OK"));
    else Serial.println(F("FTP FAIL"));
  }

  if (inChar == 'r')
  {
    readSD();
  }

}

File fh;

byte doFTP()
{
#ifdef FTPWRITE
  fh = SD.open(fileName, FILE_READ);
#else
  SD.remove(fileName);
  fh = SD.open(fileName, FILE_WRITE);
#endif

  if (!fh)
  {
    Serial.println(F("SD open fail"));
    return 0;
  }

#ifndef FTPWRITE
  if (!fh.seek(0))
  {
    Serial.println(F("Rewind fail"));
    fh.close();
    return 0;
  }
#endif

  Serial.println(F("SD opened"));

  if (client.connect(server, 21)) {
    Serial.println(F("Command connected"));
  }
  else {
    fh.close();
    Serial.println(F("Command connection failed1"));
    return 0;
  }

  if (!eRcv()) return 0;

  client.println(F("USER myuser"));

  if (!eRcv()) return 0;

  client.println(F("PASS mypassword"));

  if (!eRcv()) return 0;

  client.println(F("SYST"));

  if (!eRcv()) return 0;

  client.println(F("Type I"));

  if (!eRcv()) return 0;

  client.println(F("PASV"));

  if (!eRcv()) return 0;

  char *tStr = strtok(outBuf, "(,");
  int array_pasv[6];
  for ( int i = 0; i < 6; i++) {
    tStr = strtok(NULL, "(,");
    array_pasv[i] = atoi(tStr);
    if (tStr == NULL)
    {
      Serial.println(F("Bad PASV Answer"));

    }
  }

  unsigned int hiPort, loPort;

  hiPort = array_pasv[4] << 8;
  loPort = array_pasv[5] & 255;

  Serial.print(F("Data port: "));
  hiPort = hiPort | loPort;
  Serial.println(hiPort);

  if (dclient.connect(server, hiPort)) {
    Serial.println(F("Data connected"));
  }
  else {
    Serial.println(F("Data connection failed2"));
    client.stop();
    fh.close();
    return 0;
  }

#ifdef FTPWRITE
  client.print(F("STOR "));
  client.println(fileName);
#else
  client.print(F("RETR "));
  client.println(fileName);
#endif

  if (!eRcv())
  {
    dclient.stop();
    return 0;
  }

#ifdef FTPWRITE
  Serial.println(F("Writing"));

  byte clientBuf[64];
  int clientCount = 0;

  while (fh.available())
  {
    clientBuf[clientCount] = fh.read();
    clientCount++;

    if (clientCount > 63)
    {
      dclient.write(clientBuf, 64);
      clientCount = 0;
    }
  }

  if (clientCount > 0) dclient.write(clientBuf, clientCount);

#else
  while (dclient.connected())
  {
    while (dclient.available())
    {
      char c = dclient.read();
      fh.write(c);
      Serial.write(c);
    }
  }
#endif

  dclient.stop();
  Serial.println(F("Data disconnected"));

  if (!eRcv()) return 0;

  client.println(F("QUIT"));

  if (!eRcv()) return 0;

  client.stop();
  Serial.println(F("Command disconnected"));

  fh.close();
  Serial.println(F("SD closed"));
  return 1;
}

byte eRcv()
{
  byte respCode;
  byte thisByte;

  while (!client.available()) delay(1);

  respCode = client.peek();

  outCount = 0;

  while (client.available())
  {
    thisByte = client.read();
    Serial.write(thisByte);

    if (outCount < 127)
    {
      outBuf[outCount] = thisByte;
      outCount++;
      outBuf[outCount] = 0;
    }
  }

  if (respCode >= '4')
  {
    efail();
    return 0;
  }

  return 1;
}


void efail()
{
  byte thisByte = 0;

  client.println(F("QUIT"));

  while (!client.available()) delay(1);

  while (client.available())
  {
    thisByte = client.read();
    Serial.write(thisByte);
  }

  client.stop();
  Serial.println(F("Command disconnected"));
  fh.close();
  Serial.println(F("SD closed"));
}

void readSD()
{
  fh = SD.open(fileName, FILE_READ);

  if (!fh)
  {
    Serial.println(F("SD open fail"));
    return;
  }

  while (fh.available())
  {
    Serial.write(fh.read());
  }

  fh.close();
}
C:\Users\XXX>ping 169.254.155.2

Ping wird ausgeführt für 169.254.155.2 mit 32 Bytes Daten:
Antwort von 169.254.155.2: Bytes=32 Zeit<1ms TTL=128
Antwort von 169.254.155.2: Bytes=32 Zeit<1ms TTL=128
Antwort von 169.254.155.2: Bytes=32 Zeit<1ms TTL=128
Antwort von 169.254.155.2: Bytes=32 Zeit<1ms TTL=128

Ping-Statistik für 169.254.155.2:
    Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0
    (0% Verlust),
Ca. Zeitangaben in Millisek.:
    Minimum = 0ms, Maximum = 0ms, Mittelwert = 0ms

In die Console habe ich erst f und dann r eingetragen. In der txt-Datei habe ich testbla reingeschrieben.

14:31:41.429 -> test
14:31:44.002 -> Ready. Press f or r
14:33:35.171 -> SD opened
14:33:36.188 -> Command connection failed
14:33:36.223 -> FTP FAIL
15:01:06.322 -> testbla

Hat jemand eine Idee ob ich noch etwas an meinem Computer einstellen soll/muss?

Da auf Deinem PC mit hoher Wahrscheinlichkeit kein FTP-Deamon läuft, kann er auch nicht FTP-Server sein. Da ist auf dem PC nichts, was an Port 21 lauscht.

Dein Beispiel passt nicht zu den Gegebenheiten. Dein Arduino muss die Rolle eines FTP-Servers spielen, wenn Du auf ihm Files ablegen und lesen willst. Die Anfragen müssen dann übers Netz von einem FTP-Client (z.B. Filezilla oder Ähnliches) kommen.

Gruß Tommy

Jo da war ja was. Jetzt habe ich das soweit fertig gemacht und es läuft... aber für große Datein recht langsam. Habe 3 MB übertragen ~1MB pro min

16:16:38.962 -> Ready. Press f or r
16:16:42.910 -> SD opened
16:16:42.910 -> Command connected
16:16:42.944 -> 220-FileZilla Server 0.9.60 beta
16:16:42.977 -> 220-written by Tim Kosse (tim.kosse@filezilla-project.org)
16:16:43.049 -> 220 Please visit https://filezilla-project.org/
16:16:43.088 -> 331 Password required for myuser
16:16:43.122 -> 230 Logged on
16:16:43.161 -> 215 UNIX emulated by FileZilla
16:16:43.161 -> 200 Type set to I
16:16:43.203 -> 227 Entering Passive Mode (169,254,155,167,236,76)
16:16:43.242 -> Data port: 60492
16:16:43.279 -> Data connected
16:16:43.279 -> 150 Opening data channel for file upload to server of "/20190428.TXT"
16:16:43.357 -> Writing
16:19:41.898 -> Data disconnected
16:19:41.898 -> 226 Successfully transferred "/20190428.TXT"
16:19:41.932 -> 221 Goodbye
16:19:41.975 -> Command disconnected
16:19:41.975 -> SD closed
16:19:42.009 -> FTP OK
FileZilla Server 0.9.60 beta
Copyright 2001-2016 by Tim Kosse (tim.kosse@filezilla-project.org)
https://filezilla-project.org/
Connecting to server localhost:14147...
Connected, waiting for authentication
Logged on
You appear to be behind a NAT router. Please configure the passive mode settings and forward a range of ports in your router.
Warning: FTP over TLS is not enabled, users cannot securely log in.
(000005)28.05.2019 16:16:42 - (not logged in) (169.254.155.2)> Connected on port 21, sending welcome message...
(000005)28.05.2019 16:16:42 - (not logged in) (169.254.155.2)> 220-FileZilla Server 0.9.60 beta
(000005)28.05.2019 16:16:42 - (not logged in) (169.254.155.2)> 220-written by Tim Kosse (tim.kosse@filezilla-project.org)
(000005)28.05.2019 16:16:42 - (not logged in) (169.254.155.2)> 220 Please visit https://filezilla-project.org/
(000005)28.05.2019 16:16:43 - (not logged in) (169.254.155.2)> USER myuser
(000005)28.05.2019 16:16:43 - (not logged in) (169.254.155.2)> 331 Password required for myuser
(000005)28.05.2019 16:16:43 - (not logged in) (169.254.155.2)> PASS **********
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> 230 Logged on
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> SYST
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> 215 UNIX emulated by FileZilla
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> Type I
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> 200 Type set to I
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> PASV
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> 227 Entering Passive Mode (169,254,155,167,236,76)
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> STOR 20190428.TXT
(000005)28.05.2019 16:16:43 - myuser (169.254.155.2)> 150 Opening data channel for file upload to server of "/20190428.TXT"
(000005)28.05.2019 16:19:41 - myuser (169.254.155.2)> 226 Successfully transferred "/20190428.TXT"
(000005)28.05.2019 16:19:41 - myuser (169.254.155.2)> QUIT
(000005)28.05.2019 16:19:41 - myuser (169.254.155.2)> 221 Goodbye
(000005)28.05.2019 16:19:41 - myuser (169.254.155.2)> disconnected.

Hast Du erwartet, ein Hochgeschwindigkeits-NAS mit dem Arduino aufbauen zu können?

Gruß Tommy

Ne dafür reicht der Controller definitiv nicht, aber ich kann meine Log-Datei noch erheblich kleiner machen dann geht es auch erheblich schneller.

Allerdings will ich komplette Strings einlesen, um verschiedene Dateien auswählen zu können. Daher wollte ich String->CharArray nutzen. An dem Code habe ich nur das einlesen und Datei öffnen angepasst. Als Eingabe mache ich test.txt.

void loop()
{
  while (Serial.available()) {
    fileName = Serial.readString();
    fileName.remove(12);
    Serial.println(fileName);
  }

  if (fileName == "test.txt")
  {
    if (doFTP()) Serial.println(F("FTP OK"));
    else Serial.println(F("FTP FAIL"));
  }

}
File fh;

byte doFTP()
{
  fileName.toCharArray(cfileName, 13);
  Serial.print("char Name: ");
  for (int i = 0; i < 14; i++)
  {
    Serial.print(cfileName[i]);
  }
  Serial.println();
  
#ifdef FTPWRITE
  fh = SD.open(cfileName, FILE_READ);
#else
  SD.remove(cfileName);
  fh = SD.open(cfileName, FILE_WRITE);
#endif

......

In der Ausgabe sehe ich dann:

....
09:26:12.666 -> SD opened
09:26:12.666 -> Command connected
09:26:12.666 -> 220-FileZilla Server 0.9.60 beta
09:26:12.711 -> 220-written by Tim Kosse (tim.kosse@filezilla-project.org)
09:26:12.797 -> 220 Please visit https://filezilla-project.org/
09:26:12.839 -> 331 Password required for myuser
09:26:12.882 -> 230 Logged on
09:26:12.882 -> 215 UNIX emulated by FileZilla
09:26:12.924 -> 200 Type set to I
09:26:12.924 -> 227 Entering Passive Mode (169,254,155,167,208,238)
09:26:13.001 -> Data port: 65179
09:26:13.951 -> Data connection failed2
09:26:13.951 -> FTP FAIL

Weiß wer ob der das so verträgt mit dem String->CharArray? Danke.

Ok jetzt geht es... manchmal hilft es alles noch mal neu zu machen.

/*
   FTP passive client for IDE v1.0.1 and w5100/w5200
   Posted October 2012 by SurferTim
   Modified 6 June 2015 by SurferTim
*/

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
// comment out next line to write to SD from FTP server
#define FTPWRITE

// this must be unique
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };  

// change to your network settings
IPAddress ip( 169, 254, 155, 2 );    
IPAddress gateway( 192, 168, 155, 1 );
IPAddress subnet( 255, 255, 255, 0 );

// change to your server
IPAddress server( 169, 254, 155, 167 );

EthernetClient client;
EthernetClient dclient;

char outBuf[128];
char outCount;

// change fileName to your file (8.3 format!)
//char fileName[13] = "test.txt";
String fileName;
void setup()
{
  Serial.begin(9600);

  digitalWrite(10,HIGH);

  if(SD.begin(4) == 0)
  {
    Serial.println(F("SD init fail"));          
  }

  Ethernet.begin(mac, ip, gateway, gateway, subnet); 
  digitalWrite(10,HIGH);
  delay(2000);
  Serial.println(F("Ready. Press f or r"));
}

void loop()
{

    while (Serial.available()) {
    fileName = Serial.readString();
    fileName.remove(8);
    Serial.println(fileName);
  }
  
//  byte inChar;
//
//  inChar = Serial.read();

  if(fileName == "test.txt")
  {
    if(doFTP()) Serial.println(F("FTP OK"));
    else Serial.println(F("FTP FAIL"));
  }

//  if(inChar == 'r')
//  {
//    readSD();    
//  }

}

File fh;

byte doFTP()
{
#ifdef FTPWRITE
  fh = SD.open(fileName,FILE_READ);
#else
  SD.remove(fileName);
  fh = SD.open(fileName,FILE_WRITE);
#endif

  if(!fh)
  {
    Serial.println(F("SD open fail"));
    return 0;    
  }

#ifndef FTPWRITE  
  if(!fh.seek(0))
  {
    Serial.println(F("Rewind fail"));
    fh.close();
    return 0;    
  }
#endif

  Serial.println(F("SD opened"));

  if (client.connect(server,21)) {
    Serial.println(F("Command connected"));
  } 
  else {
    fh.close();
    Serial.println(F("Command connection failed"));
    return 0;
  }

  if(!eRcv()) return 0;

  client.println(F("USER myuser"));

  if(!eRcv()) return 0;

  client.println(F("PASS mypassword"));

  if(!eRcv()) return 0;

  client.println(F("SYST"));

  if(!eRcv()) return 0;

  client.println(F("Type I"));

  if(!eRcv()) return 0;

  client.println(F("PASV"));

  if(!eRcv()) return 0;

  char *tStr = strtok(outBuf,"(,");
  int array_pasv[6];
  for ( int i = 0; i < 6; i++) {
    tStr = strtok(NULL,"(,");
    array_pasv[i] = atoi(tStr);
    if(tStr == NULL)
    {
      Serial.println(F("Bad PASV Answer"));    

    }
  }

  unsigned int hiPort,loPort;

  hiPort = array_pasv[4] << 8;
  loPort = array_pasv[5] & 255;

  Serial.print(F("Data port: "));
  hiPort = hiPort | loPort;
  Serial.println(hiPort);

  if (dclient.connect(server,hiPort)) {
    Serial.println(F("Data connected"));
  } 
  else {
    Serial.println(F("Data connection failed"));
    client.stop();
    fh.close();
    return 0;
  }

#ifdef FTPWRITE 
  client.print(F("STOR "));
  client.println(fileName);
#else
  client.print(F("RETR "));
  client.println(fileName);
#endif

  if(!eRcv())
  {
    dclient.stop();
    return 0;
  }

#ifdef FTPWRITE
  Serial.println(F("Writing"));

  byte clientBuf[64];
  int clientCount = 0;

  while(fh.available())
  {
    clientBuf[clientCount] = fh.read();
    clientCount++;

    if(clientCount > 63)
    {
      dclient.write(clientBuf,64);
      clientCount = 0;
    }
  }

  if(clientCount > 0) dclient.write(clientBuf,clientCount);

#else
  while(dclient.connected())
  {
    while(dclient.available())
    {
      char c = dclient.read();
      fh.write(c);      
      Serial.write(c); 
    }
  }
#endif

  dclient.stop();
  Serial.println(F("Data disconnected"));

  if(!eRcv()) return 0;

  client.println(F("QUIT"));

  if(!eRcv()) return 0;

  client.stop();
  Serial.println(F("Command disconnected"));

  fh.close();
  Serial.println(F("SD closed"));
  return 1;
}

byte eRcv()
{
  byte respCode;
  byte thisByte;

  while(!client.available()) delay(1);

  respCode = client.peek();

  outCount = 0;

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);

    if(outCount < 127)
    {
      outBuf[outCount] = thisByte;
      outCount++;      
      outBuf[outCount] = 0;
    }
  }

  if(respCode >= '4')
  {
    efail();
    return 0;  
  }

  return 1;
}


void efail()
{
  byte thisByte = 0;

  client.println(F("QUIT"));

  while(!client.available()) delay(1);

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  client.stop();
  Serial.println(F("Command disconnected"));
  fh.close();
  Serial.println(F("SD closed"));
}

void readSD()
{
  fh = SD.open(fileName,FILE_READ);

  if(!fh)
  {
    Serial.println(F("SD open fail"));
    return;    
  }

  while(fh.available())
  {
    Serial.write(fh.read());
  }

  fh.close();
}