Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by DaveWithASatellite on Tue Mar 05, 2013 5:22 pm

Hello,

I am having problems using SPI to communicate with two SPI devices: the adafruit micro-SD card breakout board+ and a YEI 3-Space Sensor Embedded (Inertial Measurement Unit / Attitude & Heading Reference System).

Hardware setup:
Arduino UNO R3 http://arduino.cc/en/Main/ArduinoBoardUno
Micro-SD Card Breakout Board+ http://www.adafruit.com/products/254
3-Space Sensor Embedded (3SS) http://tech.yostengineering.com/3-space-sensor/product-family/embedded
Image
Image
Image

1. Micro-SD Card Breakout Board+ & Arduino:
I have followed the very helpful tutorial provided through adafruit, http://www.ladyada.net/products/microsd/, and can get the Arduino to successfully run all of the example programs provided in the new SD library.

2. 3-Space Sensor Embedded & Arduino:
The 3SS is a complex beast, but I can get it working perfectly with the Arduino SPI library: sending commands and receiving data. It would be best to think of this as a black box, outside of the SPI interface. It operates by receiving commands (from Arduino) and sending data in full duplex. I have this code if necessary.

3. Micro-SD Card Breakout Board+, 3-Space Sensor Embedded & Arduino:
I essentially combined the above two programs into this "end game" program, while making sure the setup remains correct according to each of the requirements. Right off the bat, the program showed itself to be very finicky and prone to stop running in the first loop or having one of the two SPI devices not run/return data. I have tried a myriad of options, hacks and suggestions found through Arduino, adafruit, and other sources; but they are not worth listing unless the topic comes up in the future.
Here is the code:
Code: Select all
/*
  IMUData2SDcard
  Get the 3-axis accelerometer and 3-axis gyroscope data from the IMU
  using SPI then save the results in a file on the microSD card.
  Uses the SPI and SD library.
 
  Hardware Setup
       Arduino   SDcard   TSS-EM
        pin 7              SS
        pin 10    SS
        pin 11    MOSI     MOSI
        pin 12    MISO     MISO
        pin 13    SCK      SCK
 
  created 03/01/2013
  by David Hughes
*/

#include <SPI.h>
#include <SD.h>
 
/* Pins used for SPI connection */
const int chipSelectPinIMU = 7;
const int chipSelectPinSDcard = 10;
// the rest are controlled by the SPI library

/* Union for each of the 9 sensors */
// Needed to convert the bytes from SPI to float
union u_types {
    byte b[4];
    float fval;
} data[9];  // Create 9 unions, one for each sensor from the IMU
            //   Gyroscope: x-axis, y-axis, z-axis
            //   Accelerometer: x-axis, y-axis, z-axis
            //   Compass: x-axis, y-axis, z-axis

/* File object */
File myFile;

/* Initialization */
void setup() {
  Serial.begin(9600);
 
  // Start the SPI library:
  digitalWrite(chipSelectPinIMU, HIGH);
  SPI.begin();
  // Set the chip select pin for IMU:
  pinMode(chipSelectPinIMU, OUTPUT);
 
  Serial.print(F("Initializing SD card..."));
  // Set the chip select pin for the SDcard board:
  pinMode(chipSelectPinSDcard, OUTPUT);
  // Initialize the SDcard and library
  if (!SD.begin(chipSelectPinSDcard)) {
    Serial.println(F("initialization failed!"));
  } else {
    Serial.println(F("initialization done."));
  }
 
  // Give the sensor time to set up:
  delay(1000);
}

// Debugging code, to check usage of RAM
// Example Call: Serial.println(freeRam());
//int freeRam () {
//  extern int __heap_start, *__brkval;
//  int v;
//  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
//}

