Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: SPI Bus only first declared chip select board reads properly.

  1. #1
    Junior Member
    Join Date
    Mar 2023
    Posts
    6

    SPI Bus only first declared chip select board reads properly.

    Using three MAX31865 boards to measure three different RTDs. Have them all hooked up on the same SPI bus. If I call them individually all three work flawlessly. When I try to put them all together on the first one I initialize works!


    In code below. If I comment out them individually they each work. But as shown, only the RTD board on Chip Select pin 8 works

    Code:
    #include <Adafruit_MAX31865.h>
    
    // Use software SPI: CS, DI, DO, CLK
    //Adafruit_MAX31865 thermo = Adafruit_MAX31865(8, 11, 12, 13);
    // use hardware SPI, just pass in the CS pin
    Adafruit_MAX31865 thermo = Adafruit_MAX31865(8);
    Adafruit_MAX31865 thermo2 = Adafruit_MAX31865(9);
    Adafruit_MAX31865 thermo3 = Adafruit_MAX31865(10);
    
    // The value of the Rref resistor. Use 430.0 for PT100 and 4300.0 for PT1000
    #define RREF      4300.0
    // The 'nominal' 0-degrees-C resistance of the sensor
    // 100.0 for PT100, 1000.0 for PT1000
    #define RNOMINAL  1000.0
    
    void setup() {
      Serial.begin(115200);
      Serial.println("Adafruit MAX31865 PT100 Sensor Test!");
    
    //  thermo.begin(MAX31865_4WIRE);  // set to 2WIRE or 4WIRE as necessary
      thermo2.begin(MAX31865_4WIRE);  // set to 2WIRE or 4WIRE as necessary
      thermo3.begin(MAX31865_4WIRE);  // set to 2WIRE or 4WIRE as necessary
      thermo.begin(MAX31865_4WIRE);  // set to 2WIRE or 4WIRE as necessary
    
    
    }
    
    
    void loop() {
      uint16_t rtd_debug1 = thermo.readRTD();
      float ratio1 = rtd_debug1;
      ratio1 /= 32768;
    
      uint16_t rtd_debug2 = thermo2.readRTD();
      float ratio2 = rtd_debug2;
      ratio2 /= 32768;
    
      uint16_t rtd_debug3 = thermo3.readRTD();
      float ratio3 = rtd_debug3;
      ratio3 /= 32768;
    
      Serial.println("Res1      Res2        Res3");
      Serial.print(RREF*ratio1,2);  Serial.print("    "); Serial.print(RREF*ratio2,2);  Serial.print("    "); Serial.println(RREF*ratio3,2);
      Serial.println("Temp1      Temp2        Temp3");
      Serial.print(thermo.temperature(RNOMINAL, RREF));  Serial.print("       "); Serial.print(thermo2.temperature(RNOMINAL, RREF));  Serial.print("       "); Serial.println(thermo3.temperature(RNOMINAL, RREF));
    
    
      // Check and print any faults
      uint8_t fault = thermo.readFault();
      if (fault) {
        Serial.print("Fault 0x"); Serial.println(fault, HEX);
        if (fault & MAX31865_FAULT_HIGHTHRESH) {
          Serial.println("RTD High Threshold"); 
        }
        if (fault & MAX31865_FAULT_LOWTHRESH) {
          Serial.println("RTD Low Threshold"); 
        }
        if (fault & MAX31865_FAULT_REFINLOW) {
          Serial.println("REFIN- > 0.85 x Bias"); 
        }
        if (fault & MAX31865_FAULT_REFINHIGH) {
          Serial.println("REFIN- < 0.85 x Bias - FORCE- open"); 
        }
        if (fault & MAX31865_FAULT_RTDINLOW) {
          Serial.println("RTDIN- < 0.85 x Bias - FORCE- open"); 
        }
        if (fault & MAX31865_FAULT_OVUV) {
          Serial.println("Under/Over voltage"); 
        }
        thermo.clearFault();
      }
      Serial.println();
      delay(1000);
    }

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,461
    You might want to look at this article Paul wrote some time ago:


    I found with doing Uncanny Eyes with two displays on the same SPI bus, I needed to add pull-up resistors for some displays. With other displays, pull-up registers did not work, but I suspect pull-down might have worked.

    The other issue might be having the proper tri-state capability.

  3. #3
    Senior Member brtaylor's Avatar
    Join Date
    Mar 2016
    Location
    Santa Fe, NM
    Posts
    841
    Sometimes helps to de-select all of the SPI devices before initializing them. Try adding this to the beginning of setup:

    Code:
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    digitalWriteFast(8, HIGH);
    digitalWriteFast(9, HIGH);
    digitalWriteFast(10, HIGH);
    Otherwise, agree that maybe the SPI devices are not tri-stating correctly.

  4. #4
    Junior Member
    Join Date
    Mar 2023
    Posts
    6
    thanks for the tips. No luck so far.
    Added 4.7kOhm pullup resistor to each chip select.
    Added a voltage divider to the MISO line.
    Added
    Code:
    SPI.endTransaction();
    calls to the end of each call to the chips.

    Nothing has worked so far.

  5. #5
    Senior Member
    Join Date
    Nov 2012
    Location
    Boston, MA, USA
    Posts
    1,135
    The voltage divider on MISO is a test, not a solution. What voltage did you measure?

    When all SPI chips are disabled, the MISO signal should “float” to approximately half the Vcc voltage. If any device is still driving the MISO line, you’ll see a logic high (usually close to 3.3V or 5.0V) or logic low (close to zero volts). This test is so easy, it should always be performed by designers of Arduino compatible products.
    If your SPI slave devices do not tristate correctly, you will need to add a tristate buffer such as SN74AHCT125. You can then drive the output enable pins to allow data to flow to the selected slave SPI device.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    28,473
    The MAX31865 seems to say the SDO pin does go high impedance when CS is high.

    Click image for larger version. 

