Reading MAX31865

Guys,
I have 15 MAX31865s on a board with a 1284P chip and TI TXB0106 chips for level converters.
I can't seem to get any response back from the chip, I'm just talking to 1 right now, with hooks in the code to expand to 15 later.
All 15 are in place, wired up for 2-wire conversion of PTD1000 probes.
Here's the code and the results I am getting. Any ideas?

/*  
 Code to read 15 MAX31865 RTD chips via ATMega1284P & send data out via Serial port using FTDI chip.
 TI TXB0108 used for 5V to 3.3V conversion of SCK, MOSI, CSx going out, and 3.3V to 5V conversion on MISO coming back
 RTD1000 probe with 4K Rref resistor, 10nF Cl.
 
 Only access 1 device for now
 */

#include <SPI.h>

// declare chip selects
// 0, 1 are serial pins
/*
byte ss0 = 10; // 10 as output for SPI Master mode
 byte ss1 = 7;
 byte ss2 = 6;
 byte ss3 = 5;
 byte ss4 = 4;
 byte ss5 = 21;
 byte ss6 = 20;
 byte ss7 = 19;
 byte ss8 = 18;
 // 11, 12, 13 are SPI pins
 byte ss9 = 17;
 byte ss10 = 16;
 byte ss11 = 15;
 byte ss12 = 14;
 byte ss13 = 29;
 byte ss14 = 28;
 */

byte SSarray[] = {
  10,7,6,5,4,21,20,19,18,17,16,15,14,29,28}; // slave select pins. See Bobuino pins_arduino.h & schematic

// 2,3,8,9,22,23,24,25,26,27,30,31 not used. Set up as inputs with pullup resistors for power savings

//declare variables
// registers
byte config_read = 0x00; 
byte config_write = 0x80;
byte RTD_MSB_read = 0x01;
byte RTD_MSB_write = 0x81; // not a valid register address
byte RTD_LSB_read = 0x02;
byte RTD_LSB_write = 0x82; // not a valid register address
byte High_Fault_Threshold_MSB_read = 0x03; // 83h FFh R/W
byte High_Fault_Threshold_MSB_write = 0x83;
byte High_Fault_Threshold_LSB_read = 0x04; // 84h FFh R/W
byte High_Fault_Threshold_LSB_write = 0x84;
byte Low_Fault_Threshold_MSB_read = 0x05; // 85h 00h R/
byte Low_Fault_Threshold_MSB_write = 0x85;
byte Low_Fault_Threshold_LSB_read = 0x06; // 86h 00h R/W
byte Low_Fault_Threshold_LSB_write = 0x86;
byte Fault_Status_write = 0x87; // not a valid register address
byte Fault_Status_read = 0x07; // 00h R

byte Readarray[120] ; // 8 x 15 RTDs, start on 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112

byte x=0; // chip counter
byte y=0; // register counter
byte incomingByte1;
byte incomingByte2;
byte incomingByte3;
byte incomingByte4;
unsigned long currentMillis;
unsigned long previousMillis;
unsigned long elapsedMillis;
//unsigned long duration = 55; // conversion time, milliseconds
unsigned long interval = 100UL; // Set longer for debug, keep PC serial port from getting swamped

void setup(){
  // set up output pins
  for (x=0; x<15; x=x+1){
    pinMode(SSarray[x], OUTPUT);  // set Slave Select pins as outputs
  }

  Serial.begin(115200);

  // SPI mode changes
  SPI.setDataMode(SPI_MODE1); // choices 0,1,2,3 - use 1,3 for MAX31865
  SPI.setBitOrder(MSBFIRST); // choices LSBFIRST, MSBFIRST - use MSBFIRST for MAX31865
  SPI.setClockDivider(SPI_CLOCK_DIV16); // choices 2,4,8,16,32,64,128.  2 = 8 MHz, 4 = 4 MHz, 8 = 1 MHz, etc.  5 MHz max for MAX31865
  SPI.begin(); // 

  x=0; // setup "chip pointer" x for use later, eventually loop thru 15 MAX31865 chips
} // end setup

