Problems with SPI and Multiple Shields (Pins are not colliding)

So i have these components:

And im trying to stack them on top of each other. However i had to place the SCK, MISO, MOSI pins of the Gameduino at pin 50-52 (Where they are located).

The shields worked fine individually, all of the example codes worked terrific.
Then i attempted to stack the Gameduino 2 Display at the top of the Wifi Shield (Pin 50-52 still used for SPI)
At first, it didnt work, until i set Slave Select for Wifi before the initializing function for GD2 Library.

void setup() {
 pinMode(SSWiFi, OUTPUT);
 digitalWrite(SSWiFi, HIGH);
 GD.begin();
 :
 : <so on>
}

But, As soon as i use any of the functions (my normal tests uses WiFi.status() ) of the WiFi library, The screen stops completely.
When reading a bit in the Wifi Library code i found:

uint8_t WiFiDrv::getConnectionStatus()
{
	WAIT_FOR_SLAVE_SELECT();

    // Send Command
    SpiDrv::sendCmd(GET_CONN_STATUS_CMD, PARAM_NUMS_0);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = -1;
    uint8_t _dataLen = 0;
    SpiDrv::waitResponseCmd(GET_CONN_STATUS_CMD, PARAM_NUMS_1, &_data, &_dataLen);

    SpiDrv::spiSlaveDeselect();
 
    return _data;
}

What i can get from this, The Wifi Library should handle the SPI by itself, but i dont know how their solution for multiple stacking of shields would be. (Long time googlin’ hasnt helped at all).

The slave selects that exists are: GPU select, SD Select on Gameduino2; SD Select and SS WiFi on the Arduino WiFi Shield.

Basically my questions are:

  • How does the WiFi library handle the SPI and How do you use it with other Shields?
  • Is my SPI Setup strange in any kind of manner?
  • (Having the WiFi shield be connected to ICSP Header, and the Gameduino on Megas SPI Pin 50-53 )*
  • How does WiFi shield handle SPI on Mega ADK when its not even connected to the 50-53 pins.

In theory the setup should work. as no pins are colliding, both shields worked individually, when stacked the Display Worked when not using the Wifi.
Any kind of input would be gladly appritiated

Wifi shield has female header on the bottom that plugs onto ICSP header to pick up SCK, MISO, MOSI, and Reset/Gnd/Power. You can see it here next to the uC body.

CrossRoads:
Wifi shield has female header on the bottom that plugs onto ICSP header to pick up SCK, MISO, MOSI, and Reset/Gnd/Power.
You can see it here next to the uC body.

Thanks for a quick reply, but its not really the main issue
I knew that the ICSP Header was the connection for the WiFi shield, but how is that connected to the Pins 50-53? Are they two separate modules or are they linked together? Compared to that code worked with Both Shields i guess its linked. But the fact the Wifi shield isnt present when plugging in the Display doesnt make sense. I’ve checked at least 10 times and the pins are not colliding. Im not even calling code from the Display library.

ICSP header connects directly to SPI pins at 50-53. You can see that in the various board schematics on the Products page.

The shields worked fine individually, all of the example codes worked terrific. Then i attempted to stack the Gameduino 2 Display at the top of the Wifi Shield (Pin 50-52 still used for SPI) At first, it didnt work, until i set Slave Select for Wifi before the initializing function for GD2 Library.

Both in hardware and in software, you'll need to ensure that each SPI device has its own unique CS (Chip Select / Slave Select) control.

In theory the setup should work. as no pins are colliding, both shields worked individually, when stacked the Display Worked when not using the Wifi.

This suggests: 1. In software, the CS pin assignments may not be unique. 2. If the display CS is physically connected to the Wifi CS (when stacked), then one of them will need to be physically changed to another available pin.

dlloyd:

The shields worked fine individually, all of the example codes worked terrific. Then i attempted to stack the Gameduino 2 Display at the top of the Wifi Shield (Pin 50-52 still used for SPI) At first, it didnt work, until i set Slave Select for Wifi before the initializing function for GD2 Library.

Both in hardware and in software, you'll need to ensure that each SPI device has its own unique CS (Chip Select / Slave Select) control.

In theory the setup should work. as no pins are colliding, both shields worked individually, when stacked the Display Worked when not using the Wifi.