Name:	screenshot.jpg 
Views:	12 
Size:	183.9 KB 
ID:	31037

    Still might be worthwhile to do the voltage divider test just to make sure MISO it really isn't being driven by anything while all the CS signals are high. But unless some other SPI device is connected, seems unlikely this is actual problem.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    28,473
    I ran the code from msg #1 on a Teensy 4.1 with no hardware connected, just to quickly look at the 3 chip select signals. Indeed it seems to be generating them on the 3 pins.

    Click image for larger version. 

Name:	file1.png 
Views:	8 
Size:	28.5 KB 
ID:	31038

    When I zoom in, looks like only 300ns from pin 8 high to pin 9 low.

    Click image for larger version. 

Name:	file2.png 
Views:	8 
Size:	29.2 KB 
ID:	31039

    Maybe this is fine, but as a quick and easy test, try adding delays before you read each sensor. I see inside the library Adafruit used delays of 10 and 65 ms, and they configure a slow 1 MHz clock. Perhaps these are pretty slow devices? Maybe such a short time is an issue? Just adding 10ms delays in the main program after attempting to read each sensor might be worth a quick try.

  8. #8
    Junior Member
    Join Date
    Mar 2023
    Posts
    6
    thanks for the help y'all. When I did the voltage divider it was sitting high, not floating...

    Looking back through the Adafruit_MAX31865 library which uses the Adafruit_SPIDevice library, I thought Paul found the problem. But additionally delays in the main code between thermo.readRTD() calls doesn't solve it.

    Code:
    /**************************************************************************/
    /*!
        @brief Read the raw 16-bit value from the RTD_REG in one shot mode
        @return The raw unsigned 16-bit value, NOT temperature!
    */
    /**************************************************************************/
    uint16_t Adafruit_MAX31865::readRTD(void) {
      clearFault();
      enableBias(true);
      delay(10);
      uint8_t t = readRegister8(MAX31865_CONFIG_REG);
      t |= MAX31865_CONFIG_1SHOT;
      writeRegister8(MAX31865_CONFIG_REG, t);
      delay(65);
    
      uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
    
      enableBias(false); // Disable bias current again to reduce selfheating.
    
      // remove fault
      rtd >>= 1;
    
      return rtd;
    }



    it seems the readRegister16 line (shown above) should also have delay after it as it calls this function from Adafruit_SPIDevice (shown below). Regardless adding delays in the main loop should resolve this...



    Code:
    bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer,
                                             size_t write_len, uint8_t *read_buffer,
                                             size_t read_len, uint8_t sendvalue) {
      beginTransactionWithAssertingCS();
      // do the writing
    #if defined(ARDUINO_ARCH_ESP32)
      if (_spi) {
        if (write_len > 0) {
          _spi->transferBytes(write_buffer, nullptr, write_len);
        }
      } else
    #endif
      {
        for (size_t i = 0; i < write_len; i++) {
          transfer(write_buffer[i]);
        }
      }
    
    #ifdef DEBUG_SERIAL
      DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
      for (uint16_t i = 0; i < write_len; i++) {
        DEBUG_SERIAL.print(F("0x"));
        DEBUG_SERIAL.print(write_buffer[i], HEX);
        DEBUG_SERIAL.print(F(", "));
        if (write_len % 32 == 31) {
          DEBUG_SERIAL.println();
        }
      }
      DEBUG_SERIAL.println();
    #endif
    
      // do the reading
      for (size_t i = 0; i < read_len; i++) {
        read_buffer[i] = transfer(sendvalue);
      }
    
    #ifdef DEBUG_SERIAL
      DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
      for (uint16_t i = 0; i < read_len; i++) {
        DEBUG_SERIAL.print(F("0x"));
        DEBUG_SERIAL.print(read_buffer[i], HEX);
        DEBUG_SERIAL.print(F(", "));
        if (read_len % 32 == 31) {
          DEBUG_SERIAL.println();
        }
      }
      DEBUG_SERIAL.println();
    #endif
    
      endTransactionWithDeassertingCS();
    
      return true;
    }

  9. #9
    Junior Member
    Join Date
    Mar 2023
    Posts
    6
    Alternatively, while poking around I found another library that uses the MAX31865 chip.

    https://github.com/PlayingWithFusion/PWFusion_MAX31865

    AND IT WORKS

    This code is also much more readable for my level of programming. I will use it for now but will try to return to debugging the adafruit library later.

    Thanks all.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •