Need help with my SD card and ethernet shield 2 (W5500)

Hi!
I am very new at programming but need to do some for my work.
My boards are the Uno with an ethernet shield 2 (W5500).
What I want to do is to catch interrupts, count the time and safe them on SD Card.
Currently it is working on general, but I have problems on adding further programmings.
I added the modification in the SD.cpp

Here's the sketch:

#include <SPI.h>
#include <SD.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>


const int chipSelect = 4;                             // SD Karte
const byte Strommesser_unten = 2;                     // untere Grenze
const byte Strommesser_oben = 3;                      // obere Grenze
volatile int dauer;                                   
int dauerold;
boolean startwert_erfasst = false;
boolean signal2_erfasst = false;
volatile int startwert;
boolean karte_eingesetzt = false;
volatile int T_mittel;
volatile int T_mittelold;


void setup ()
{
  Serial.begin(115200);
  Serial.print("initializing...");          // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) 
  {
    Serial.println("Initializing failed");  // don't do anything more:
    karte_eingesetzt = false;
   // return;
  }
  else
  {
  Serial.println("Card initialized:");
  karte_eingesetzt = true;
  }
  pinMode (chipSelect, OUTPUT);
  digitalWrite (Strommesser_unten, HIGH);  // internal pull-up resistor
  digitalWrite (Strommesser_oben, HIGH);
} 

void loop ()
{
  Serial.println ("TEST");
  String dataString = "Dauer: ";         // Anlegen eines Strings
  String Mittel = "Mittel: ";
  attachInterrupt (0, ERSTER, FALLING);
  attachInterrupt (1, MITTEL, FALLING);
  attachInterrupt (0, ZWEITER, RISING);
  if (dauer != dauerold && signal2_erfasst == true)
  {
    dataString += String(dauer);              // Beschreiben des Strings mit dem Aussetzer
    Mittel += String(T_mittel);
    File dataFile = SD.open("Kontakt.txt", FILE_WRITE);
    dataFile.println(dataString);
    dataFile.println(Mittel);
    dataFile.close();
    Serial.println(dataString);
    Serial.println(Mittel);
    dauerold = dauer;
    signal2_erfasst = false;
  }
} 

void ERSTER ()
{
    startwert_erfasst = true;
    startwert = micros();
}

void MITTEL()
{
  if(startwert_erfasst == false) return;
  else
  {
  signal2_erfasst = true;
  T_mittel = millis()-T_mittelold;
  T_mittelold = millis();
}
}

void ZWEITER()
{
  if(startwert_erfasst == false) return;
  else
  {
    detachInterrupt(0);
    dauer = micros() - startwert;
  }
}

It is a little bit unstructured, maybe someone could help me in this case too....

The main problem is, that i want the loop only get started when the SD Card is insert.
I tried to use