This suggests: 1. In software, the CS pin assignments may not be unique. 2. If the display CS is physically connected to the Wifi CS (when stacked), then one of them will need to be physically changed to another available pin.

1 The chip select pins are not modified in software.

2 The only chip selects in the Display is 8 & 9. The wifi Shield uses 10, 4 for CS, there is no stacked CS. However if the fact is that i cannot use any pin at all if the SS is not selected, then that would explain some things.

On the Mega, PB0, 53, must be set to an output even if not used for SS. That tells the Mega that is SPI master. If left as an input and it goes low, the Mega goes into SPI slave mode.

If you have any doubt, disable all SPI devices before starting any of them. After that, you should be able to start them in any order you want.

void setup() {
 // disable wifi SPI
 pinMode(SSWiFi, OUTPUT);
 digitalWrite(SSWiFi, HIGH);

 // disable wifi shield SD SPI
 pinMode(4, OUTPUT);
 digitalWrite(4, HIGH);

 // disable GD GPU SPI
 pinMode(8, OUTPUT);
 digitalWrite(8, HIGH);

 // disable GD SD SPI
 pinMode(9, OUTPUT);
 digitalWrite(9, HIGH);
  
 // now start the SPI devices
 GD.begin();
 :
 : <so on>
}

OK, so there's 5 SPI devices and it looks like there's no hardware conflicts:

Summary:

[b]CS Pin   Name      Board[/b]
D53      SS        Mega SPI master/salve (set as output for master) (reply#6)
D8       GPU SEL   Display
D9       SD SEL    Display
D4       SD SS     Wifi Shield
D10      Wifi      Wifi Shield

EDIT: Reply#7 is the correct method for CS control.

CrossRoads:
On the Mega, PB0, 53, must be set to an output even if not used for SS. That tells the Mega that is SPI master. If left as an input and it goes low, the Mega goes into SPI slave mode.

pinMode(53, OUTPUT);
I’ve did that as well, read it from the Arduino Website, However i was confused if there was a need to connect a cable to 53. As is already has a connection to the WiFi shield by the ICSP Header I assume it handles it already, since it worked previously with all devices.


SurferTim:
If you have any doubt, disable all SPI devices before starting any of them. After that, you should be able to start them in any order you want.

void setup() {

// disable wifi SPI
pinMode(SSWiFi, OUTPUT);
digitalWrite(SSWiFi, HIGH);

// disable wifi shield SD SPI
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);

// disable GD GPU SPI
pinMode(8, OUTPUT);
digitalWrite(8, HIGH);

// disable GD SD SPI
pinMode(9, OUTPUT);
digitalWrite(9, HIGH);
 
// now start the SPI devices
GD.begin();
:
:
}

That i havent tried yet. I usually just unplugged the power and inserted it again as i was seeing problems with that.


dlloyd:
OK, so there’s 5 SPI devices and it looks like there’s no hardware conflicts:

Summary:

[b]CS Pin   Name      Board[/b]

