DUE + Ethernet Shield + RTC DS3234 = SPI Problem?

Hello!! :wink:

In General it should be possible to run Arduino DUE with three SPI devices, but I have a Problem to get it run:
I want to use DUE with the Ethernet Shield R3 (LAN & SD) and a SPI Real Time Clock (DS3234).
Ethernet is using Pin 10 as SS, the SD card Pin 4 and the RTC I connected to Pin 52.
MISO, MOSI, CLK of the RTC I ve connected to PIN 12,13,14. (are the pins connected to the SPI by the Eth. Shield at all?) :astonished:

I have tested the RTC by connecting it directly to the SPI Port of DUE - without Ethernet Shield - and this works
Also the LAN connection is working without RTC...

Pls help!! :~

do you have an external power supply connected?

Cromium_Steel:
do you have an external power supply connected?

No, I run Arduino by USB and RTC with 3.3V from Arduino... do you think this does affecting the SPI?

Primary I want to know, if the combination of this three SPI devices (Ethernet, SD and RTC) works on DUE (or is there a 5V - 3.3V Problem)?
Further I am not quite sure if the Ethernet Shields Pin 12,13,14 is connected to SPI (also in Combination with DUE)...

It appears you have a SPI mode problem also. The DS3234 is a mode 1 SPI device according to the datasheet, and the w5100 and SD are mode 0. You will probably need to switch modes when accessing the RTC.

// change to mode 1 for RTC
 SPI.setDataMode(SPI_MODE1);  

 // do your RTC SPI stuff

 // then change back to mode 0 for w5100 and SD
 SPI.setDataMode(SPI_MODE0);

You might need to modify that for the Due. It requires the slaveSelectPin parameter. You might be able to set each SPI slave select device with its own mode in setup instead of switching back and forth.

Thanks for your reply SurferTIM!!

I have changed the mode only at initialisation of the RTC in setup()...but maybe i have to change the mode every time i want to access the RTC!?

I will test this at the evening and report it here... c.u. then! 8)

I'm not experienced with the Due SPI, so you may have to play with it a bit. Let us know if you get it working and how.

soooo...my assumption is probably right, that the Ethernet Shield in combination with DUE does not provide SPI (Miso, Mosi, clk) on Pin 11,12,13
-> i soldered the three SPI wires of the RTC directly to the SPI soldering points of the Ethernet Shield and: IT WORKS!! :slight_smile:

Further it works also together with Ethernet, BUT if the SD.h gets included the SD and RTC may be working, but the SD may affect the Ethernet functionality
-> set SPI mode0 everytime before using Ethernet: SPI.setDataMode(SPI_MODE0);
....its not working with SPI.setDataMode(10, SPI_MODE0) .. which was surprising to me (because of the extended SPI functionality of DUE)

so, finally, here is my code for testing:

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

#define rtc_pin 52 //chip select
#define sd_pin 4

Sd2Card card;
SdVolume volume;
SdFile root;

byte mac[] = {0x00,0x01,0xDA,0x0D,0x02,0x03};
byte ip[] = {x,x,x,x};
byte gw[] = {x,x,x,x};
byte DNS[] = {208,67,222,222}; //Open DNS Server
byte DNS2[] = {8,8,4,4}; //Google DNS Server
byte subnet[] = {255,255,255,0};
    
void setup() {
  Serial.begin(9600);
}

void loop() {
 if (Serial.available() > 0) {
   
    int incomingByte = Serial.read();
    
    if ((incomingByte) == 'a') {
      RTC_init();
      Serial.print("RTC inizialized..."); }
    
    else if ((incomingByte) == 's') {
      SetTimeDate(11,12,13,14,15,16); //day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
      Serial.println("time set"); }
    
    else if ((incomingByte) == 'd') {
        Serial.println(ReadTimeDate());}
    
    else if ((incomingByte) == 'g') { 
      Ethernet.begin(mac, ip, DNS, gw, subnet);
      Serial.print("W5100 initialized"); }
    
    else if ((incomingByte) == 'h') Upload();

    else if ((incomingByte) =='j') SDTest();
   }
}

  //===================================================================================
void Upload () {

  SPI.setDataMode(SPI_MODE0);
  
  EthernetClient client1;
  
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  Serial.print("connecting...");

  client1.connect("www.arduino.cc", 80);
  if (client1.connected()) {
    Serial.print("connected");
    // send the HTTP PUT request:
    client1.println("GET /latest.txt HTTP/1.1");
    client1.println("Host: www.arduino.cc");
    client1.println("User-Agent: arduino-ethernet");
    client1.println("Connection: close");
    client1.println();
   
  }else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting...");
    client1.stop();
  }
}

  //=====================================