void loop(){

  // send write address, data to start a conversion
  digitalWrite (SSarray[x], LOW); 
  SPI.transfer(config_write);  // send out register #
  delayMicroseconds(10);  // see if slight delay between write & read  helps
  SPI.transfer(0b10100010); // send out data: 
  // 7 1 = bias on, 
  // 6 0 = conversion mode off
  // 5 1 = start a conversion
  // 4 0 = 2 wire mode
  // 3,2 0, 0 = no action
  // 1 1 = clear faults in status register 
  // 0 0 = 60 Hz filter
  digitalWrite(SSarray[x], HIGH);

  delay(500); // wait for conversion - 500mS

  // send read address, read the data
  digitalWrite (SSarray[x], LOW); 
  SPI.transfer(RTD_MSB_read);  // send out register #
  delayMicroseconds(10);
  incomingByte1 = SPI.transfer(0); // read register contents back
  digitalWrite(SSarray[x], HIGH);


  // send write address, data
  digitalWrite (SSarray[x], LOW); 
  SPI.transfer(RTD_LSB_read);  // send out register #
  delayMicroseconds(10);
  incomingByte2 = SPI.transfer(0); // read register contents back
  digitalWrite(SSarray[x], HIGH);

  // send write address, data
  digitalWrite (SSarray[x], LOW); 
  SPI.transfer(Fault_Status_read);  // send out register #
  delayMicroseconds(10);
  incomingByte3 = SPI.transfer(0); // read register contents back
  digitalWrite(SSarray[x], HIGH);

  // send write address, data to start a conversion
  digitalWrite (SSarray[x], LOW); 
  SPI.transfer(config_read);  // send out register #
  delayMicroseconds(10);
  incomingByte4 = SPI.transfer(0); // read register contents back
  digitalWrite(SSarray[x], HIGH);

  // show the data
  Serial.print("MSB ");
  Serial.print(incomingByte1, HEX);
  Serial.print("  LSB ");
  Serial.print(incomingByte2, HEX);
  Serial.print("  Fault ");
  Serial.print(incomingByte3, HEX);
  Serial.print("  Config ");
  Serial.println(incomingByte4, HEX);

  delay(200); // wait for conversion
} // end loop
[code]

[/code]

MAX31865.pdf (1.53 MB)

txb0106.pdf (748 KB)

Results

MSB 0 LSB FF Fault 0 Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config 0
MSB FF LSB 0 Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault 0 Config 0
MSB 0 LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB 0 Fault 0 Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB 0 LSB 0 Fault FF Config 0
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB FF LSB FF Fault FF Config FF
MSB 0 LSB FF Fault 0 Config FF

Somewhat a repeating pattern but not really.

I'm positive when I started testing I was seeing 400mV across the probe connections, now its 0.
Must have something hosed in the config_write data I am sending.
Damn this is aggravating.
Had saleae probes on both side of the TXB0106, can see clock, enable, and MOSI going, MISO coming back just looks to sit high most of the time tho.

Schematic and a picture of the card

bump - late night posting got dropped too early.

It sounds as if you may have a fundamental problem preventing SPI communication. Perhaps it would be worth moving to a minimal sketch that just tries to read a single register from a single card, and see if you can get sensible data from it. Getting back anything except 0x00 and 0xff would be a good start, but (if SPI works) you ought to be able to write to a config register and then read back the same config. Other than that I don't know what to suggest. There are only so many pins involved in SPI and so many options to configure it, and I guess you have tried them all by now. I think you're at the point where I'd be reaching for a logic analyser to see what's actually happening on the SPI interface.

PeterH,
this Is that minimal sketch.
The results I get back make no sense - why does it read back all FFs most of the time, but then appear to periodically return something that almost makes sense? I've already had the saleae analyzer on it making sure the signals & data were making it thru the TXB0106 level translater. Everything seems to be toggling as expected with the correct data on MOSI, except SDO from the chip, the line is just high most of the time.

Just occurred to me - wonder if MISO is being driven the floating output of the uC and not changing direction when the MAX31865 starts driving? Maybe I can put a weak pullup on the MAX31865 side so the uC side is an output all the time?

What does the analyzer show on the MAX31865 side? With 8 channels you should be able to hook onto both sides of the level converter and confirm it is working properly.

It only shows the 3.3V MISO as sitting high almost all the time.
Every 32 to 36 reads it shows some non-FF data, but it doesn't look like anything valid, see the non-FF data above, about every 11-12th group.
SCK, MOSI, Chip Selects look good, 3.3V output mimics the input. MISO, just high generally on both sides per the Saleae.