if (SD.begin(chipSelect)
.
.
.

This works, but i get problems with my interrupts. For any reasons, the times aren't right anymore.

I get true times in this sketch, but the SD-conditions doesn't work. As you can see I tried to solve this in the setup with the boolean operation, but that's doesnt work very well cause it does the serial.begin only one time.
I tried to find it out by myself and with help from the datasheet, but can't solve it... Hope you can help me.
Thanks,
toolmaker

I added the modification in the SD.cpp

What modification?

Your setup() function does not set pin 10 as an output. That is mandatory for the Arduino to be a SPI master.

  attachInterrupt (0, ERSTER, FALLING);
  attachInterrupt (1, MITTEL, FALLING);
  attachInterrupt (0, ZWEITER, RISING);

You can only have one interrupt type per pin. ERSTER will never be called.

  attachInterrupt (0, ERSTER, FALLING);
  attachInterrupt (1, MITTEL, FALLING);
  attachInterrupt (0, ZWEITER, RISING);

Note what Paul says. If you need to act on both FALLING and RISING events then consider using CHANGE and test the pin state in the ISR and act accordingly.

PaulS:
What modification?

Your setup() function does not set pin 10 as an output. That is mandatory for the Arduino to be a SPI master.

This modification:

boolean SDClass::begin(uint8_t csPin) {
/*

Performs the initialisation required by the sdfatlib library.

Return true if initialization succeeds, false otherwise.

*/
if (root.isOpen()) root.close(); // allows repeated calls
return card.init(SPI_HALF_SPEED, csPin) &&
volume.init(card) &&
root.openRoot(volume);
}

So can you explain me again what's behind the fact with pin 10? I wrote about it a few times but couldn't understand it.

Are you sure that my interrupts are wrong? I measured them with an oszi and it looked good. What I want to catch with this program is the time from an delta voltage on a inverted comparator.
the first interrupt catches when the voltages goes up --> comparator signal 1 goes low,
the second one catches the time when the highes voltage arrieved --> comparator signal 2 goes low,
the last interrupt catches the time when the voltage goes down again --> comparator signal 1 rises.

I think it works that way because the times look realistic. But I'm going to check this tomorrow!

So can you explain me again what's behind the fact with pin 10? I wrote about it a few times but couldn't understand it.

The mode of pin 10 defines whether the Arduino is an SPI master or an SPI slave. An ethernet shield or SD card can not be an SPI master. How would they drive the Arduino to send them data? So, pin 10 must be set as OUTPUT to define that it is the master.

Are you sure that my interrupts are wrong?

I am sure that each time you call attachInterrupt(), all previous handler registered for the specified pin are removed. So, attachInterrupt (0, ZWEITER, RISING) unregisters the handler registered with attachInterrupt (0, ERSTER, FALLING).

Ok the first step i do tomorrow is to put 10 as an output. But what else do I have to change then to start and stop the programm with an plug in and off from the SD?

And there is still a question open for the interrupts... (Don't get me wrong I reall just try to understand it)
What I've learned before is that an interrupt jumps into the ISR when it gets the signal, works down the ISR and jumps out again. If that's right, why is my sketch wrong then? When the delta voltage start falling, the ISR (0, ERSTER, FALLING) saves the time at this point into a volatile variable and jumps out in the loop again.
After that, the loop waits if it's FALLING or RISING again.

Or is it that when it jumps into the (0, ERSTER, FALLING) ISR, it stays in it until the Pin 0 is high again (--> RISING)?

But what else do I have to change then to start and stop the programm with an plug in and off from the SD?

Does your SD reader have the card detect pin broken out? If so, yo can simply read the state of the pin in loop(), and do nothing if there is no SD card detected.

What I've learned before is that an interrupt jumps into the ISR when it gets the signal, works down the ISR and jumps out again.

Correct.

If that's right, why is my sketch wrong then?

It is wrong only in the sense that you expect ERSTER() to be called even though you have unregistered it.

When the delta voltage start falling, the ISR (0, ERSTER, FALLING) saves the time at this point into a volatile variable and jumps out in the loop again.

Well, it would IF it ever got called. It does not get called, so that can't happen.

Each interrupt pin can only have one Interrupt Service Routine (ISR) associated with it. So when you do

  attachInterrupt (0, ERSTER, FALLING);
  attachInterrupt (1, MITTEL, FALLING);
  attachInterrupt (0, ZWEITER, RISING);

only the ZWEITER function will be associated with interrupt 0 so ERSTER will never be called even if a rising signal occurs on the interrupt pin.

This works, but i get problems with my interrupts. For any reasons, the times aren't right anymore.

I pointed this out to Surfer Tim a while back. When you use interrupts, it takes priority over millis. In the example, the interrupt was continuously called, and the serial monitor printed millis(). But millis never changed. SurferTim was able to explain the exact reason, but I thought i'd just give you a heads up.

OK thanks so far. I think i get it now. I'm currently trying to change my two ISR for PIN 0 into one ISR with CHANGING.

But still I would be really thankfull if you could help me with my sketch. I've got to solve this in few weeks and be really totally new in programming.

To the problem with the SD detecter Pin, I'm not really sure about that. I couldn't find it out from the datasheet but be very sure that it has this Pin. Just don't know how to find it out... This is the datasheet:

http://download.arduino.org/products/ETHERNETSHIELD2/arduino-Ethernet-Shield2-V2-sch.pdf


Edith: I measured the signals with measure software and got the right times now.
Here's my actual sketch:

#include <SPI.h>
#include <SD.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>

/**************************************************************************************
* FESTLEGEN DER VARIABLEN                                                             *
**************************************************************************************/

const int chipSelect = 4;                             // SD Karte
const byte Strommesser_unten = 2;                     // untere Grenze
const byte Strommesser_oben = 3;                      // obere Grenze
volatile int dauer;                                   
int dauerold;
boolean startwert_erfasst = false;
boolean signal2_erfasst = false;
volatile int startwert;
boolean karte_eingesetzt = false;
volatile int T_mittel;
volatile int T_mittelold;

/**************************************************************************************
* START DES SETUPS                                                                    *
**************************************************************************************/

void setup ()
{
  Serial.begin(115200);
  //***********************************************************************************
  Serial.print("SD Karte wird initialisiert...");          // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) 
  {
    Serial.println("Initialisierung fehlgeschlagen oder Karte fehlt");  // don't do anything more:
    karte_eingesetzt = false;
   // return;
  }
  else
  {
  Serial.println("Karte initialisiert. Starte Messung:");
  karte_eingesetzt = true;
  }
  //***********************************************************************************
  
  //pinMode (LEDro, OUTPUT);  // so we can update the LED
  //pinMode (LEDgr, OUTPUT);
  pinMode (chipSelect, OUTPUT);
  digitalWrite (Strommesser_unten, HIGH);  // internal pull-up resistor
  digitalWrite (Strommesser_oben, HIGH);
} 

/**************************************************************************************
* START DES LOOPS                                                                     *
**************************************************************************************/

void loop ()
{
  String dataString = "Dauer: ";         // Anlegen eines Strings
  String Mittel = "Mittel: ";
  attachInterrupt (0, untere_grenze, CHANGE);
  attachInterrupt (1, MITTEL, FALLING);
  if (dauer != dauerold || T_mittel != T_mittelold)
  {
    dataString += String(dauer);              // Beschreiben des Strings mit dem Aussetzer
    Mittel += String(T_mittel);
    File dataFile = SD.open("Kontakt.txt", FILE_WRITE);
    dataFile.println(dataString);
    dataFile.println(Mittel);
    dataFile.close();
    Serial.println(dataString);
    Serial.println(Mittel);
    dauerold = dauer;
    signal2_erfasst = false;
  }
} 

/**************************************************************************************
* ISR des ersten Interrupts                                                          *
**************************************************************************************/

void untere_grenze ()
{
    if ( digitalRead (Strommesser_unten) == LOW)
    {
      startwert_erfasst = true;
      startwert = micros();
    }
    if (digitalRead (Strommesser_unten) == HIGH)
    {
      dauer = micros() - startwert;
    }
}

/**************************************************************************************
* ISR des mittleren Interrupts                                                        *
**************************************************************************************/

void MITTEL()
{
  T_mittel = millis()-T_mittelold;
  T_mittelold = millis();
}

I still use micros() for the first ISR because "dauer" is only around 900 microseconds long. By taking millis(), I would only get 0's and 1's.

The sketch is still a little bit unstructured. Maybe you could give me some tipps what I can do better.
My destiny is it, that it writes "dauer", and "T_mittel" on the SD, when it's unequal to the last measure. It's going to measure electrical contacts on a motor-injector. If dauer or T_mittel is unequal to the last measure, I know that there was an defect on the contacts.
Maybe you could give me some inputs or tipps, and still the problem with the " if (SD present)..." thing

Are you using a library for the w5500 IC? Most use a different include file name.

I recommend disabling the slave selects on all other SPI devices before starting any of them. This is what I use. I avoid the "pinMode(10,OUTPUT)" call before the digitalWrite call because it causes problems on the Due.

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

  // disable the w5500 SPI
  digitalWrite(10,HIGH);

  // start the SD
  if (!SD.begin(chipSelect))

SurferTim:
Are you using a library for the w5500 IC? Most use a different include file name.

Yes I think so. I installed the one for Ethernet shield 2 from Wiznet.

I'm going to try this with pin 10. And tell you later. Thank you all so far!

If you still have problems, insure you power down the Arduino for a few seconds after reprogramming it with the new code. Sometimes the other SPI devices lock up if the slave selects are not disabled when you run a begin call on another SPI device.

Thank you, it works!

But one last question. Can someone explain me how I can integrate the serial prints in the loop?

Currently I've got the messages "SD card initialising....." "SD card initialised" etc. in the setup, which means i get this one time when the arduino gets power. If i plug in or out the SD the loop starts or stop. What I want is, that the arduino writes "start measure:" within the loop when the SD has pluged out and in again. Not only in the setup. But my problem is, that when i write it in the loop, it constantly writes "start measure:" ... Kind of a blemish

my problem is, that when i write it in the loop, it constantly writes "start measure:"

Make the message printing in loop() dependant on a global boolean variable initially set to true. When you have printed the message set the variable to false

if (OKToprint)
  {
    Serial.println("A message");
    OKToprint = false;  
  }