SPI Help

The EtherDue combines a super powerful 84MHz Cortex M3 with onboard ethernet connectivity. Dual Micro USB, a MicroSD card slot, switchmode power supply. 100% Arduino Due compatible. [Product Page]
Post Reply
ghare
Posts: 3
Joined: Wed Jul 30, 2014 9:19 am

SPI Help

Post by ghare » Wed Jul 30, 2014 9:27 am

Hi,

I am trying to use my EtherDue with an SPI thermocouple (MAX31855) which is read only, using SCK, MISO and Pin 53 as _CS. On it's own, this works great!

I am trying to write the data from the thermocouple to a microSD. The microSD uses Pin 4 as _CS. Again, on it's own this works great, I can read and write to the card.

When I try to use them together, the SD initialises, but when I try to read the thermocouple, the data seems to get stomped all over?????

Help!

angusgr
Freetronics Staff
Freetronics Staff
Posts: 853
Joined: Tue Apr 09, 2013 11:19 pm
Location: Melbourne, Australia
Contact:

Re: SPI Help

Post by angusgr » Wed Jul 30, 2014 11:44 pm

Hi ghare,

The most likely cause here, as you probably guessed, is one of the CS lines not de-asserting (being driven high) when talking to the other device.

Can you please post the sketch that you are using? (Use the

Code: Select all

 tags to format it correctly). Also if you're not already using it I suggest updating to Arduino 1.5.6, the earlier versions had some problems with multiple SPI devices on Due (I saw it with Ethernet & SD concurrently, but it could have also been a problem with other combinations).

Does the SD card work properly if you take the thermocouple out of the equation?

Regards,


Angus

ghare
Posts: 3
Joined: Wed Jul 30, 2014 9:19 am

Re: SPI Help

Post by ghare » Thu Jul 31, 2014 5:54 am

Angus,

I am already using 1.5.6-r2.

Here is the SD code (just the standard example) However, I did note that if I transposed the SD and SPI header includes, the code breaks. i.e. card doesn't initialise.

Code: Select all

/*
  SD card datalogger

 This example shows how to log data from three analog sensors
 to an SD card using the SD library.

 The circuit:
 * analog sensors on analog ins 0, 1, and 2
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

 created  24 Nov 2010
 modified 9 Apr 2012
 by Tom Igoe

 This example code is in the public domain.

 */

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

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(4, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}

Here is the code for the thermocouple interface...

Code: Select all

/* MAX31855 Thermocouple Interface for Extruder temperature control */

#include <SPI.h>

const unsigned int error = 0x0001; // LSB - Error indicator
const unsigned int sign = 0x8000; // MSB - Sign bit of temperature
const unsigned int temp = 0x7FFC; // 14 bit temperature mask

const int _CS = 53;

void setup()

{
  Serial.begin(9600); // Start the serial channel for debugging
  
  SPI.begin(_CS); // Start the SPI channel to talk to MAX31855
  
  pinMode(_CS, OUTPUT); // Setup the _CS pin for the MAX31855 as an output  
}

void loop()

{
  getTemp();
  delay(1000); 
}

void getTemp()

{
  unsigned int result = readMAX(); // read raw data from MAX31855
  
  if((result & error) == error)
    Serial.println("Error with sensor");
  else
  {
    Serial.print("Temp [C] = ");
    Serial.println((float) ((result & temp) >> 2)/4, 2);
  }
}

unsigned int readMAX()

{
  unsigned int result = 0; // result to return
  
  digitalWrite(_CS, LOW); // Pull _CS Low to enable MAX31855
  result = SPI.transfer(0x00) << 8; // Send an 0x00 and read result back
  result = result | SPI.transfer(0x00);
  digitalWrite(_CS, HIGH); // Pull _CS High to disable MAX31855
  return(result);
}
On there own, both of the above work fine.

The following code is the logger I'm writing

Code: Select all

/* MAX31855 Thermocouple Interface for Extruder temperature control

MISO : D12
SCK : D13
_csTC : D4

*/

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