I gotta get to bed - let me know if you think pulling MISO high on the 3.3V side with 10K or something will make the TXB0106 think the MAX31865 side is always driving. MAX only has 1.6mA drive current.
I'll try scoping the signal too (busy tomorrow night, high school graduation stuff coming up, big day is Sunday) see if its doing anything or if I'm just kidding myself. No test points, have to re-attach the probe wires I put on on the 3.3V side, they got pulled off.
I really wasn't expecting this much trouble from this chip combination!

Hmm:
Pullup or Pulldown Resistors on I/O Lines
The TXB0106 is designed to drive capacitive loads of up to 70 pF. The output drivers of the TXB0106 have low
dc drive strength. If pullup or pulldown resistors are connected externally to the data I/Os, their values must be
kept higher than 50 k? to ensure that they do not contend with the output drivers of the TXB0106.
For the same reason, the TXB0106 should not be used in applications such as I2C or 1-Wire where an opendrain driver is connected on the bidirectional data I/O. For these applications, use a device from the TI TXS01xx
series of level translators.

When SPI is not active MISO is not driven by either side - maybe I have a race condition kind of thing going?
Need to get a scope on those lines next I guess.

Did you ever got i working?

No, has been aside for a bit. Looking to get back to it later this weekend, get it finished up so I can move on to other things.

I have ben trying to get mine working but i am stuck, would you post your code if you get it working?

Can do. Not sure mine is totally a code problem, might be a hardware buffering issue as well.

After reading the entire post, it seams like we have the same problem, so we might as well try and help each other. What do you mean by a buffer problem?

I used TXB0108 for the level converters. I have 15 chips that each receive the SCK and MOSI signals, and drive the MISO signal. Each gets its own CS signal. I didn't put any pads to monitor the signals, so have been struggling with finding a place to attach a logic analyzer or oscilloscope as well.

So far i found out that there is a problem with your level converter, i use the same one, but can not get data running ether way, so i went to try with a simple voltage divider instead and then a pull up for the MISO (Master In Serial Out) the MAX31865 apparently can only pull the channel low so as far as i found out, no matter what you do you need a pull up on that pin.

I am getting two friends over in the weekend (electronic engineers) and we will try getting the level converter running and refining the code, i will post the code for you after the weekend and make a proper schematic also so you can see the difference between our code/hardware

I just got a good digital scope (200 MHz/4 channel), will be looking at signals one of these nights or this weekend, see what is going on.
I suspect lack of drive capability from the MAX31865 Data Out to the TXB0106. If signals bear that out, will try bypassing the TXB0106 and go direct from MAX31865 to MISO on 1284.
I have 15 chips ganged on MISO and SCK/MOSI going the other way and 1284P should have plenty of drive to put SCK/MOSI & 15 Chip selects thru.

Just read this on page 10 in the TXB0106 datasheet, bottom 3 lines:
For the same reason, the TXB0106 should not be used in applications such as I2C or 1-Wire where an open- drain driver is connected on the bidirectional data I/O. For these applications, use a device from the TI TXS01xx series of level translators.

MAX31865 does not fall in that. However, it show 1.6mA of output - while TXB0106 shows needing 2mA to drive the inputs.

Progress!
I slowed SPI clock way down, rewired MOSI to go thru a 2.2K/4.7K voltage divider instead of going thru TXB0106, and am bringing MISO direct from the chips instead of coming back thru TXB0106.
Here's screen shots of the 3.3V signals SCK MISO, chip select, MOSI.
These are reads from several of the registers, with data similar to this:

Write Register 80 Write Value FF
Read Register 0 Read Value F1
Read Register 1 Read Value 97
Read Register 2 Read Value FA
Read Register 3 Read Value FF
Read Register 4 Read Value FF
Read Register 5 Read Value 0
Read Register 6 Read Value 0

Read Register 0 Read Value D1
Read Register 1 Read Value 98
Read Register 2 Read Value 0
Read Register 3 Read Value FF
Read Register 4 Read Value FF
Read Register 5 Read Value 0
Read Register 6 Read Value 0

Read Register 0 Read Value D1
Read Register 1 Read Value 99
Read Register 2 Read Value D4
Read Register 3 Read Value FF
Read Register 4 Read Value FF
Read Register 5 Read Value 0
Read Register 6 Read Value 0

