Here is the code I have so far. It is not documented as well as I would like it, but I can do that later.
The "#define FTPWRITE" determines whether it reads or writes to the FTP server. Commented out, it reads from the FTP server and writes to the SD.
Change your network settings, and the user/password in the doFTP() routine.
Place a file named test.txt in your FTP server.
Upload and open serial monitor. Wait for ready.
Press 'r' and enter to view SD file contents.
Press 'f' and enter to transfer.
#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
// reads from server and writes to SD file
// uncomment next line to write SD file to server.
// #define FTPWRITE
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };
IPAddress ip( 192, 168, 0, 2 );
IPAddress gateway( 192, 168, 0, 1 );
IPAddress subnet( 255, 255, 255, 0 );
// FTP server ip
IPAddress server( 192, 168, 0, 3 );
EthernetClient client;
EthernetClient dclient;
char outBuf[128];
char outCount;
void setup()
{
Serial.begin(9600);
if(SD.begin(4) == 0)
{
Serial.println("SD init fail");
}
Ethernet.begin(mac, ip, gateway, gateway, subnet);
digitalWrite(10,HIGH);
delay(2000);
Serial.println("Ready. Press f or r");
}
void loop()
{
byte inChar;
inChar = Serial.read();
if(inChar == 'f')
{
if(doFTP()) Serial.println("FTP OK");
else Serial.println("FTP FAIL");
}
if(inChar == 'r')
{
readSD();
}
}
File fh;
byte doFTP()
{
#ifdef FTPWRITE
fh = SD.open("test.txt",FILE_READ);
#else
SD.remove("test.txt");
fh = SD.open("test.txt",FILE_WRITE);
#endif
if(!fh)
{
Serial.println("SD open fail");
return 0;
}
Serial.println("SD opened");
if (client.connect(server,21)) {
Serial.println("Command connected");
}
else {
Serial.println("Command connection failed");
fh.close();
return 0;
}
if(!eRcv()) return 0;
// change to your user
client.write("USER myusername\r\n");
if(!eRcv()) return 0;
// change to your password
client.write("PASS mypassword\r\n");
if(!eRcv()) return 0;
client.write("SYST\r\n");
if(!eRcv()) return 0;
client.write("PASV\r\n");
if(!eRcv()) return 0;
// new code
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("Bad PASV Answer");
client.stop();
fh.close();
return 0;
}
}
unsigned int hiPort,loPort;
hiPort = array_pasv[4] << 8;
loPort = array_pasv[5] & 255;
// end of new code
Serial.print("Data port: ");
hiPort = hiPort | loPort;
Serial.println(hiPort);
if (dclient.connect(server,hiPort)) {
Serial.println("Data connected");
}
else {
Serial.println("Data connection failed");
client.stop();
fh.close();
return 0;
}
#ifdef FTPWRITE
client.write("STOR /test.txt\r\n");
#else
client.write("RETR /test.txt\r\n");
#endif
if(!eRcv())
{
dclient.stop();
return 0;
}
#ifdef FTPWRITE
Serial.println("Writing");
// This needs improvement
while(fh.available())
{
char c = fh.read();
dclient.write(c);
}
#else
while(dclient.connected())
{
while(dclient.available())
{
char c = dclient.read();
fh.write(c);
Serial.write(c);
}
}
#endif
dclient.stop();
Serial.println("Data disconnected");
if(!eRcv()) return 0;
client.write("QUIT\r\n");
if(!eRcv()) return 0;
client.stop();
Serial.println("Command disconnected");
fh.close();
Serial.println("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.write("QUIT\r\n");
while(!client.available()) delay(1);
while(client.available())
{
thisByte = client.read();
Serial.write(thisByte);
}
client.stop();
Serial.println("Command disconnected");
fh.close();
Serial.println("SD closed");
}
void readSD()
{
fh = SD.open("test.txt",FILE_READ);
if(!fh)
{
Serial.println("SD open fail");
return;
}
while(fh.available())
{
Serial.write(fh.read());
}
fh.close();
}
If you have questions, ask. My apology in advance for any typos.
edit: This is FTP client code. I could not find a way to use passive mode with the Arduino as the server.
edit2: Code change on passive mode port retrieval, thanks to cedric2.
That saves about 2K of memory.