Go Down

Topic: Arduino + official ethernet shield + SD -> all working together. (Read 14473 times) previous topic - next topic

Sergegsx


The examples I was referring to are supplied with the version 022 software.

That's why I was so surprised... I will go even further and say that many questions on the forum could be answered if everyone downloaded and set up the latest version of the software.You can stick with your old stuff if you are tied to libraries -- but maybe start writing new programs with the new compiler...

I encourage everyone not to plug in their new toy but spend two or three days (or whatever it takes) to review all the material on the forum and review this board. You don't have to read an understand all -- but when the time comes maybe you will remember that you saw something useful...



I would be interested to know which example does what this post intended to.
- be able to use in a simple manner, both ethernet part and SD part of the ethernet shield.

plus at the time of opening this post i was very limited in knowledge on some aspects that were pointed out in this thread and know i have been able to learn from it. hopefully giving back to the community a working example of my initial aim so that anyone on the same situation can benefit from it.

so...i dont see anything wrong in this thread, only very kind users helping out another Arduino enthusiast.

Sergegsx

in terms of the aim of the original post...

I am currently waiting to be able to test my code when i have my arduino and ethernet shield available again (cant use it right now).

I will try to confirm the code is working + try to clean it up + and try to make it as user friendly as possible with some functions or something.

once again, thanks to the community for their feedback, you are great !!

aboshan

Hey,

Take a look at the "TinyWebServer" examples. Google it as you need to download them, they are not part of the default example package.
Within the TinyWebServer package, is an example called "FileUpload", which does what you want.

However, the code isn't very user friendly, your approach, if it works, seems way easier.

Let us know.

Sergegsx

aboshan excellent contribution !!
i am going to try to make my version work with the new information you have me, because as you said, it looks much easier to me also

Sergegsx

im not sure if this code will work as although it compiles, i am not able to test it yet.
just in case anyone is interested. i will post a final code when i am able to test it and its working


Code: [Select]



//Libraries
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
/*
The circuit:
* analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
* Ethernet chip attached to SPI bus as follows:
** SS - pin 10 (by default)
*/
// to deselect a peripherial (SD or ethernet) put HIGH to its CS pin.

//Server IP address
byte server[] = { 173,194,33,104 }; // Google
//Setup a client
Client client(server, 80);
byte ip[] = { 192,168,1,69 };  // Using a Router
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte gateway[] = { 192, 168, 1, 1 };   //your router's IP address


    boolean SDavailable;

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int SDchipSelectPin = 4;
const int ETHERNETchipSelectPin = 10;

void setup()
{
// ---- start setup SERIAL PORT --------------------------------------------------
Serial.begin(9600);
Serial.println(" ********************** Arduino Started ********************** ");
// ---- end setup SERIAL PORT --------------------------------------------------


// ------------ Set pin modes ... ----------------------------------------------
  pinMode(ETHERNETchipSelectPin, OUTPUT);    // pin 10 -> make sure that the default chip select pin is set to output, even if you don't use it:  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
  pinMode(SDchipSelectPin, OUTPUT);      //    pin 4 -> On the Ethernet Shield, CS is pin 4  pinMode(4, OUTPUT); // set the SS pin as an output (necessary!)
  // both units are turned off here.
  //digitalWrite(10, HIGH); // but turn off the W5100 chip!
  //digitalWrite(4, HIGH); // but turn off the SD card functionality!
// ------------ End Set pin modes ... -------------------------------------------

 
// --------  Start ethernet --------------------------------
  digitalWrite(ETHERNETchipSelectPin, LOW); // turn on the W5100 chip! by default it will be ON, so unnecessary.
  digitalWrite(SDchipSelectPin, HIGH); // but turn off the SD card functionality!
  Ethernet.begin(mac, ip, gateway);     //, subnet);
// ----------- end setup ethernet --------------------------


//------------ start of setup SD -------------------------------
  // initialize the SD card
  Serial.println("Setting up SD card...");    //To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
    digitalWrite(ETHERNETchipSelectPin, HIGH); // turn off the W5100 chip!
digitalWrite(SDchipSelectPin, LOW); // turn on the SD chip!

  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(SDchipSelectPin)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    //return;
    SDavailable =  false;  // set a flag to indicate that the SD is not available so that the code in the loop knows.
  }
  Serial.println("card initialized.");