/* Main Loop */
void loop() {
  Serial.print(F("Sending packet..."));
  // Take the chip select low to select the device:
  digitalWrite(chipSelectPinIMU, LOW);
  // Clear the internal data buffer on the IMU
  SPI.transfer(0x01);
  delay(10);
  // Send start of packet:
  SPI.transfer(0xF6);
  delay(1);
  // Send command:
  SPI.transfer(0x40);
  delay(1);
  // Get status of device:
  byte result = SPI.transfer(0xFF);
  while (result != 0x01) {  // Repeat until device is Ready
    delay(1);
    result = SPI.transfer(0xFF);
  }
  // Get the 36 bytes of return data from the device:
  for (int ii=0; ii<9; ii++) {
    for (int jj=0; jj<4; jj++) {
      data[ii].b[jj] = SPI.transfer(0xFF);
      delay(1);
      Serial.print("data[");
      Serial.print(ii);
      Serial.print("].b[");
      Serial.print(jj);
      Serial.print("]: ");
      Serial.println(data[ii].b[jj],HEX);
    }
  }
  // Take the chip select high to de-select:
  digitalWrite(chipSelectPinIMU, HIGH);
  Serial.println(("Packet send/receive complete."));
 
  // Convert Big Endian (IMU) to Little Endian (Arduino)
  for( int mm=0; mm<9; mm++) {
    endianSwap(data[mm].b);
  }
  Serial.println(F("Data endian swap complete."));
 
  // Traverse the union to print the data values
  Serial.println(F("Gyroscope:"));
  for (int kk=0; kk<9; kk++) {
    Serial.print(data[kk].fval);
    if (kk == 2) {
      Serial.println("");
      Serial.println(F("Acceleration:"));
    } else if (kk == 5) {
      Serial.println("");
      Serial.println(F("Compass:"));
    } else {
      Serial.println("");
    }
  }
 
  // Open the file. Note that only one file can be open at a time
  myFile = SD.open("test.txt", FILE_WRITE);
  // Write data to the file
  if (myFile) {  // if the file opened okay, write to it:
    Serial.print(F("Writing to test.txt..."));
    // Traverse the union to print the data values
    myFile.println("Gyroscope:");
    for (int kk=0; kk<9; kk++) {
      myFile.print(data[kk].fval);
      if (kk == 2) {
        myFile.println("");
        myFile.println("Acceleration:");
      } else if (kk == 5) {
        myFile.println("");
        myFile.println("Compass:");
      } else {
        myFile.println("");
      }
    }
    myFile.close();  // close the file
    Serial.println(F("Write to file complete."));
  } else {
    // if the file didn't open, print an error:
    Serial.println(F("error opening test.txt"));
  }
  myFile.println("");
 
  delay(5000);  // Wait x/1000 seconds before next loop
}

/* Endian swap - big to little */
inline void endianSwap(byte temp[4]) {
//  Serial.println("Before swap: ");
//  Serial.println(temp[0],HEX);
//  Serial.println(temp[1],HEX);
//  Serial.println(temp[2],HEX);
//  Serial.println(temp[3],HEX);
  byte myTemp = temp[0];
  temp[0] = temp[3];
  temp[3] = myTemp;
  myTemp = temp[1];
  temp[1] = temp[2];
  temp[2] = myTemp;
//  Serial.println("After swap:  ");
//  Serial.println(temp[0],HEX);
//  Serial.println(temp[1],HEX);
//  Serial.println(temp[2],HEX);
//  Serial.println(temp[3],HEX);
}

Currently, I suspect it is a problem or conflict between the SPI and SD libraries. I have not been able to sort how these two libraries are related to each other, I had originally thought the SD supersedes the SPI library. In this 3rd program, 3SS & SD board & Arduino, the SD card communication/writing is working as it should while the communication with the 3SS looks to be scrambled.
Here picture of the data returned from the 3SS during operation of the 3SS & Arduino program, which shows how the correct data should be received (nicely organized in 4 bytes):
Image
Here is a picture of the data returned from the 3SS during operation of the above program, 3SS & SD board & Arduino, which shows the incorrect byte-stream:
Image

