Detecting the presence of an SPI device on the arduino..

Is there a way to detect the presence of an SPI device on the bus, unlike the I2C MCP23017 which I use a portion of the i2c scanner code to detect it's physically there, I am trying to see how to see if the MCP23S17 is on the bus or not as It's being used in a hot plug situation and they have their own 5v 1amp power source.

the small circuit board consists of 8 MCP23S17 with HAEN enabled for 128 input/output pins, with 36 of those pins are programmed/wired to optocouplers as input trigger from 12volt devices, when 12 volt is applied, for example on the optocoupler, it drives the line low, if not, resistor pulls to 5v.

Wether the board is connected or not with no trigger line, if i do a mcp.digitalRead both will result in a HIGH or logic 1 result. This may confuse some programming at one point for a false positive.

the hot plugging works fine provided the external power does it's job, and it does, device works if i disconnect it and reconnect it, the power keeps the registers set.

problem is, i need to know how to make the arduino know it's physically there or not before i pull a digitalRead command.

is there an SPI physical detection algorithm like the i2c scanner implements?
thanks
Tony

one idea that i can think of is since they are input output chips and on reset they are in high impedance state, perhaps if i set an output pin of one of the mcp23s17 to GND and feed that to an additional arduino pin with pullup, it can detect whether it's there or not, at the expense of one mcp23s17 and 1 arduino pin.

How do you detect an SPI device without trying to talk to one? An SPI device would not respond until you held its chip select low and gave it a clock.

well, if i sent a digitalRead from the mcp23s17 it would return a logic 1 or HIGH, whether it's physically connected or not.

tonton81:
well, if i sent a digitalRead from the mcp23s17 it would return a logic 1 or HIGH, whether it's physically connected or not.

No it would not.

You loop the serial out of your device to the SPI input. You send out a byte, then a second and that first byte should be sent out and back into the Arduino. If you get back what you sent you have a device attached, if you don't then you haven't.

i am reading the PIN of the SPI MCP23S17 that is HIGH. Serial.print shows HIGH.
Now, I physically UNPLUG the MCP23S17.
I read THE SAME PIN AGAIN even tho it's PHYSICALLY DISCONNECTED, yet the Serial.print still shows HIGH.

Actually, ALL pins on any MCP23S17's report HIGH while it's disconnected.

Yes they are floating inputs and as the last thing they saw was a high they will stay that way for a bit and then interference will drag them in a random direction.

You ask for advice but seem unwilling to accept it.

that is why i need a way to detect if its there or not physically so it won't cause false positives. i CAN read but you CAN'T comprehend.

Then say so instead of whittling on about this amazing discovery that you have made.
What part of send two bytes out and see if you get the first one back do you not understand.?

Put a large value resistor on the CS line as a pulldown. 10 Meg or 100 Meg. This will not pull the CS low when the chip is connected but if the chip is absent you can make this an input and read it to see if it's low.

Don't do this with the Arduino hardware CS (10) as making that an input puts the SPI system into slave mode.

im using pin 9 as CS on arduino mega

you are right about the resistors, however, a pull up on MISO (pin 50) is working for my situation now thanks.
I'll also include a pullup on CS outputs.
thanks
Tony

Also, I added another sub routine in the MCP23S17.cpp function class.

Before:

uint8_t MCP23S17::readPort(uint8_t port) {
    if (port == 0) {
        readRegister(GPIOA);
        return _reg[GPIOA];
    } else {
        readRegister(GPIOB);
        return _reg[GPIOB];
    }
}

After:

uint8_t MCP23S17::readPort(uint8_t port) {
[b]    if (port == 2) {
        readRegister(IOCONA);
        return _reg[IOCONA];
    }
[/b]    if (port == 0) {
        readRegister(GPIOA);
        return _reg[GPIOA];
    } else {
        readRegister(GPIOB);
        return _reg[GPIOB];
    }
}

Now when i do a Serial.println(MCPSPI_8_0.readPort(2));lt should be a value of 24, if not, one of these issues happened:

ext power to MCP/OPTOS was removed, result would return 0.
CS line disconnected: result 255
MOSI/MISO/SCLK removed: result 255
EXT PWR and MISO/MOSI/SCLK/CS disconnected, registers empties, and plugged in, result: 0

Otherwise, normally, 24 means it's operational.

So basically I can use an if statement to verify for value 24 before processing commands, otherwise return and end functions related to those chips while trying to reinit until it's found.

And here is the sample that is working for future reference:
:slight_smile:

#include <MCP23S17.h>
#include <SPI.h>

// 8 == PIN, 0 == CHIP
MCP23S17 MCPSPI_8_0(&SPI, 8, 0);
MCP23S17 MCPSPI_8_1(&SPI, 8, 1);
MCP23S17 MCPSPI_8_2(&SPI, 8, 2);
MCP23S17 MCPSPI_8_3(&SPI, 8, 3);
MCP23S17 MCPSPI_8_4(&SPI, 8, 4);
MCP23S17 MCPSPI_8_5(&SPI, 8, 5);
MCP23S17 MCPSPI_8_6(&SPI, 8, 6);
MCP23S17 MCPSPI_8_7(&SPI, 8, 7);
//MCPSPI MCPSPI_9_1(&SPI, 9, 0);




void setup() {
  Serial.begin(115200);
  MCPSSetup();
}

void MCPSSetup() {
  //RE-INITIALIZE THE CHIPS (AND ENABLE HAEN AGAIN)
  //THIS IS NEEDED IF THE CHIP(S) CONNECTION IS LOST.
  MCP23S17 MCPSPI_8_0(&SPI, 8, 0);
  MCP23S17 MCPSPI_8_1(&SPI, 8, 1);
  MCP23S17 MCPSPI_8_2(&SPI, 8, 2);
  MCP23S17 MCPSPI_8_3(&SPI, 8, 3);
  MCP23S17 MCPSPI_8_4(&SPI, 8, 4);
  MCP23S17 MCPSPI_8_5(&SPI, 8, 5);
  MCP23S17 MCPSPI_8_6(&SPI, 8, 6);
  MCP23S17 MCPSPI_8_7(&SPI, 8, 7);
  MCPSPI_8_0.begin(); MCPSPI_8_1.begin(); MCPSPI_8_2.begin(); MCPSPI_8_3.begin(); MCPSPI_8_4.begin(); MCPSPI_8_5.begin(); MCPSPI_8_6.begin(); MCPSPI_8_7.begin();
  for (int i = 0; i <= 15; i++) {
    MCPSPI_8_0.pinMode(i, INPUT_PULLUP);
    MCPSPI_8_1.pinMode(i, INPUT_PULLUP);
    MCPSPI_8_2.pinMode(i, INPUT_PULLUP);
  }
  for (int i = 0; i <= 15; i++) {
    MCPSPI_8_3.pinMode(i, OUTPUT);
    MCPSPI_8_4.pinMode(i, OUTPUT);
    MCPSPI_8_5.pinMode(i, OUTPUT);
    MCPSPI_8_6.pinMode(i, OUTPUT);
    MCPSPI_8_7.pinMode(i, OUTPUT);
    MCPSPI_8_3.digitalWrite(i, LOW);
    MCPSPI_8_4.digitalWrite(i, LOW);
    MCPSPI_8_5.digitalWrite(i, LOW);
    MCPSPI_8_6.digitalWrite(i, LOW);
    MCPSPI_8_7.digitalWrite(i, LOW);
  }
}
void loop() {
  if (MCPSPI_8_0.readPort(2) != 24) {
    Serial.println("NOT DETECTED!!!");
    MCPSSetup();
    return;

  }
  Serial.println("DETECTED!!!");
  for (int i = 0; i <= 15; i++) {
    if (MCPSPI_8_0.digitalRead(i) != 1) {
      Serial.print("Port Expander SPI CHIP #0: Pin: ");
      Serial.print(i);
      Serial.print(": Result: ");
      Serial.println(MCPSPI_8_0.digitalRead(i));
      Serial.println("");
    }
  }
  for (int i = 0; i <= 15; i++) {
    if (MCPSPI_8_1.digitalRead(i) != 1) {
      Serial.print("Port Expander SPI CHIP #1: Pin: ");
      Serial.print(i);
      Serial.print(": Result: ");
      Serial.println(MCPSPI_8_1.digitalRead(i));
      Serial.println("");
    }
  }
  for (int i = 0; i <= 15; i++) {
    if (MCPSPI_8_2.digitalRead(i) != 1) {
      Serial.print("Port Expander SPI CHIP #2: Pin: ");
      Serial.print(i);
      Serial.print(": Result: ");
      Serial.println(MCPSPI_8_2.digitalRead(i));
      Serial.println("");
    }
  }
}

Also, there must be a pullup resistor (I use 10Kohm) on MISO and CS line.