//------------ end of setup SD -------------------------------


}

void loop() {
// ++++++++++++++++++ GET SOME DATA ++++++++++++++++++++++++++
// make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

sendtoethernet(dataString);

sendtoSD(dataString);

delay(10000);

}


void sendtoethernet(String dataString){
  // ----------------------------Send the data via ethernet ----------------------------
//set its SS pin (10) HIGH, and the SD card's SS (4) pin LOW
digitalWrite(ETHERNETchipSelectPin, LOW);       // select ethernet mode -> LOW selects, HIGH deselects module
digitalWrite(SDchipSelectPin, HIGH);       // deselect SD mode -> LOW selects, HIGH deselects module

  if (client.connect()) {   
    client.print("GET http://website.com/upload.php?P=");
    client.print(dataString);
    client.println();
    client.stop();
  }
else {
    Serial.println(" ***************** Failed to connect to client ***************** ");
  }
}


void sendtoSD(String dataString){
// ----------------------------Save the data in the SD -------------------------------------------
if (SDavailable != false){
//To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
digitalWrite(ETHERNETchipSelectPin, HIGH);       // deselect ethernet mode-> LOW selects, HIGH deselects module
digitalWrite(SDchipSelectPin, LOW);           // select SD mode-> LOW selects, HIGH deselects module

// open the file. note that only one file can be open at a time, so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  } 
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

}
// ---------------- end of saving data to SD -----------------------------
}

// to be implemented later
/*
void switch2microSD() {
  //
  digitalWrite(10,HIGH);
  digitalWrite(4,LOW);
  delay(5);
}

void switch2eth() {
  //
  digitalWrite(10,LOW);
  digitalWrite(4,HIGH);
  delay(5);
}
*/

aboshan

#20
Mar 13, 2011, 09:45 pm Last Edit: Mar 13, 2011, 09:47 pm by aboshan Reason: 1
Gixxer,

I am glad to tell you that I tested your code and it works.
However, I had to modify the initialization of the SD card:
Code: [Select]
//------------ start of setup SD -------------------------------
 // initialize the SD card
 Serial.println("Setting up SD card...");     //To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
   digitalWrite(ETHERNETchipSelectPin, HIGH); // turn off the W5100 chip!
digitalWrite(SDchipSelectPin, LOW); // turn on the SD chip!

 Serial.print("Initializing SD card...");
 // see if the card is present and can be initialized:
 if (!SD.begin(SDchipSelectPin)) {
   Serial.println("Card failed, or not present");
   // don't do anything more:
   //return;
   SDavailable =  false;  // set a flag to indicate that the SD is not available so that the code in the loop knows.
 }
//<<<<<<<<<<<<<<<<<<<<<<<<<MODIFIED PART >>>>>>>>>>>>>>>>>>>>>>>>>>>>//
 else{
 Serial.println("card initialized.");
 SDavailable = true;
 }
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>//
//------------ end of setup SD -------------------------------


You need to initialize SDavailable for it to be true.

Here's my full code (needs some cleanup), it basicly generates a random int between 0 and 50, sends it to a php script on my server and also to "testfile.txt" on the SD card.

the loop executes every 10 seconds, because I have a database that has a 10 second refresh rate. Feel free to remove the prevtime/newtime part if you don't want refresh control.

Code: [Select]
// Simple example to show how the Ethernet WebClient example would
// change to use the DHCP and DNS libraries

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

float prevTime=0;
float newTime=0;

/*
The circuit:
* analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
* Ethernet chip attached to SPI bus as follows:
** SS - pin 10 (by default)
*/
// to deselect a peripherial (SD or ethernet) put HIGH to its CS pin.

char* kHostname = "192.168.1.3";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[4]; // = { 10, 0, 0, 177 };
byte server[4]; // = { 64, 233, 187, 99 }; // Google

Client client(server, 80);

boolean SDavailable;

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int SDchipSelectPin = 4;
const int ETHERNETchipSelectPin = 10;


