RobTillaart / MCP23S17

Arduino library for SPI based MCP23S17 16 channel port expander
MIT License
27 stars 11 forks source link

MCP23S17 Daisy Chain On Common SPI Line #27

Closed seliimsi closed 9 months ago

seliimsi commented 1 year ago

Hello, Can we configure multiple slaves on common spi line by simply using 4 pins ? I wanna be able to select the slaves by hardware adress pins...

RobTillaart commented 1 year ago

Thanks for the question,

I had to look into the code, and yes the library should work with 4 wires and using up to 8 different device-addresses 0..7.

The address should be passed in the constructor, and is default 0, so for one device you do not need to set it although I would do to make it explicit.

RobTillaart commented 1 year ago

See MCP23S17_two_ADDRESS.ino

RobTillaart commented 1 year ago

Note to myself The library has no example for an array of devices. Could make it easier to access them in a for or while loop.

RobTillaart commented 1 year ago

not tested array example (it compiles)

//
//    FILE: MCP23S17_four_ADDRESS_array.ino
//  AUTHOR: Rob Tillaart
// PURPOSE: demo two MCP23S17 devices
//     URL: https://github.com/RobTillaart/MCP23S17
//
// #27, experimental, not tested with hardware yet

#include "MCP23S17.h"
#include "SPI.h"

MCP23S17 MCP_A(10, 12, 11, 13, 0);   //  SW SPI, address 0
MCP23S17 MCP_B(10, 12, 11, 13, 1);   //  SW SPI, address 1
MCP23S17 MCP_C(10, 12, 11, 13, 2);   //  SW SPI, address 2
MCP23S17 MCP_D(10, 12, 11, 13, 3);   //  SW SPI, address 3

//  MCP23S17 MCP_A(10, 0);   //  HW SPI, address 0
//  MCP23S17 MCP_B(10, 1);   //  HW SPI, address 1
//  MCP23S17 MCP_C(10, 2);   //  HW SPI, address 2
//  MCP23S17 MCP_D(10, 3);   //  HW SPI, address 3

MCP23S17 MCP[4] = { MCP_A, MCP_B, MCP_C, MCP_D };

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.print("MCP23S17_LIB_VERSION: ");
  Serial.println(MCP23S17_LIB_VERSION);
  Serial.println();
  delay(100);

  SPI.begin();
  for (int addr = 0; addr < 4; addr++)
  {
    MCP[addr].begin();
    MCP[addr].enableHardwareAddress();
  }

  //  test connected
  for (int addr = 0; addr < 4; addr++)
  {
    Serial.print(addr);
    Serial.print("\t");
    Serial.println(testConnection(MCP[addr]));
  }

  //  set all pins OUTPUT => LOW
  for (int addr = 0; addr < 4; addr++)
  {
    MCP[addr].pinMode16(0);
    MCP[addr].write16(0x0000);
  }
}

void loop()
{
  int pin  = random(64);
  int addr = random(4);
  MCP[addr].digitalWrite(pin, HIGH);
  delay(100);
  MCP[addr].digitalWrite(pin, LOW);
  delay(100);
}

//
//  the connection test tries to write a magic number to a register
//  and read it back. If it is the same it is assumed to be connected
//
int testConnection(MCP23S17 & mcp)
{
  uint16_t magic_test_number = 0xABCD;

  //  Read the current polarity config to restore later
  uint16_t old_value;
  if (! mcp.getPolarity16(old_value)) return -1;

  //  Write the magic number to polarity register
  if (! mcp.setPolarity16(magic_test_number)) return -2;

  //  Read back the magic number from polarity register
  uint16_t temp;
  if (! mcp.getPolarity16(temp)) return -3;

  //  Write old config to polarity register
  if (! mcp.setPolarity16(old_value)) return -4;

  //  Check the magic connection test
  if (temp != magic_test_number) return -5;

  return 0;  //  OK
}

//  -- END OF FILE --
seliimsi commented 1 year ago

Thanks so much for the reply Sir,

This is so helpful, I'm gonna share the details with you once I set up the wiring and test it...

Regards, Selim.

seliimsi commented 1 year ago

Hello again,

I tried to following code and set up the wiring with esp32 on VSPI pins and It does not pull any pin of any slave device to HIGH and it seems like no error other than this (E (103) psram: PSRAM ID read error: 0xffffffff) but I am not sure if it can be ignored. (see the attached file) Untitled

