RobTillaart / MCP23S17

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

Support for multiple Chips missing? #19

Closed felixlindemann closed 1 year ago

felixlindemann commented 1 year ago

Thank you for the Library. With one Chip(=mcp23s17) at a Time, i could get to run. When i tried to Add a Second or Third Chip, the adressing didn’t work. Could you please Provide an example with 2+ Chips- maybe a copy from Chip 1 to Chip 2? Thank you very much Felix

RobTillaart commented 1 year ago

Thanks for reporting this issue. As my agenda is rather full it might take several days before I have time to investigate. Furthermore I do not have the hardware to test, i assume you have?

RobTillaart commented 1 year ago

Found a moment to write (copy/paste) a sketch that uses two devices with an Arduino UNO. It uses software SPI so you can adjust pins if you want to. Note that the only difference in the parameters is the SELECT pin. Although the devices share the SWSPI bus, only one will be addressed by means of the SELECT pin.

Not tested with hardware!

Use SELECT pin

//
//    FILE: MCP23S17_two.ino
//  AUTHOR: Rob Tillaart
// PUPROSE: demo two MCP23017 devices
//
// see issue #19 library

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

MCP23S17 MCP_A(10, 12, 11, 13);  //  SW SPI
MCP23S17 MCP_B(9 , 12, 11, 13);  //  SW SPI, different select pin!

//  MCP23S17 MCP_A(10);  //  HW SPI
//  MCP23S17 MCP_B(9);   //  HW SPI, different select pin!

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

  SPI.begin();
  MCP_A.begin();
  MCP_B.begin();

  //  test connected
  int c = testConnection(MCP_A);
  Serial.print("Connect A: ");
  Serial.println(c);
  c = testConnection(MCP_B);
  Serial.print("Connect B: ");
  Serial.println(c);

  //  all pins OUTPUT  LOW
  MCP_A.pinMode16(0);
  MCP_A.write16(0x0000);
  MCP_B.pinMode16(0);
  MCP_B.write16(0x0000);
}

void loop()
{
  int x = random(32);
  if (x < 16)
  {
    MCP_A.digitalWrite(x, HIGH);
    delay(100);
    MCP_A.digitalWrite(x, LOW);
  }
  else
  {
    x -= 16;
    MCP_B.digitalWrite(x, HIGH);
    delay(100);
    MCP_B.digitalWrite(x, LOW);
  }
}

//
//  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 --

Use Address pins ==> NOT TESTED

There should be another way to use multiple devices, by assigning them different addresses. Then in theory they could use even the same SELECT pin. I have never tried this, but given the chip has address pins I expect it to work.

RobTillaart commented 1 year ago

Note, for using the HW address pins, one should enable them - IOCON.HAEN See 3.3.2 datasheet. (need to check library for that)

(checked) This should enable hardware addresses.

MCP.enableControlRegister(0x08);
RobTillaart commented 1 year ago

Created a develop branch which should improve the support for multiple devices.

This branch includes the example above + an example to use the hardware address to operate multiple devices.

Please give it a try and let me know the results.

felixlindemann commented 1 year ago

Wow, That is a fast response. I’ll Check it tonight! Thanks in advance. Felix

felixlindemann commented 1 year ago

hello Rob, I will have to check it on the weekend. I won't make tonight. Thanks for your very fast response I'll get back to you asap.

RobTillaart commented 1 year ago

@felixlindemann Any progress ?

felixlindemann commented 1 year ago

Hi @RobTillaart sorry I am not able to get it to run. In my setup up I want to be flexible according to the wiring - (in my final design I use a canbus board and some pwm servos as well.) for that reason i use the software spi.

The yellow LED on the left flashes randomly the blue in the middle is permanently on. both leds of the second chip are permanently off

here is my Sketch. image

here the breedboard image

Here is the SoftwareSPI

//
//  AUTHOR: Rob Tillaart / Felix Lindemann
// PUPROSE: demo two MCP23017 devices
//
// see issue #19 library

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

const int wCS = 9;
const int wCLK = 13;
const int wSI = 11;
const int wSO = 12;

MCP23S17 MCP_A(wCS,wSI, wSO, wCLK, 0x00 );  
MCP23S17 MCP_B(wCS,wSI, wSO, wCLK, 0x01 );  

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

  SPI.begin();
  MCP_A.begin();
  MCP_B.begin();
  MCP_A.enableHardwareAddress(); 
  MCP_B.enableHardwareAddress(); 

  //  all pins OUTPUT  LOW
  MCP_A.pinMode16(0);
  MCP_A.write16(0x0000);
  MCP_B.pinMode16(0);
  MCP_B.write16(0x0000);
}

void loop()
{ 
  int x= 1;
  int y= 8;
    Serial.println("8/1");
    MCP_A.digitalWrite(x, LOW);
    MCP_A.digitalWrite(y, HIGH);
    MCP_B.digitalWrite(x, HIGH);
    MCP_B.digitalWrite(y, LOW);
    delay(1000);
    Serial.println("1/8");
    MCP_A.digitalWrite(x, HIGH);
    MCP_A.digitalWrite(y, LOW);
    MCP_B.digitalWrite(x, LOW);
    MCP_B.digitalWrite(y, HIGH);
    delay(1000);
}

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

int x= 1; int y= 8;

Please try to use x = 0; and y = 7;, as pin numbering is 0 based, 0 .. 15

void loop()
{ 
  int x= 0;
  int y= 7;
    Serial.println("8/1");
    MCP_A.digitalWrite(x, LOW);
    MCP_A.digitalWrite(y, HIGH);
    MCP_B.digitalWrite(x, HIGH);
    MCP_B.digitalWrite(y, LOW);
    delay(1000);
    Serial.println("1/8");
    MCP_A.digitalWrite(x, HIGH);
    MCP_A.digitalWrite(y, LOW);
    MCP_B.digitalWrite(x, LOW);
    MCP_B.digitalWrite(y, HIGH);
    delay(1000);
}
felixlindemann commented 1 year ago

^ | |____ don't code while tired

obiviously... it works

felixlindemann commented 1 year ago

thanks a lot 👍

RobTillaart commented 1 year ago

I will merge the PR to support the multi device / address code into master asap.

RobTillaart commented 1 year ago

@felixlindemann

What board are you using? I have prototype code for AVR software SPI transfer for the MCP23S17. If you are interested to test it I can send it, it will be part of a - not planned - future release.