void setup()
{
 Serial.begin(9600);
 //pin i/o
 //pinMode(2,INPUT);
 //pinMode(13,OUTPUT);
 
 //pull-ups
 //digitalWrite(2,HIGH);
 
 //interrupts
 //attachInterrupt(1,ctr,CHANGE);
 
 pinMode(ETHERNETchipSelectPin, OUTPUT);    // pin 10 -> make sure that the default chip select pin is set to output, even if you don't use it:  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
 pinMode(SDchipSelectPin, OUTPUT);      //    pin 4 -> On the Ethernet Shield, CS is pin 4  pinMode(4, OUTPUT); // set the SS pin as an output (necessary!)
 digitalWrite(ETHERNETchipSelectPin, LOW); // turn on the W5100 chip! by default it will be ON, so unnecessary.
 digitalWrite(SDchipSelectPin, HIGH); // but turn off the SD card functionality!
 
 // Get an IP address to use and also find out our DNS server address
 while (Dhcp.beginWithDHCP(mac) != 1)
 {
   Serial.println("Error getting IP address via DHCP, trying again...");
   delay(15000);
 }    
 delay(1000);
 byte buffer[6];
 Dhcp.getLocalIp(buffer);
 Serial.print("ip address: ");
 printArray(&Serial, ".", buffer, 4, 10);
 Serial.println("connecting...");
 
 DNSClient dns;
 // Use "server" to hold the DNS server address while we initialise
 // the DNS code
 Dhcp.getDnsServerIp(server);
 dns.begin(server);

 // Resolve the hostname to an IP address
 // Re-use "server" to hold the address for the resolved hostname
 int err = dns.gethostbyname(kHostname, server);
 if (err == 1)
 {
   Serial.print(kHostname);
   Serial.print(" resolved to ");
   Serial.print((int)server[0]);
   Serial.print(".");
   Serial.print((int)server[1]);
   Serial.print(".");
   Serial.print((int)server[2]);
   Serial.print(".");
   Serial.println((int)server[3]);
 }
 else
 {
   Serial.println("DNS lookup failed");
 }
//------------ start of setup SD -------------------------------
 // initialize the SD card
 Serial.println("Setting up SD card...");     //To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
   digitalWrite(ETHERNETchipSelectPin, HIGH); // turn off the W5100 chip!
digitalWrite(SDchipSelectPin, LOW); // turn on the SD chip!

 Serial.print("Initializing SD card...");
 // see if the card is present and can be initialized:
 if (!SD.begin(SDchipSelectPin)) {
   Serial.println("Card failed, or not present");
   // don't do anything more:
   //return;
   SDavailable =  false;  // set a flag to indicate that the SD is not available so that the code in the loop knows.
 }
 else{
 Serial.println("card initialized.");
 SDavailable = true;
 }
//------------ end of setup SD -------------------------------

}

void printArray(Print *output, char* delimeter, byte* data, int len, int base)
{
char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for(int i = 0; i < len; i++)
{
if(i != 0)
output->print(delimeter);
output->print(itoa(data[i], buf, base));
}
output->println();
}

void loop()
{
 newTime=millis();
 
 // execute code every 10sec, as rrd refresh is also 10sec
 if(newTime>=prevTime+10000)
 {
   prevTime=newTime;
   
   int randomNr = random(0,50);
   
   sendtoSD(randomNr);
   sendtoethernet(randomNr);

 }
}

void sendtoethernet(int randomNr)
{
// ----------------------------Send the data via ethernet ----------------------------
   //set its SS pin (10) HIGH, and the SD card's SS (4) pin LOW
   digitalWrite(ETHERNETchipSelectPin, LOW);       // select ethernet mode -> LOW selects, HIGH deselects module
   digitalWrite(SDchipSelectPin, HIGH);       // deselect SD mode -> LOW selects, HIGH deselects module

   
   String a = "GET /rrdcounter/counterUpdate.php?value=";
   String b = " HTTP/1.0";
   String url = a + randomNr + b;
   
   if (client.connect())
   {
     Serial.println("connected");
     client.println(url);
     client.println();
     Serial.print("submitted value: ");
     Serial.println(randomNr);
   }
   else
   {
     Serial.println("connection failed");
   }
   
   while(client.available()) {
   char c = client.read();
   Serial.print(c);
   }
   
   Serial.println();
   Serial.println("disconnecting...");
   client.stop();
}
 