My initial conclusion was based on this line of reasoning, in that there is a conflict between the libraries. Could they be in conflict with initializing the SPI twice? What is the SPI "mode" of the adafruit board, defined as clock polarity (CPOL) and clock phase (CPHA)? [3SS is CPOL=0, CPHA=0.]

I am happy to include more information, or clarification, on any of the above information. We hope to hear back soon and look forward to finding a solution to this problem.

Thank you.
DaveWithASatellite
 
Posts: 6
Joined: Tue Mar 05, 2013 2:22 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by adafruit_support_bill on Wed Mar 06, 2013 6:05 am

Sounds like it could be interference with SPI operations, or possibly a memory issue. Memory problems are unpredictable, but tend to be more catastrophic than what you are seeing.
Taking a quick look at the SD library source code, I don't see where it includes the SPI library. I suspect it may do it's own SPI communication. Maybe there is some incompatibility with the SPI lib.

If you are using Adafruit's SD library, there is a "Soft SPI" option. Just supply the pin numbers to SD.begin. That should avoid any conflict with the hardware SPI communication.
https://github.com/adafruit/SD
User avatar
adafruit_support_bill
 
Posts: 25556
Joined: Sat Feb 07, 2009 9:11 am

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by DaveWithASatellite on Fri Mar 08, 2013 4:09 pm

I tried the "Soft SPI" option, here is the change in code:

Code: Select all
  if (!SD.begin(chipSelectPinSDcard,11,12,13)) {  // chipSel, mosi, miso, sck
    Serial.println(F("initialization failed!"));
  } else {
    Serial.println(F("initialization done."));
  }

The result - the SD card failed to initialize and will not read/write.

Looks like the Soft SPI will not work within this program, and my guess would be due to the SPI library and its associated functions. If we go back to regular (non-Soft) SPI, the SD library functions will work but the SPI will not work with the external 3SS device (as seen in the pictures above).

I too noticed that the SD library does not include anything from the SPI library in its source code, which is somewhat baffling given the nature of the communication (SPI itself). Do you have any insight on this?

What can we try next?
Do you have any previous support or customers dealing with the SD library and the SPI library?

Thank you!
DaveWithASatellite
 
Posts: 6
Joined: Tue Mar 05, 2013 2:22 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by adafruit_support_bill on Fri Mar 08, 2013 5:23 pm

Sorry, I forgot to mention: To use the Soft-SPI, you need to pick different pins for the Soft-SPI device. The SPI library will want exclusive control of 11-13.
User avatar
adafruit_support_bill
 
Posts: 25556
Joined: Sat Feb 07, 2009 9:11 am

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by DaveWithASatellite on Sun Mar 10, 2013 3:25 pm

I will try this out as soon as I finish this post.

My main question is whether or not there is a problem with using the Arduino SPI library with the adafruit SD library. Is there any information about this specific setup - as in do you have documentation that this setup works, or this setup was never tested?

Our main concern is that we already have the circuit board custom-made, and making changes could be costly or not be available within our time frame. We did extensive research/searching to make the assumption that the two libraries would work (using the same hardware lines), but it was still an assumption that had to be made.

Thank you
DaveWithASatellite
 
Posts: 6
Joined: Tue Mar 05, 2013 2:22 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by adafruit_support_bill on Sun Mar 10, 2013 4:30 pm

I don't know that that combination has been tested. The Adafruit SD library is based on the Arduino SD library which is in turn based on sdfatlibby William Greiman (a.k.a. "fat16lib"). Interestingly, the Arduino SD reference page contains a link to the SPI library reference page, but it does not state they work together.
User avatar
adafruit_support_bill
 
Posts: 25556
Joined: Sat Feb 07, 2009 9:11 am

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by DaveWithASatellite on Tue Mar 12, 2013 11:35 am