//
//    FILE: MCP23S17_two_ADDRESS.ino
//  AUTHOR: Rob Tillaart
// PURPOSE: demo two MCP23S17 devices
//     URL: https://github.com/RobTillaart/MCP23S17
//
// #19, experimental, not tested wirth hardware yet

#include "MCP23S17.h"
#include "SPI.h"

SPIClass mySPI(VSPI);

uint8_t SC=5;

MCP23S17 MCP_A(SC,0x00,&mySPI);   //  HW VSPI, address 0
MCP23S17 MCP_B(SC,0x01,&mySPI);   //  HW VSPI, address 1
MCP23S17 MCP_C(SC,0x02,&mySPI);   //  HW VSPI, address 2
MCP23S17 MCP_D(SC,0x03,&mySPI);   //  HW VSPI, address 3
MCP23S17 MCP_E(SC,0x04,&mySPI);   //  HW VSPI, address 4

MCP23S17 MCP[5] = { MCP_A, MCP_B, MCP_C, MCP_D, MCP_E };

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.print("MCP23S17_LIB_VERSION: ");
  Serial.println(MCP23S17_LIB_VERSION);
  Serial.println();
  delay(100);

  mySPI.begin();
  for (int addr = 0; addr < 5; addr++)
  {
    MCP[addr].begin();
    MCP[addr].enableHardwareAddress();
  }

  //  test connected
  for (int addr = 0; addr < 5; addr++)
  {
    Serial.print(addr);
    Serial.print("\t");
    Serial.println(testConnection(MCP[addr]));
  }

  //  set all pins OUTPUT => LOW
  for (int addr = 0; addr < 5; addr++)
  {
    MCP[addr].pinMode16(0);
    MCP[addr].write16(0x0000);
  }
}

void loop()
{
  int addr = random(5);
  MCP[addr].digitalWrite(7, HIGH);
  Serial.println(MCP[addr].digitalRead(7));
  delay(100);
  MCP[addr].digitalWrite(7, LOW);
  delay(100);
  Serial.println(MCP[addr].digitalRead(7));
}

//
//  the connection test tries to write a magic number to a register
//  and read it back. If it is the same it is assumed to be connected
//
int testConnection(MCP23S17 & mcp)
{
  uint16_t magic_test_number = 0xABCD;

  //  Read the current polarity config to restore later
  uint16_t old_value;
  if (! mcp.getPolarity16(old_value)) return -1;

  //  Write the magic number to polarity register
  if (! mcp.setPolarity16(magic_test_number)) return -2;

  //  Read back the magic number from polarity register
  uint16_t temp;
  if (! mcp.getPolarity16(temp)) return -3;

  //  Write old config to polarity register
  if (! mcp.setPolarity16(old_value)) return -4;

  //  Check the magic connection test
  if (temp != magic_test_number) return -5;

  return 0;  //  OK
}

//  -- END OF FILE --

(added code tags)

RobTillaart commented 1 year ago
  1. Can you adapt the sketch to use HSPI?
  2. Does any example with one device work?

I do not have time to investigate and have to look if I have the hardware.

seliimsi commented 1 year ago

1)Yes I have tried, ended up same.

2)I also have tried with one device and It did not work either. I focused on the hardware side and the circuit but it was all working fine and couldnt even manage to work with one device only.

I'll investigate more on this and have a deep check on the source code, then share my findings here.

Thanx once again,

Selim.

RobTillaart commented 1 year ago

@seliimsi Any progress made in your investigation?

seliimsi commented 12 months ago

Hello again, I needed to focus on another project but I'll keep you informed once I'll have the time for it. We can keep the issue as open for now.

Selim.

RobTillaart commented 11 months ago

@seliimsi Did you find time to make any progress?

seliimsi commented 10 months ago

Unfortunately not, still working on the other project as soon as I finish I will have that time. But I was not able to work with one device only either (with hardware adress), its maybe because of esp not sure and I have tried every possible way with the library itself as I remember. (VSPI, SPI, HSPI on both esp8266 and esp32 also tried with customized pins (software serial))

RobTillaart commented 9 months ago

As there are no new insights or questions here I close the issue. Feel free to reopen if needed in the future.