void sendtoSD(int randomNr)
{
// ----------------------------Save the data in the SD -------------------------------------------
 if (SDavailable != false)
 {
//To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
 digitalWrite(ETHERNETchipSelectPin, HIGH);       // deselect ethernet mode-> LOW selects, HIGH deselects module
 digitalWrite(SDchipSelectPin, LOW);           // select SD mode-> LOW selects, HIGH deselects module

// open the file. note that only one file can be open at a time, so you have to close this one before opening another.
 File dataFile = SD.open("testfile.txt", FILE_WRITE);
// if the file is available, write to it:
 if (dataFile) {
   dataFile.print(randomNr);
   dataFile.print(",");
   dataFile.close();
   // print to the serial port too:
   Serial.print("Value written to SD: ");
   Serial.println(randomNr);
 }  
 // if the file isn't open, pop up an error:
 else {
   Serial.println("error opening testfile.txt");
 }

 }
// ---------------- end of saving data to SD -----------------------------
}



Nice job, seriously!

Sergegsx

you have made my day !!!
thanks for testing it! im so happy it worked. I really was not sure as all was written whilst learning the theory with no chance to test it. its so frustrating not being able to test it at the moment.

So I guess my objective was accomplished, to create a dead easy code to use both ethernet and SD with just one line of code

Code: [Select]

sendtoethernet(dataString);

sendtoSD(dataString);


Im sure it will be useful for other people.

Sergegsx

#22
Mar 13, 2011, 10:55 pm Last Edit: Mar 13, 2011, 11:04 pm by Gixxer Reason: 1
latest version with aboshan comments implemented. thanks !

once i have the chance to test it i will clean it up.

Code: [Select]

/*
  Official Ethernet shield + SD working together.

This sketch connects to the internet and sends a value to a php file for it
to process it to its convenience (ie: store it in mysql database), it also
saves the value to de SD card using the Arduino Wiznet Ethernet shield.

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

The circuit:
* analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
* Ethernet chip attached to SPI bus as follows:
** SS - pin 10 (by default)
// to deselect a peripherial (SD or ethernet) put HIGH to its CS pin.

created 13 Mar 2011
by S. Escuder

*/

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

//Server IP address
byte server[] = { 173,194,33,104 }; // Google
//Setup a client
Client client(server, 80);
byte ip[] = { 192,168,1,69 };  // Using a Router
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte gateway[] = { 192, 168, 1, 1 };   //your router's IP address

boolean SDavailable;

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int SDchipSelectPin = 4;
const int ETHERNETchipSelectPin = 10;

void setup()
{
// ---- start setup SERIAL PORT --------------------------------------------------
Serial.begin(9600);
Serial.println(" ********************** Arduino Started ********************** ");
// ---- end setup SERIAL PORT --------------------------------------------------


// ------------ Set pin modes ... ----------------------------------------------
  pinMode(ETHERNETchipSelectPin, OUTPUT);    // pin 10 -> make sure that the default chip select pin is set to output, even if you don't use it:  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
  pinMode(SDchipSelectPin, OUTPUT);      //    pin 4 -> On the Ethernet Shield, CS is pin 4  pinMode(4, OUTPUT); // set the SS pin as an output (necessary!)
  // both units are turned off here.
  //digitalWrite(10, HIGH); // but turn off the W5100 chip!
  //digitalWrite(4, HIGH); // but turn off the SD card functionality!
// ------------ End Set pin modes ... -------------------------------------------

 
// --------  Start ethernet --------------------------------
  digitalWrite(ETHERNETchipSelectPin, LOW); // turn on the W5100 chip! by default it will be ON, so unnecessary.
  digitalWrite(SDchipSelectPin, HIGH); // but turn off the SD card functionality!
  Ethernet.begin(mac, ip, gateway);     //, subnet);
// ----------- end setup ethernet --------------------------


//------------ start of setup SD -------------------------------
  // initialize the SD card
  Serial.println("Setting up SD card...");    //To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
    digitalWrite(ETHERNETchipSelectPin, HIGH); // turn off the W5100 chip!
digitalWrite(SDchipSelectPin, LOW); // turn on the SD chip!

  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(SDchipSelectPin)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    //return;
    SDavailable =  false;  // set a flag to indicate that the SD is not available so that the code in the loop knows.
  }
  else{
  Serial.println("Card initialized.");
  SDavailable = true;
  }