D53      SS        Mega SPI master/salve (set as output for master) (reply#6)
D8      GPU SEL  Display
D9      SD SEL    Display
D4      SD SS    Wifi Shield
D10      Wifi      Wifi Shield



I now suspect (see reply#6) or a software conflict with the two SD cards. At least that's somewhere to investigate ... especially if the drivers are compatible. Perhaps the CS signal for one SD card isn't pulled high before the other SD card is selected.

Hmm, there you actually said something. Since there are 4 SPI Devices, A viable solusion might be if i did a state changes before calling any library functions. I’ve only tried to enable/disable the Wifi and GPU.
so if i did this

void GD_enable() {
//disable The WiFi shield:
digitalWrite(SSWifiSD, HIGH);
//enable the slave of the WiFi
digitalWrite(SSWifi, LOW);
//enable GPU & Disable SD of Display -- Presumable since the the GPU start of by sending via the GPU Port, i think it remains in this state. the SD should be switched by the functions that are using the SD Card, So if the state is the same as the originally the functions should work then.
etc etc
}

void enable_wifi(){
 //Same logic, disable everything else except for how the states was before.
}
}

Or alternatively. A Shield handler class that would recognize the previous select states before switching. which would make a few operations more, but would be compatible with other libraries as well.

An enable function for when switching between the shields would be appropriate for the way i do my code.

Will try this when i go home.

All SPI device libraries I deal with manage their own slave selects once the SPI devices are started. The low level library functions pull the slave select LOW, do the read/write, and set it HIGH again when finished. There is no need for you to do that in your code.

The only no-no I know of is do not read or write to a SPI device during an interrupt. (edit: Meaning not in the ISR function itself.)

However i was confused if there was a need to connect a cable to 53. As is already has a connection to the WiFi shield by the ICSP Header I assume it handles it already, since it worked previously with all devices.

There is no SS on the ICSP header tho - Only SCK/MOSI/MISO and Reset/Pwr/Gnd. So if you're going to use 53 and the shield does not plug in the Mega dual-row header, then and jumper is needed to where SS is on the shield.

SurferTim: All SPI device libraries I deal with manage their own slave selects once the SPI devices are started. The low level library functions pull the slave select LOW, do the read/write, and set it HIGH again when finished. There is no need for you to do that in your code.

The only no-no I know of is do not read or write to a SPI device during an interrupt. (edit: Meaning not in the ISR function itself.)

the Display has a interrupt pin at Pin 2, which is connected to a shield. I have to read a bit more about it. Does most libraries handle interupts ? Does arduinos Wifi library do interupts for buffering or something? It might be very likely due to it has to monitor for packets? There must be a wait function till an interupt is free if im not mistaken.


CrossRoads:

However i was confused if there was a need to connect a cable to 53. As is already has a connection to the WiFi shield by the ICSP Header I assume it handles it already, since it worked previously with all devices.

There is no SS on the ICSP header tho - Only SCK/MOSI/MISO and Reset/Pwr/Gnd. So if you're going to use 53 and the shield does not plug in the Mega dual-row header, then and jumper is needed to where SS is on the shield.

So in this case, since WiFi SS is pin 10, I would have to do a jumper between 10 and 53? As its a shield for Uno and up, it doesnt connect to 53 in any way at the moment.

Since the shield has a SD card onboard, it probably does not use the interrupt to read/write. At least I hope not. That would cause a potential SPI bus collision. That would result in corrupted data at best and hardware damage at worst.

I'm definitely no expert on this, but from what I've been reading is that sometimes multiple operations get performed, like periodically certain file handling operations are automatically performed causing up to 250 ms latency on some SD drives.

So in this case, since WiFi SS is pin 10, I would have to do a jumper between 10 and 53? As its a shield for Uno and up, it doesnt connect to 53 in any way at the moment.

If the shields were all designed for an Uno, and you're using them on a mega, then you likely need to jumper 50-51-52 over to 11-12-13 (check the order). D4,8,9, and 10 can then be used as CS pins.

My experience has been that the Arduino libraries do not manage the SPI settings very well. Check to see if your devices have any SPI setting conflicts (mode, bit order, clock div). If so, you might have a library problem. The typical Arduino library sets the SPI settings in the begin() function and then assumes they never change.

This FAQ shows required connections. Note that there is a shield available that re-wires the pins.

This adapter also looks interesting:

  • ‘ADAM’ Arduino Display Adaptor Module
  • 4DLCD-FT843 Display
  • Arduino Mega Compatible

Sorry for bumping an old thread, but I believe I've found a workaround.

I recently got my first Gameduino2 and had the same issues when trying to use it with a WiFi shield. After reading this thread and doing some more digging of my own I found that pin 8 (GPU sel) is left HIGH LOW after calling any of the GD features. My workaround was to add a function to the GDClass, exposing the stop function in the transport class.

void GDClass::pause() {
 GDTR.stop();
}

I could then call GD.pause() after initialization and GD.resume() when I need to use the library. It's quite messy but it works.

With more knowledge about how the Gameduino operates it may be possible to integrate this in a better way, but I'm assuming the SPI is left open for performance reasons.

I hope this may help someone out there avoid the frustration I've felt.

After reading this thread and doing some more digging of my own I found that pin 8 (GPU sel) is left HIGH after calling any of the GD features.

If that is the SPI slave select, then it should be left HIGH after any operation. The slave select HIGH is SPI bus disabled for that device.