Created Tue, 30 Apr 2013 14:06:49 +0000 by Jacob Christ
Tue, 30 Apr 2013 14:06:49 +0000
I recently changed the SD examples from something like this:
const int chipSelect = 8;
void setup() { Serial.begin(9600); Serial.print("\nInitializing SD card..."); pinMode(10, OUTPUT); // change this to 53 on a mega
to something like this (changed literal 10 to chipSelect):
const int chipSelect = 8;
void setup() { Serial.begin(9600); Serial.print("\nInitializing SD card..."); pinMode(chipSelect, OUTPUT); // change this to 53 on a mega
Talking with one of the guys I work with, he thinks that the pin 10 output is set to make sure the library works when you use the code with some Arduino boards. So I was thinking about changing it to something like this:
const int chipSelect = 8; // CS pin for SD card const int slaveSelect = 8; // Slave Select line (maybe same as CS or different)
void setup() { Serial.begin(9600); Serial.print("\nInitializing SD card..."); pinMode(chipSelect, OUTPUT); pinMode(slaveSelect, OUTPUT);
Any thoughts or suggestions?
Jacob
Thu, 02 May 2013 17:27:35 +0000
Here is a conversation between Keith (from Digilent) and myself on this topic...
Keith:
I looked at the schematics for an Arduino UNO at http://arduino.cc/en/uploads/Main/arduino-uno-schematic.pdf, you will notice that PIN10 is the CS line that is routed for external SPI CS control as well as to the CS on the Arduino SPI connector. Also notice that the chipKIT Uno32 does the same thing. Pin 10 is sort of the defacto SPI CS for Arduino SPI devices.
HOWEVER, for example, the WiFi shield has 2 SPI devices on it, the WiFi module AND the SD card; and they BOTH share SPI2. So they both could be used at the same time; 2 different CS had to be picked. By default the WiFi module got the typical pin10 CS signal that Arduino uses for most SPI devices; but the SD card got pin4, not the standard Arduino CS for a single SPI device. The assumption is… there very likely could be a second and shared SPI device on the standard Arduino SPI port and you need to make sure you DON’T select it while using the non-standard SD card. You can’t have the other CS line just float. So you want to explicitly hold that other SPI device’s CS HIGH (Deselected).
Now, for chipKIT and because of the WiFi Shield, we really should have code that looks like…
pinMode(4, OUTPUT); // CS for the SD Card on a WiFi Shield
digitalWrite(4, HIGH); // Start off deselected
pinMode(10, OUTPUT); // Standard Arduio CS, used by the WiFi module on a WiFiShield
digitalWrite(10 HIGH); // Start off deselected
Fortunately, both the SD and DWIFIcK libraries initialize deselected; but if you are not using one of the libraries AND you are using a WiFiShield, setting the pin as an OUTPUT WITHOUT setting it HIGH can be a real problem. It is better to leave it as an INPUT (tri-stated; do nothing) as there are pullup resistors on the WiFiShield to hold the devices deselected. But if you set it as an output, that pin gets driven and you might drive it LOW (selected) So if you are going to set pin 10 as an output, set it high too to deselect the WiFi module.
In general, Digilent has put all of the chipKIT SD card readers on CS pin 4 and leaving open the Arduino SPI capabilities on CS pin 10. And in general, the WiFi module is on pin10, Hmmm… maybe we should have moved that to a different CS pin as well… well, it is what it is…
Slave Select to me is when you are acting as a Slave, so this would be an INPUT not an OUTPUT. I do not think your second solution is correct. I think when using the SD card, I would just add:
pinMode(10, OUTPUT); // Standard Arduio CS, used by the WiFi module on a WiFiShield
digitalWrite(10 HIGH); // Start off deselected
to turn any other shared SPI device (such as the WiFi module or other defacto Arduino SPI usage) OFF and DESELECTED. In general, putting nothing in for the WiFiShield is fine, but you don’t know what other people have put on the Arduino SPI ports and if they have pull up resistors or not. So it would always be safe to define pin10 as an output as long as you drive it high.
Jacob:
Thanks Keith... Your right I meant SD, too many things floating around in my head.
I see where the problem comes from.
So my goal in modifying the examples is of course to make it easier to get an SD card up and running for a new user. I've been writing a lab for the Fubarino SD for using the SD and when you run through all the SD examples they need to be modified in different ways from example to example. This would be the same if you were using a Uno32 or a Max32. So I was just trying to get all the examples to be consistent.
I only modified the PIC32 SD examples, didn't touch the Arduino ones at this time.
So rather than chipSelect and slaveSelect variables, maybe:
const int chipSelect_SD_default = 10; // Make 10 on Uno and 53 on a Mega (Maybe this should be an ifdef for detecting board type) const int chipSelect_SD_mine = chipSelect_SD_default; // can be changed if you do not use default CS pin
and in setup()
pinMode(chipSelect_my_SD, OUTPUT);
digitalWrite(chipSelect_my_SD, HIGH);
pinMode(chipSelect_default_SD, OUTPUT);
digitalWrite(chipSelect_default_SD, HIGH);
Keith:
And you already caught the slight error in my response, clearly the defacto default for the Mega is pin 53 not pin 10. Also I should point out that we (Digilent) are coming out with a board where the SD CS will NOT be on pin 4. We actually dedicated signals to the SD and the WiFi so they would not share the SPI port (and thus get rid of the interrupt problem with the WiFi SPI implementation). Which brings us to your second observation/suggestion. Somehow we need to have a board definition for some of these common signals, maybe in the variants file? We are now producing boards with SPI stuff on them, and hard wire signals; and I think there is a clean defacto standard for Arduino for the Uno and Mega, so I would be in favor of some kind of Default_SPI_CS in the variants; and IF the board has resources on it like SD or WiFi we should have some standard names for them as well like WiFi_SPI_CS or SD_SPI_CS. We also need to add something if SPI interrupts are going to be used like with the WIFI MRF24.
So here is a half-baked suggestion….
Let’s say in the variants Board_Defs .h you had:
#define Default_SPI_CS 10 // or 53 in a mega board
#define Default_SPI_PORT SPI2CON
#define WIFI_SPI_CS 10
#define WiFi_SPI_PORT SPI2CON
#define SD_SPI_CS 4
#define SD_SPI_PORT SPI2CON
#define ALL_SPI_INT EXTERNAL_1_IRQ // the WiFi SPI INT, if another INT is used for another SPI port, OR it in here
In your sketch code you could have some nasty thing like:
#ifdef Default_SPI_CS
pinMode(Default_SPI_CS, OUTPUT);
digitalWrite(Default_SPI_CS, HIGH);
#endif
#ifdef WIFI_SPI_CS
pinMode(WIFI_SPI_CS, OUTPUT);
digitalWrite(WIFI_SPI_CS, HIGH);
#endif
#ifdef SD_SPI_CS
pinMode(SD_SPI_CS, OUTPUT);
digitalWrite(SD_SPI_CS, HIGH);
#endif
And then in Sd2Card.cpp we could have something like:
//------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh(void) {
digitalWrite(chipSelectPin_, HIGH);
#if
#if defined (ALL_SPI_INT)
if(fspi_state_saved)
{
SD_SPI_PORT = spi_state;
fspi_state_saved = false;
restoreIntEnable(ALL_SPI_INT, interrupt_state);
}
#endif
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow(void) {
#if defined (ALL_SPI_INT)
if(!fspi_state_saved)
{
interrupt_state = clearIntEnable(ALL_SPI_INT);
spi_state = SD_SPI_PORT;
SPI2CONbits.ON = 0;
fspi_state_saved = true;
}
#endif
digitalWrite(chipSelectPin_, LOW);
}
Thu, 02 May 2013 17:32:42 +0000
Keith,
I like your idea of having some defines per board that identify pins and ports... But I prefer something like this:
#define SPI_CS_Default 10
#define SPI_PORT_Defualt SPI2CON
#define SPI_CS_WiFi 10
#define SPI_PORT_WiFi SPI2CON
#define SPI_CS_SD 4
#define SPI_PORT_SD SPI2CON
#define SPI_INT_ALL EXTERNAL_1_IRQ // the WiFi SPI INT, if another INT is used for another SPI port, OR it in here
Jacob
Fri, 03 May 2013 17:25:43 +0000
Look good to me.... Make it so!
Sat, 25 May 2013 05:26:08 +0000
I just implemented this:
const int chipSelect_SD_default = 10; // Make 10 on Uno and 53 on a Mega const int chipSelect_SD = chipSelect_SD_default;
// ... and in setup()
pinMode(chipSelect_SD, OUTPUT);
digitalWrite(chipSelect_SD, HIGH);
pinMode(chipSelect_SD_default, OUTPUT);
digitalWrite(chipSelect_SD_default, HIGH);
But didn't want to attack the board_def.h yet.