//------------ end of setup SD -------------------------------
}




void loop() {
// ++++++++++++++++++ GET SOME DATA ++++++++++++++++++++++++++
// make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

sendtoethernet(dataString);

sendtoSD(dataString);

delay(10000);

}


void sendtoethernet(String dataString){
  // ----------------------------Send the data via ethernet ----------------------------
//set its SS pin (10) HIGH, and the SD card's SS (4) pin LOW
digitalWrite(ETHERNETchipSelectPin, LOW);       // select ethernet mode -> LOW selects, HIGH deselects module
digitalWrite(SDchipSelectPin, HIGH);       // deselect SD mode -> LOW selects, HIGH deselects module

  if (client.connect()) {   
    client.print("GET http://website.com/upload.php?P=");
    client.print(dataString);
    client.println();
    client.stop();
  }
else {
    Serial.println(" ***************** Failed to connect to client ***************** ");
  }
}


void sendtoSD(String dataString){
// ----------------------------Save the data in the SD -------------------------------------------
if (SDavailable != false){
//To use the SD card, you set its SS pin HIGH and the Ethernet shield's SS pin LOW
digitalWrite(ETHERNETchipSelectPin, HIGH);       // deselect ethernet mode-> LOW selects, HIGH deselects module
digitalWrite(SDchipSelectPin, LOW);           // select SD mode-> LOW selects, HIGH deselects module

// open the file. note that only one file can be open at a time, so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.print("Value written to SD: ");
    Serial.println(dataString);
  } 
  // if the file isn't open, pop up an error:

  else {
    Serial.println("error opening datalog.txt");
  }

}
// ---------------- end of saving data to SD -----------------------------
}



// to be implemented later
/*
void switch2microSD() {
  //
  digitalWrite(10,HIGH);
  digitalWrite(4,LOW);
  delay(5);
}

void switch2eth() {
  //
  digitalWrite(10,LOW);
  digitalWrite(4,HIGH);
  delay(5);

}
*/

colbec

Here is my serial output from Gixxer latest version.

Code: [Select]

********************** Arduino Started **********************

Setting up SD card...

Initializing SD card...Card initialized.

***************** Failed to connect to client *****************

error opening datalog.txt

***************** Failed to connect to client *****************

error opening datalog.txt



Since aboshan has no problem this could be just my setup. SD files seem to be ok for my approach (see earlier in thread) so I'm not sure what is different. Using new UNO and Arduino0022. Only changes to code are to use fixed IP suitable for my subdomain, remove references to gateway since this will be correctly deduced by the system, and change MAC addr.

Since it is only a few days until Gixxer has his hardware in hand will wait and see what transpires at that time.

Sergegsx

COLBEC I have the same problem

Code: [Select]

Initializing SD card...card initialized.
error opening datalog.txt
679,878,42
684,886,43
683,887,42
685,888,42


aboshan can you tell me the exact SD card you are using? i have tried with a nokia SD card that comes with mobile phones.
also, how is your card formatted?

I think its an SD card problem cause the example that comes with arduino 22 gives me the same problem.

davekw7x

#25
Mar 21, 2011, 05:09 pm Last Edit: Mar 21, 2011, 06:07 pm by davekw7x Reason: 1

... nicer and more updated one....

I'll start with a way of implementing the "updated" part.  Someone else can make it "nicer."

I started with the Ethernet library WebClient example in arduino-0022.  I added a few lines from the SD library DataLogger example to open a file and store the bytes in the SD card on the Ethernet Shield.

