SPI woes - Ethernet shield vs. everything else

I would be very grateful if the forum could help me to a better insight into how SPI works and, in particular, why I am failing to get my set up to behave. This is the hardware stack that I am trying to get to work:

5" TFT display with SPI-connected flash chip
Display shield
Ethernet shield (1 or 2)
SD card on the Ethernet board
Arduino Due

The library stack is
#include <SPI.h>
#include <SdFat.h>
#include <Ethernet.h> (or #include <Ethernet2.h>)
#include <ICMPPing.h>
#include <UTFT.h>
#include <UTFT_GHL.h>

The Ethernet connection receives asynchronous UDP data for the intended application. The application then processes the data, saves stuff to the SD card and writes information to the display using fonts obtained from the flash chip. I am using the Ethernet library (or the Ethernet2 library for the v2 card) and SdFat. The flash chip uses the UTFT_GHL library. There are, therefore, three users of the SPI: Ethernet, SD card and flash chip.

It doesn't work!

To try to narrow down the problem I wrote a simple app that pings Google via the Ethernet card, reads/writes/deletes files on the SD card and writes stuff to the display in a continuous loop. I'm happy to post this code if it will help.

What happens?

Each of the SPI interfaces works fine on its own. If I run the Ethernet and SD card together, as soon as I do anything with the SD card the Ethernet interface dies so conclusively that it hangs the entire machine when the next ping is sent. The same thing happens if I run Ethernet with Flash font screen printing. The only combination that does work is SdFat R/W/D and UTFT_GHL reading the flash to get its fonts.

Anecdotally the Ethernet card doesn't play nicely with other things on the SPI and my experience seems to be adding to that sorry tale. It seems to me that this is something that it ought to be possible to fix once and for all but I am no expert when it comes to the innards of these drivers/libraries and am a relatively recent convert to programming in C. So I am appealing to those with greater knowledge and experience than me to help out with this one.

Any insight gratefully received!

Thanks in advance.

John.

I hope you get to the bottom of this, as no doubt in the future I am likely to get 'my ethernet shield doesn't work with UTFT_GHL' ..... :confused:

Regards,

Graham

Update:

After a lot of Googling, I came to the perhaps mistaken conclusion that the SPI library for Due might be different to that for, e.g. Mega 2560. I decided to try my code on a 2560. Lo and behold, Ethernet and SdFat happily coexist.

Unfortunately I do not have a Mega-compatible shield for the display, so I can't easily test that interface. As the UTFT_GHL/SdFat combination works on the Due, I suspect it will on the Mega.

My application really needs the processing power of the Due, otherwise I'd be tempted to just go with the Mega and be done with it.

So, is there a different SPI library for the Due? And if so, where can I get it?

Thanks in advance

John.

johnlinford:
As the UTFT_GHL/SdFat combination works on the Due, I suspect it will on the Mega.

Yes John, it does.

Regards,

Graham

Thanks Graham.

It seems that none of the forum experts can find a barge pole long enough to convince them that it's safe to engage on this issue. That's a shame - it seems that SPI is both poorly understood and poorly implemented in many cases.

Someone out there will know the answer and it would be great if they would come forward. Meanwhile I shall continue to look at other options.

John.

Final attempt to stir up some response :smiley: Here is the test code I am using...

#define SD_CS_PIN 4
#include <SPI.h>
#include <SdFat.h>
//#include <SD.h>
#include <Ethernet.h>
#include <ICMPPing.h>
#include <UTFT.h>
#include <UTFT_GHL.h>

bool SDInitialised=false;
SdFat SD;
File myFile;

bool EthernetInitialised=false;
IPAddress pingAddr(8,8,8,8); // ip address to ping
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0xB4, 0x9A}; // MAC address for ethernet shield
SOCKET pingSocket = 0;
char buffer [256];
ICMPPing ping(pingSocket, (uint16_t)random(0, 255));

bool TFTInitialised=false;
UTFT myGLCD(CPLD,25, 26, 27, 28);
UTFT_GHL CTE_LCD(&myGLCD);

int Count;