Read Register 0 Read Value D1
Read Register 1 Read Value 9A
Read Register 2 Read Value A2
Read Register 3 Read Value FF
Read Register 4 Read Value FF
Read Register 5 Read Value 0
Read Register 6 Read Value 0

Haven't figured out what to write to the registers yet, and these readings are with probe freshly placed in front of my laptop exhaust fan and warming up.

The code is kind of klugdy, but it does let me write any value from 0x00 to 0xFF into any of the 7 registers.

/*  
 Code to read 15 MAX31865 RTD chips via ATMega1284P & send data out via Serial port using FTDI chip.
 TI TXB0106 used for 5V to 3.3V conversion of SCK, MOSI, CSx going out, and 3.3V to 5V conversion on MISO coming back
 RTD1000 probe with 4K Rref resistor, 10nF Cl.
 
 Only access 1 device for now
 
 USAGE: w100 to w1FF, w600 to w6FF
 r1 to r6
 */

#include <SPI.h>

// 0, 1 are serial pins

byte SSarray[] = {
  10,7,6,5,4,21,20,19,18,17,16,15,14,29,28}; // slave select pins. See Bobuino pins_arduino.h & schematic

//declare variables
// registers
byte config_read = 0x00; 
byte config_write = 0x80;
      // 7 1 = bias on, 
      // 6 0 = conversion mode off
      // 5 1 = start a conversion
      // 4 0 = 2 wire mode
      // 3,2 0, 0 = no action
      // 1 1 = clear faults in status register
      // 0 0 = 60 Hz filter
byte RTD_MSB_read = 0x01;
byte RTD_MSB_write = 0x81; // not a valid register address
byte RTD_LSB_read = 0x02;
byte RTD_LSB_write = 0x82; // not a valid register address
byte High_Fault_Threshold_MSB_read = 0x03; // 83h FFh R/W
byte High_Fault_Threshold_MSB_write = 0x83;
byte High_Fault_Threshold_LSB_read = 0x04; // 84h FFh R/W
byte High_Fault_Threshold_LSB_write = 0x84;
byte Low_Fault_Threshold_MSB_read = 0x05; // 85h 00h R/
byte Low_Fault_Threshold_MSB_write = 0x85;
byte Low_Fault_Threshold_LSB_read = 0x06; // 86h 00h R/W
byte Low_Fault_Threshold_LSB_write = 0x86;
byte Fault_Status_write = 0x87; // not a valid register address
byte Fault_Status_read = 0x07; // 00h R

byte Readarray[120] ; // 8 x 15 RTDs, start on 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112

byte x=0; // chip counter
byte y=0; // register counter
byte incomingByte;
byte incomingByte1;
byte incomingByte2;
byte incomingByte3;
byte incomingByte4;
unsigned long currentMillis;
unsigned long previousMillis;
unsigned long elapsedMillis;
//unsigned long duration = 55; // conversion time, milliseconds
unsigned long interval = 100UL; // Set longer for debug, keep PC serial port from getting swamped

byte regHi;
byte regLo;
byte regNo;
byte valueHi;
byte valueLo;
byte value;
byte command;
byte hiNib;
byte loNib;

void setup(){
  // set up output pins
  for (x=0; x<15; x=x+1){
    pinMode(SSarray[x], OUTPUT);  // set Slave Select pins as outputs
    digitalWrite (SSarray[x],  HIGH); // set Slave Select pins high
  }

  Serial.begin(115200);

  SPI.begin(); //
  // SPI mode changes
  SPI.setDataMode(SPI_MODE1); // choices 0,1,2,3 - use 1,3 for MAX31865
  //SPI.setBitOrder(MSBFIRST); // choices LSBFIRST, MSBFIRST - use MSBFIRST for MAX31865
  SPI.setClockDivider(SPI_CLOCK_DIV128); // choices 2,4,8,16,32,64,128.  2 = 8 MHz, 4 = 4 MHz, 8 = 1 MHz, etc.  5 MHz max for MAX31865


  x=0; // setup "chip pointer" x for use later, eventually loop thru 15 MAX31865 chips
/*  // test for CS probe connectivity
  while(1){
    digitalWrite(SSarray[x], LOW);
    delayMicroseconds(10);
    digitalWrite(SSarray[x], HIGH);
    delayMicroseconds(10);
  }
  */
} // end setup

void loop(){
  if (Serial.available()>1){
    command = Serial.read(); // read the command

      if (command == 'w'){
      if (Serial.available()){
        incomingByte = Serial.read();   // read the register
        switch (incomingByte){
        case '0':
          regNo = 0x80;
          break;
        case '1':
          regNo = 0x81;
          break;
        case '2':
          regNo = 0x82;
          break;
        case '3':
          regNo = 0x83;
          break;
        case '4':
          regNo = 0x84;
          break;
        case '5':
          regNo = 0x85;
          break;
        case '6':
          regNo = 0x86;
          break;
        }

        Serial.print ("Write Register ");
        Serial.print (regNo, HEX);
       Serial.print (" ");

        incomingByte = Serial.read(); // read the high nibble
        switch (incomingByte){
        case '0':
          hiNib = 0x00;
          break;
        case '1':
          hiNib = 0x10;
          break;
        case '2':
          hiNib = 0x20;
          break;
        case '3':
          hiNib = 0x30;
          break;
        case '4':
          hiNib = 0x40;
          break;
        case '5':
          hiNib = 0x50;
          break;
        case '6':
          hiNib = 0x60;
          break;
        case '7':
          hiNib = 0x70;
          break;
        case '8':
          hiNib = 0x80;
          break;
        case '9':
          hiNib = 0x90;
          break;
        case 'a':
          hiNib = 0xA0;
          break;
        case 'b':
          hiNib = 0xB0;
          break;
        case 'c':
          hiNib = 0xC0;
          break;
        case 'd':
          hiNib = 0xD0;
          break;
        case 'e':
          hiNib = 0xE0;
          break;
        case 'f':
          hiNib = 0xF0;
          break;
        }
        incomingByte = Serial.read(); // read the low nibble
        switch (incomingByte){
        case '0':
          loNib = 0x00;
          break;
        case '1':
          loNib = 0x01;
          break;
        case '2':
          loNib = 0x02;
          break;
        case '3':
          loNib = 0x03;
          break;
        case '4':
          loNib = 0x04;
          break;
        case '5':
          loNib = 0x05;
          break;
        case '6':
          loNib = 0x06;
          break;
        case '7':
          loNib = 0x07;
          break;
        case '8':
          loNib = 0x08;
          break;
        case '9':
          loNib = 0x09;
          break;
        case 'a':
          loNib = 0x0A;
          break;
        case 'b':
          loNib = 0x0B;
          break;
        case 'c':
          loNib = 0x0C;
          break;
        case 'd':
          loNib = 0x0D;
          break;
        case 'e':
          loNib = 0x0E;
          break;
        case 'f':
          loNib = 0x0F;
          break;
        }
      }

      value = hiNib+loNib;
      Serial.print ("Write Value ");
      Serial.println (value, HEX);

      // send write address, data to start a conversion
      digitalWrite (SSarray[x], LOW); 
      digitalWrite (SSarray[x], LOW);
      SPI.transfer(regNo);  // send out register #
      delayMicroseconds(10);  // see if slight delay between write & read  helps
      SPI.transfer(value); // send out data: 
      digitalWrite(SSarray[x], HIGH);
    }
    if (command == 'r'){
      //regHi = Serial.read() - 0x30;
      //regLo = Serial.read() - 0x30;
      //regNo = (regHi <<4) + regLo;

      //valueHi = Serial.read() - 0x30;
      //valueLo = Serial.read() - 0x30;
      //value = (valueHi <<4) + valueLo;
      if (Serial.available()>0){
        incomingByte = Serial.read();   // read the register
        switch (incomingByte){
        case '0':
          regNo = 0x00;
          break;
        case '1':
          regNo = 0x01;
          break;
        case '2':
          regNo = 0x02;
          break;
        case '3':
          regNo = 0x03;
          break;
        case '4':
          regNo = 0x04;
          break;
        case '5':
          regNo = 0x05;
          break;
        case '6':
          regNo = 0x06;
          break;
        }
      }
      Serial.print ("Read Register ");
      Serial.print (regNo, HEX);
      Serial.print (" ");
  }
} // end loop

DS0005.BMP (1.37 MB)

DS0006.BMP (1.37 MB)