By building on "official" Arduino library examples rather than just making up a bunch of stuff on my own, my hope is that maybe the result will be useful as a reference that can be maintained more easily as the Arduino stuff evolves over subsequent releases.

Note, particularly, that with the Arduino libraries, the application sketch does not have to manipulate any of the chip select pins for alternating between accesses to the two different SD devices.  Really.

I mean, I have seen some postings where people made flat statements that you had to clutter up your sketches with all of that stuff, but you don't have to.  Really.  The libraries take care of that.

I have used multiple SPI devices in other applications, but since this thread is about the Ethernet Shield, that's what the following simple example is for.

Code: [Select]

/*
       EthernetSD.pde
       
       
 A note from davekw7x:
 
 Code in this sketch combines code from two examples in arduino-0022:
 
 The Ethernet library WebClient example sketch
     created 18 Dec 2009
     by David A. Mellis
     
  No licensing or copyright information was explicitly given
  in the sketch, but it is part of the Arduino distribution,
  so this little program inherits whatever restrictions are
  in effect for Arduino.
 
 The SD library DataLogger example sketch:
     created  24 Nov 2010
     updated 2 Dec 2010
      by Tom Igoe
     
   That author graciously released the DataLogger code to public domain,
   and I do the same for whatever few lines that I have created for this example
   
 Citation would be the Polite Thing To Do, but is not really expected.
   
   
   Regards,
   
   davekw7x
*/