void setup() {
  Serial.begin(115200);
  delay(500);
  //pinMode(4, OUTPUT);   //Makes no difference
  //pinMode(10, OUTPUT);  //Ethernet doesn't initialise if this is enabled
  //pinMode(52, OUTPUT);  //Makes no difference
  //pinMode(53, OUTPUT);  //Makes no difference

  Serial.println("Initialising display...");
  myGLCD.InitLCD();
  myGLCD.setBackColor(VGA_BLACK);
  CTE_LCD.SPI_Flash_init(FLASH_CS_PIN);
  myGLCD.clrScr();
  TFTInitialised=true;

  Serial.println("Initialising SD card...");
  if (SD.begin(SD_CS_PIN)) {
    Serial.println("SD card initialised OK");
    SDInitialised=true;
    }
  else {
    Serial.println("SD card initialisation failed");
    }

  Serial.println("Initialising Ethernet...");
  if (Ethernet.begin(mac)) {
    Serial.println("Ethernet initialised OK");
    EthernetInitialised=true;
    }
  else {
    Serial.println("Ethernet initialisation failed");
    }

  Count=0;
  }

void loop() {
  Count++;

  //Send ping request
  //The ping is just a convenient way of testing whether the Ethernet interface is still working. 
  Serial.println();
  Serial.println("Ping request");
  ICMPEchoReply echoReply = ping(pingAddr, 4);
  if (echoReply.status == SUCCESS) {
    sprintf(buffer,
            "Ping reply[%d] from: %d.%d.%d.%d: bytes=%d time=%ldms TTL=%d",
            echoReply.data.seq,
            echoReply.addr[0],
            echoReply.addr[1],
            echoReply.addr[2],
            echoReply.addr[3],
            REQ_DATASIZE,
            millis() - echoReply.data.time,
            echoReply.ttl);
    }
  else {
    sprintf(buffer, "Ping request failed; %d", echoReply.status);
    }
  Serial.println(buffer);
  delay(500);  
    
  //Write file
  Serial.println("Write to SD");
  myFile = SD.open("test.txt", FILE_WRITE);
  if (myFile) {
    myFile.print("Test data, loop count=");
    myFile.println(Count);
    myFile.close();
    }
  delay(500);

  //Display stuff
  Serial.println("Write to display");
  CTE_LCD.Put_Text("Test data, loop count=",10,200,BVS_34);
  CTE_LCD.Put_Text(String(Count)+"    ",400,200,BVS_34);
  delay(500);

  //Read the file
  Serial.println("Read file from SD");
  myFile = SD.open("test.txt", FILE_READ);
  if (myFile) {
    while (myFile.available()) {
      Serial.write(myFile.read());
      }
    myFile.close();
    }  
  delay(500);

  //Delete the file
  Serial.println("Delete file on SD");
  SD.remove("test.txt");
  delay(500);  
  }

And here is the serial port display

Initialising display...
Initialising SD card...
SD card initialised OK
Initialising Ethernet...
Ethernet initialised OK

Ping request
Ping reply[0] from: 8.8.8.8: bytes=64 time=14ms TTL=128
Write to SD
Write to display
Read file from SD
Test data, loop count=1
Delete file on SD

Ping request

...at which point it dies. Either SD card activity or writing to the display kills the Ethernet.

Still hoping someone might be able to help...

Thanks

John.

Hi John,

mmm I am not sure if you have already tried and removed it, or if you only partially implemented my suggestion?

I see all of your pinMode definitions, now commented out, but I don't see your corresponding digitalWrite(pin, HIGH) commands?

eg :-

  pinMode(4, OUTPUT);   //Makes no difference
  digitalWrite(4, HIGH);
  pinMode(10, OUTPUT);  //Ethernet doesn't initialise if this is enabled
  digitalWrite(10, HIGH);
  pinMode(52, OUTPUT);  //Makes no difference
  digitalWrite(52, HIGH);
  pinMode(53, OUTPUT);  //Makes no difference
  digitalWrite(53, HIGH);

?

Regards,

Graham

Hi Graham,

Yes I did try setting all the pins high but the problem remains unchanged. The only pin that makes any difference is setting pin 10 to output. That just kills the Ethernet card immediately, at initialisation, regardless of whether I then set the pin to high...

Initialising display...
Initialising SD card...
SD card initialised OK
Initialising Ethernet...