I have also been working on this problem over at the Arduino forums website, which has been very helpful, but our testing points at the adafruit SD library as the problem. This discussion can be seen here: http://arduino.cc/forum/index.php/topic,153447.0.html. We are at a point where we need to do testing on the adafruit SD library, especially with the SPI library. The hard fact is that the original Arduino SD library does work with the SPI library. I'll admit, this could also be a red herring, but right now all checks/testing point to the adafruit SD library having a problem working with the SPI library for some unknown reason.

We would like to get adafruit's thoughts on this problem.

Thank you
DaveWithASatellite
 
Posts: 6
Joined: Tue Mar 05, 2013 2:22 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by adafruit on Wed Mar 13, 2013 1:20 pm

If the original Arduino SD library works, then you should use it
The only thing added to the Adafruit SD library is soft-spi support
if you dont need soft-spi just use the Arduino SD library which uses hardware SPI
there are 4 SPI mode, your library/code for this device may not use the same MODE bits as SD and it may set the mode and not reset it, causing problems. this is something you may need an experienced firmware programmer to go through and thoroughly test if you are going into manufacture
User avatar
adafruit
 
Posts: 11509
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by DaveWithASatellite on Tue Mar 19, 2013 4:59 pm

What is the MODE of the SD device?
DaveWithASatellite
 
Posts: 6
Joined: Tue Mar 05, 2013 2:22 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by DaveWithASatellite on Sun Mar 24, 2013 2:06 pm

I was able to get the SPI setup to work with both the microSD card breakout board+ and another SPI device. I stopped using the SD library, both the Arduino standard lib and the Adafruit lib, and moved over to the master SdFat library. The SD libraries were based off an early/old version of the SdFat library, so it made sense to use the most recent version of the library (SdFat).

The SdFat library is located for download at http://code.google.com/p/sdfatlib/downloads/list.

We made a few modifications to our Arduino programs, based on the provided examples with SdFat. After these small changes (include, definitions, functions calls) we were able to get the programs to run perfectly as intended!

I hope others will find this thread when they encounter this problem, and avoid the weeks of frustration involved with an old and outdated SD library.

Dave
DaveWithASatellite
 
Posts: 6
Joined: Tue Mar 05, 2013 2:22 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD Libraries

by cjosey on Sun Sep 08, 2013 10:26 pm

Dave,
I am currently struggling with getting SPI communications between the embedded 3-Space sensor to my Arduino Uno. I copied the code you show above into a sketch and modified it (to remove the SD card), but I am still having difficulties. Could I get a copy of your latest code? Thanks. (cjosey at mindspring dot com)

Carl
cjosey
 
Posts: 1
Joined: Sun Sep 08, 2013 10:18 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD L

by bvernham on Thu Nov 21, 2013 10:02 am

I am having the same issue.

I am trying the run a CAN shield and the Adafruit looger on the SPI together.

Everything work fine until I open a file.

Both the SD and the CAN initialize fine but as soon as I open a file the CAN can no longer be communicated with.

If I do not open a file, no problem.

I am not sure what mode the SD card is but I tried changing the spi setting to match the CAN Spi requirement before trying to read from the CAN controller but no help.

I CAN shield is using INT 0. If I do not open the file the interrupt is cleared by reading the message buffer in the CAN chip.

As soon as I open a file the ISR is visited 1 time and then done because the message buffers are not being cleared.

Any ideas?
bvernham
 
Posts: 4
Joined: Mon Nov 18, 2013 7:26 pm

Re: Arduino UNO, Micro-SD Card Breakout Board+, SPI and SD L

by adafruit_support_bill on Thu Nov 21, 2013 11:37 am

@bvernham - it sounds like it could be a memory problem: http://learn.adafruit.com/memories-of-an-arduino
User avatar
adafruit_support_bill
 
Posts: 25556
Joined: Sat Feb 07, 2009 9:11 am