/*

 Web client example sketch from arduino-0022 with a few lines
 added by davekwy7x to store results of an HTML "get" command
 in a file on SD.
 
 Tested with genuine Arduino Ethernet Shield Version 5
 (the one with the microSd connector) and a genuine Arduino
 Duemilanove.
 
 My local net is served by a Linux machine with IP address 10.10.5.1,
 and it has an Apache web server configured in a completely conventional
 manner.
 
 There is a file named "test.php" in /var/www/html/daves.
 
 The contents of the file are between the dashed lines
 ------------------------------------------
<html>
<head>
   <Title>test.php</title>
<body>
   <?php
        
print 'Hello, World!<br>';
        print 
'From /var/www/html/daves';
    
?>

</body>
 ------------------------------------------

After running this sketch you can take the SD card from
the Ethernet Shield and read it on your PC (or whatever).

Or you can run the SD library DumpFile example (after
changing the file name in that sketch to match the
file name in this one).

davekw7x
March, 2011

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

const int SD_CHIP_SELECT = 4; // For the Ethernet Shield
const int ETHERNET_CHIP_SELECT = 10;

//
// Enter a MAC address and IP address for your controller below.
//
// A "private" MAC address that will never be part
// of any commercial product, so shouldn't conflict
// with anything on your net (unless you are running
// something else like this that you have given
// this identical MAC address.)
byte mac[]    = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

//
//IP address for my sandbox LAN with an Apache web server
// Change the following to whatever addresses are
// appropriate for your testing.
//
byte ip[]     = {10, 10, 5, 177};
byte server[] = {10, 10, 5, 1};

//
//HTML command to get a PHP file located in /var/www/html/daves on
// my webserver machine.
// Change it for whatever you want to test it with.
//
char  htmlCommand[] = "GET /daves/test.php";

//
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP),
// and is used by my Apache server.
//
Client client(server, 80);

//
// Define the file name and file here so that it can be used
// in both setup() and loop()
char filename[] = "webfile.txt";
File dataFile;


void setup() {
   //
   // Start the serial library.
   Serial.begin(9600);

   //
   // Give things a second to settle down.
   delay(1000);

   Serial.print("Initializing SD card...");
   //
   // Make sure that the default chip select pin is set to
   // output, even if you don't use it.  (Note
   // from davekw7x: This isn't really necessary
   // here, since the library takes care of it,
   // but it doesn't hurt.)
   pinMode(ETHERNET_CHIP_SELECT, OUTPUT);
   digitalWrite(ETHERNET_CHIP_SELECT, HIGH);

   //
   // See if the card is present and can be initialized.
   if (!SD.begin(SD_CHIP_SELECT)) {
       Serial.println("Card failed, or not present");
       //
       // exit() disables interrupts and enters
       // a do-nothing forever loop
       exit(1); // Value is irrelevant
   }
   Serial.println("card initialized.");

   //
   // Open the file.
   dataFile = SD.open(filename, FILE_WRITE);
   if (!dataFile) {
       Serial.println("Can't open ");Serial.print(filename);
       Serial.println(" for writing.");
       exit(1);
   }
   Serial.print("Opened file ");Serial.print(filename);
   Serial.println(" for writing.");

   //
   // Start the Ethernet connection.
   Ethernet.begin(mac, ip);
   Serial.println("Connecting...");

   // If it couldn't connect, bail out
   if (!client.connect()) {
       Serial.println("Connection failed.");
       exit(1);
   }
   // OK! Now ready for action.
   Serial.println("Connected!");

   // Make the HTTP request.
   client.println(htmlCommand);
   client.println();

   // Return from setup() so that the results of
   // the request can be handled in loop()
}

void loop()
{

   // If there are incoming bytes available
   // from the server, read them and print
   // them and store then in the SD file.
   if (client.available()) {
       char c = client.read();
       Serial.print(c);
       dataFile.print(c);
       
   }

   //
   // If the server is disconnected, stop the client and close the file
   if (!client.connected()) {
       Serial.println();
       Serial.println("Disconnecting.");
       client.stop();
       Serial.print("Closing file ");Serial.println(filename);
       dataFile.close();
       Serial.println("Program is complete.");
       exit(0);
   }
   
   // Client is still connected.
   // Loop back for more bytes.
}


Note that the argument to open a file for writing is "FILE_WRITE" and is documented on the Arduino SD reference page.  If the file does not exist, it creates a new file.  If the file already exists, it appends new stuff to it.  Other arguments are possible and are documented in the SdFat library, for which the Arduino SD library is a wrapper.

I have tested this with a couple of microSD cards that I have (1 GigaByte and 4 GigaByte).  They came formatted "FAT32." I had no reason re-format them, so I left the formatting alone.  I can read and write them in any of the various card readers on my Windows XP and my Linux workstations.

Bottom line recommendations:

1.  Don't even think of trying my little program unless (and until) you can successfully run the SD DataLogger and SD FileDump examples.  That way you can verify that the required SD functionality is present with your setup.

2.  For the Ethernet stuff, I would probably start with the WebServer example before going to WebClient.  That way you can make sure your Ethernet setup works before you try to get some HTML stuff from a web server.  At any rate, make sure that WebClient works by itself before trying to combine its code with other stuff.

3.  For other kinds of Ethernet applications and other kinds of SD applications  (SD reading from a file to use with a WebServer, for example), you can try doing the same as I did: Test each one using Arduino library examples or make your own examples. After each one is working (perfectly), then (and only then) try to combine them.


Regards,

Dave

Footnote

To whom it may concern:
The subject of this thread when it started was about combining Ethernet and SD functions on an Ethernet Shield.  I respectfully suggest that you verify correct operations of both Ethernet and SD stuff before trying to combine them.  If you have problems with one or other of the separate functions, I respectfully suggest that you confer with other posts in this forum (or start your own thread)  instead of tacking stuff to this one.

Sergegsx

Thank you for such a detail explanation.

I have tried the example included in SD->Datalogger and i get this....

Code: [Select]

Initializing SD card...card initialized.
error opening datalog.txt


any idea why? I have a 2Gb card that came with my nokia N81 phone.
Ive tried formating it to fat32 and fat. noluck.

Sergegsx

ok, i just read another post of yours. asking for the setup, when i tried the Sd i had a few things connected to the arduino, so maybe that has something to do. I will look into it with just my arduino uno and official ethernet shield.

aboshan

My sd card was also a Nokia microSD card - 8GB - fat32 formatted.

Could you try my code integrally?
The only requirement is that the arduino be connected to a dhcp server, don't bother about the other ip's, the sd part should work anyway.

Sergegsx

hi, yes i will try your code tomorrow that i will be near my hardware.

thanks for the reply, i hope its a matter of my setup.
I will report back how your code works.

btw, i noticed that one program i had running in my setup (nothing SD related) stopped working (the internet connection) when inserting the sd card.

Go Up