...and it's dead.

John.

Hi John,

Ok.

Specifically which Ethernet cards do you have, and which ethernet library are you using?

G

I have the standard "Ethernet R3" shield and I've also tried the "Ethernet Shield 2". Both behave in exactly the same way. The library is the one installed with the Arduino 1.6.8 IDE. Version 1.1.2 according to the library.properties file and that seems to be the current version on GitHub.

J.

AHA.....

Maybe worth trying this one then, since it mentions now works at SPI 42Mhz, which is also oddly enough what the Font IC runs at....

G

Disappointing! Exactly the same results with the WIZ library. I have checked that the new library is definitely being compiled in (via a Serial.print within the library) and I've configured it per the instructions to use the R3 Ethernet shield. I have yet to try it on the Ethernet 2 shield but it's not looking promising.

I must be doing something stupid but I cannot for the life of me work out what it is.

J.

** Update: exactly the same results with the Ethernet 2 card. :frowning:

I am running out of ideas.....

Oh by the way, after my lengthy reply to your lengthy reply, STM32 stuff..... there will very soon be a DUE replacement with almost the exact hardware!! Now THAT will be nice.... do a search for Arduino Star OTTO.

G

Thanks for trying Graham. The Star OTTO (what an odd name) does indeed look interesting, as does the EtherDue (if I can ever get a reply from the supplier). No doubt each will bring all sorts of new things that don't quite work as expected...

Is this 5 inch TFT using RA8875?

The RA8875 has a known problem where it can not tri-state its MISO pin. A separate tri-state buffer is usually required if the RA8875 is used together with any other SPI chips.

Sometimes it can work, when another chip also drives MISO, but the result is an incorrect voltage for logic high and low, so whether it works depends on the MISO receiver circuitry in your Arduino. I've heard reports of 2 RA8875 (but not 3) working on Mega, but failing on Teensy 3.2. No idea about Due.

Star Otto looks like powerful hardware, but it's made by that "other" Arduino. Maybe it'll turn out to be an awesome product, but given their dismal performance on the software side so far (mostly copying everything from Ardiuno.cc with only minor tweaks), might be best to take a wait-and-see approach. The market is already filled with extremely powerful STM32-based boards that don't have good Arduino compatibility.

Hi Paul,

No, John is not using RA8875, it is 5" CPLD.

The problem I gather you are already aware of in passing, SdFat/Ethernet and SPI issues. John and I have been in communication with this issue, but I suggested he contact you directly as your understanding of the SPI library for DUE is clearly much better than mine.

The problem John is having is getting sdfat and ethernet to co-exist, since UTFT_GHL uses the same DMA code used by sdfat, it stands to reason my library will cause the same fatal error. But WHAT is the problem? Are you aware of any way (with transactions or otherwise) of getting Ethernet to not die during a SdFat file write?

We have already tried digitalPin(Ethernet_CS, HIGH); before an SD operation and digitalPin(SD_CS, HIGH) before any ethernet operations, but to no avail, that I am afraid is where my SPI knowledge ends...

Hope you can shed some light on this issue!?

Thanks!

Regards,

Graham

Maybe try using SD instead of SdFat?

Ok Thank you.

That doesn't really get to the bottom of the problem, but since nobody appears to want to I guess I am not surprised.

Regards,

Graham

Hi Paul,

Thank you for engaging with us on this. As Graham says, I have the CTE CPLD display and use UTFT_GHL to drive it. I have tried SD and it does indeed work OK with Ethernet. That's what I was originally using but it still leaves the issue of getting the display flash to work as well.

It's still not clear to me whether the issue is in the Ethernet library or in SdFat/UTFT_GHL. I suppose Graham could try using the SD SPI interface code instead.

Regards,

John.

ghlawrence2000:
That doesn't really get to the bottom of the problem

What if the problem is a resource conflict between SdFat and one of these other libs? If using SD makes things work, why can you accept that as a solution?

Or do you expect "get to the bottom of the problem" to involve someone actually digging into the low-level details of these libs and editing them to work together?

I regularly do that for Teensy boards, but I'm not going to do it for Arduino Due. Maybe someone from Arduino who supports Due might be interested in such work?