int RTC_init(){ 
	  pinMode(rtc_pin,OUTPUT); // chip select

	  // start the SPI library:
	  SPI.begin();
	  SPI.setBitOrder(MSBFIRST); 
	  SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work 
	  //set control register 
	  digitalWrite(rtc_pin, LOW);  
	  SPI.transfer(rtc_pin,0x8E);
	  SPI.transfer(rtc_pin,0x60); //60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled
	  digitalWrite(rtc_pin, HIGH);
	  delay(10);
}
//=====================================
int SetTimeDate(int d, int mo, int y, int h, int mi, int s){ 
    int TimeDate [7]={s,mi,h,0,d,mo,y};
	for(int i=0; i<=6;i++){
		if(i==3)
			i++;
		int b= TimeDate[i]/10;
		int a= TimeDate[i]-b*10;
		if(i==2){
			if (b==2)
				b=B00000010;
			else if (b==1)
				b=B00000001;
		}	
		TimeDate[i]= a+(b<<4);
		  
		digitalWrite(rtc_pin, LOW);
		SPI.transfer(rtc_pin,i+0x80); 
		SPI.transfer(rtc_pin,TimeDate[i]);        
		digitalWrite(rtc_pin, HIGH);
  }
}
//=====================================
String ReadTimeDate(){
	String temp;
	int TimeDate [7]; //second,minute,hour,null,day,month,year		
	for(int i=0; i<=6;i++){
		if(i==3)
			i++;
		digitalWrite(rtc_pin, LOW);
		SPI.transfer(rtc_pin,i+0x00); 
		unsigned int n = SPI.transfer(rtc_pin,0x00);        
		digitalWrite(rtc_pin, HIGH);
		int a=n & B00001111;    
		if(i==2){	
			int b=(n & B00110000)>>4; //24 hour mode
			if(b==B00000010)
				b=20;        
			else if(b==B00000001)
				b=10;
			TimeDate[i]=a+b;
		}
		else if(i==4){
			int b=(n & B00110000)>>4;
			TimeDate[i]=a+b*10;
		}
		else if(i==5){
			int b=(n & B00010000)>>4;
			TimeDate[i]=a+b*10;
		}
		else if(i==6){
			int b=(n & B11110000)>>4;
			TimeDate[i]=a+b*10;
		}
		else{	
			int b=(n & B01110000)>>4;
			TimeDate[i]=a+b*10;	
			}
	}
	temp.concat(TimeDate[4]);
	temp.concat("/") ;
	temp.concat(TimeDate[5]);
	temp.concat("/") ;
	temp.concat(TimeDate[6]);
	temp.concat("     ") ;
	temp.concat(TimeDate[2]);
	temp.concat(":") ;
	temp.concat(TimeDate[1]);
	temp.concat(":") ;
	temp.concat(TimeDate[0]);
  return(temp);
}


  //===================================================================================
void SDTest() {
  File myFile;
  SD.begin(sd_pin);
  
    // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, sd_pin)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is inserted?");
    Serial.println("* Is your wiring correct?");
    Serial.println("* did you change the sd_pin pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present."); 
  }
  
    // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
  
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize *= 512;                            // SD card blocks are always 512 bytes
  Serial.print("Volume size (bytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  
  Serial.print("\nOpening File...");
  
  myFile = SD.open("test.txt", FILE_WRITE);
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
	// close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  Serial.print("\nReading File...");
  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
    	Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);
  
  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
  
  SPI.end(sd_pin);
 
}

important: The RTC must be initialized every time after using another SPI (Ethernet, SD)!!

That code is not what I would use. The SD and w5100 should be initialized in setup(), not loop(). Set it, and forget it. Same with the RTC.

Once you get all set correctly, you should end up like this user:
http://forum.arduino.cc/index.php?topic=172871.0

yes, i know... firstly iam a "programming" beginner, thats why iam using Arduino and secondly the code was written just for testing the SPI functionality...
Anyway in my understanding there is no difference for the µC to execute comands in setup() or loop()... isnt the only difference that once is executed once at startup and another in loop mode?
Also in main.cpp there is "just" a code like this:

int main(void)
{
      init();

      setup();
    
      for (;;)
            loop();
        
      return 0;
}

However, for me it was confusing with the old Ethernet-SD Shield, the new "extended SPI" of DUE and RTC, which didnt work on Pin 11,12,13....
and maybe another Beginner can benefit from the code
I think the SPI.setDataMode(SPI_MODE0) trick should be implemented in Ehternet.h

...and that main(void) stays in the loop() function forever.

Har har! The "pirate's code" only applies to pirates, and they are only guidelines. :wink:

It is up to YOU to initialize your devices correctly. The SPI bus has 4 modes. Set it incorrectly, and "Remember the Hindenburg!" Oh, the humanity!!