const unsigned int error = 0x0001; // LSB - Error indicator
const unsigned int sign = 0x8000; // MSB - Sign bit of temperature
const unsigned int temp = 0x7FFC; // 14 bit temperature mask

const int _csTC = 53;
const int csSD = 4;

void setup()

{
  Serial.begin(9600); // Start the serial channel for debugging
  
  pinMode(csSD, OUTPUT);
  pinMode(_csTC, OUTPUT); // Setup the _csTC pin for the MAX31855 as an output  

  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  
  // see if the card is present and can be initialized:
  if (!SD.begin(csSD)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  
  SPI.begin(_csTC); // Start the SPI channel to talk to MAX31855

}

void loop()

{
  // make a string for assembling the data to log:
  String dataString = "";

  dataString += String(getTemp());

  File dataFile = SD.open("PID.log", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening PID.log");
  } 

  delay(1000); 
}

float getTemp()

{
  unsigned int result = readMAX(); // read raw data from MAX31855
  
  if((result & error) == error)
    Serial.println("Error with sensor");
  else
  {
    Serial.print("Temp [C] = ");
    Serial.println((float) ((result & temp) >> 2)/4, 2);
    return (float) ((result & temp) >> 2)/4;
  }
}

unsigned int readMAX()

{
  unsigned int result = 0; // result to return
  
  digitalWrite(_csTC, LOW); // Pull _csTC Low to enable MAX31855
  result = SPI.transfer(0x00) << 8; // Send an 0x00 and read result back
  result = result | SPI.transfer(0x00);
  digitalWrite(_csTC, HIGH); // Pull _csTC High to disable MAX31855
  return(result);
}

The code runs fine, but the first byte being read from the MAX31855 is getting corrupted, resulting in temperature of 1000+ degrees instead of 20ish degrees.

The SD card is being written to and the file reads fine, it just contains the wrong temp??

Cheers,

George

angusgr
Freetronics Staff
Freetronics Staff
Posts: 853
Joined: Tue Apr 09, 2013 11:19 pm
Location: Melbourne, Australia
Contact:

Re: SPI Help

Post by angusgr » Thu Jul 31, 2014 6:06 am

Hi George,

I think you may need to drive the thermocouple interface CS pin high immediately after you set it as an output:

Code: Select all

pinMode(_csTC, OUTPUT); // Setup the _csTC pin for the MAX31855 as an output 
digitalWrite(_csTC, HIGH);
Because otherwise as an output it's defaulting to low (asserted), and then when you call SD.begin() the MAX31855 is also enabled for the duration of that SD initialisation sequence, which probably causes it to get into a bad state.


- Angus

ghare
Posts: 3
Joined: Wed Jul 30, 2014 9:19 am

Re: SPI Help

Post by ghare » Thu Jul 31, 2014 7:52 am

Angus,

Tried putting a manual digitalWrite in various places with no luck.

However I have solved the problem in a really UGLY way. I have created a 'throw-away' variable and do an additional SPI transfer before I assert my TC chip select line low. Seems to clear the corrupt data and I get my 2 bytes of temperature data.

Code: Select all

unsigned int readMAX()

{
  unsigned int dummy = 0;
  unsigned int result = 0; // result to return
  
  digitalWrite(csSD, HIGH);
  dummy = SPI.transfer(0xFF);
  digitalWrite(_csTC, LOW); // Pull _csTC Low to enable MAX31855
  result = SPI.transfer(0x00) << 8; // Send an 0x00 and read result back
  result = result | SPI.transfer(0x00);
  digitalWrite(_csTC, HIGH); // Pull _csTC High to disable MAX31855
  return(result);
}

I think the problem is probably somewhere in the backend of the SD code. I've noticed there is no SD.end function along the lines of the SPI.end but I don't have time at the moment to delve into the code to find it. My fix will work for getting the data I need to finish my Master's.

Cheers,

George

Post Reply