I have a project where I want to connect a number of SPI devices, and I'm running out of Slave Select pins (SPI) on the Arduino. So I thought that I could use something like an MCP23S17 to get additional pins and use those as SS pins, but most libraries require to pass the pins when initialising, and it seems that I can't pass the MCP's pins as a function/class argument (or can I?). For example:

U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /*cs*/ 12, /*dc*/ 4, /*rst*/ 6);

So my question is: How can I get more SS pins? Thank you

  • The problem with your plan is... how do you arrange to only have one SS pin active at once? You turn one of the expander pins on - that SS is then active. However you need a different SS active to turn it off again. You have a bit of a catch-22 situation: you need to turn off the SS pin in order to turn off the SS pin. The only reliable way is to have a second SPI bus that controls the expander.
    – Majenko
    Jul 3, 2017 at 22:19
  • True. What if I use the i2c MCP23017 though? In which case the SS pins would be controlled through i2c... That's my current scenario, but it doesn't solve the issue of putting the MCP's pins into library function calls.
    – J-M
    Jul 4, 2017 at 15:45
  • That would fix it - basically using a second bus (and changing the protocol but that's irrelevant).
    – Majenko
    Jul 4, 2017 at 15:46
  • And how would I pass the SS pins on an MCP23017 as arguments to the libraries after that?
    – J-M
    Jul 4, 2017 at 15:57
  • You wouldn't. Not without lots of nasty hacks.
    – Majenko
    Jul 4, 2017 at 15:58

3 Answers 3


I would suggest adding a layer of abstraction in your whole design.

Use the ESP8266 as the main system controller, then farm out sensor communications to one or more other "active" expansion devices.

Rather than just using an expander for the SS pins you are using the "expander" for all the communication.

By "expander" I basically mean some other microcontroller (maybe an ATMega328P for example) which receives an instruction to sample a sensor then goes off and gathers the data that is wanted and sends it back to the master ESP8266 controller.

How you arrange that communication is up to you, but maybe I2C would be a good way to go. You could even make the sensor data gathering completely autonomous so that the ESP8266 just then requests the latest data from the slave(s).

It means:

  • You don't have to change any libraries
  • You get distributed processing, sharing the work out
  • The ability to communicate with an almost infinite number of sensors
  • I assume you're right and this is the best solution, but I would prefer to have only one controller chip. Otherwise it means I have to write 2 programs, one for the ESP8266 and one for the sensor communication controller. Is there any way to avoid that?
    – J-M
    Jul 4, 2017 at 16:07
  • Use a bigger controller with more pins. It is very common to build a system with multiple controllers in it.
    – Majenko
    Jul 4, 2017 at 16:08
  • Ok, assuming I use something like an ATMega328P, how would I update its firmware then if it is merely a slave of the ESP8266?
    – J-M
    Jul 4, 2017 at 16:21
  • The same way you would in any other situation. Just because it is connected to an esp8266 makes no difference.
    – Majenko
    Jul 4, 2017 at 17:10

My solution would be to keep it simple. Use real pins for every SPI SS. Buy an other Arduino board with more pins if you need more pins.

What else is connected to your Arduino board ? Perhaps it is easier to reduce those pins. Almost all analog pins can be digital pins as well. You could use external ADC modules. Perhaps replacing 1-Wire or DHT11 or DTH22 with I2C sensors. Using a I2C display. There are many options to use buttons and leds with a few pins. And so on.

  • I'm actually using an ESP8266 (in the arduino environment), so my pins are rather limited.
    – J-M
    Jul 4, 2017 at 15:44
  • The ESP32 has solved all the disadvantages of the ESP8266. For example the Sparkfun Thing learn.sparkfun.com/tutorials/esp32-thing-hookup-guide has 32 pins.
    – Jot
    Jul 4, 2017 at 16:29

A maybe dirty solution is to change all the libraries. Everywhere the SS pin is used, instead call a function and set it yourself (by using the MCP23S17).

To make this a bit better, define a class that contains this functionality to abstract it from the changed library classes.


As initialization of the library a function or class constructor will be used, e.g.


This you will use like:

MCP23S17 my_component = MCP23S17();

You need to change this to:

MCP23S17(int ss_pin);

And change the related code, store it in a class variable and use it everywhere in the library instead of the fixed SS pin number.

Than you can constructor your own instance by:

MCP23S17 my_component = MCP23S17(4);

Where 4 is the SS pin number

  • That is a possibility, but a bit of a difficult one and not very efficient. I mean if any library upgrades, I have an issue...
    – J-M
    Jul 4, 2017 at 15:46
  • Yes completely true, it's quite dirty to change libraries anyway (but a literal ' solution' ) ... on the other hand, if you change the libraries and make the SS pins flexible everybody can use it (and it could be the new 'default' libraries). Actually I don't understand why people making libraries do not implement flexible pin assignments anyway directly from the start. Jul 4, 2017 at 16:05
  • Can you give me an example of what that could look like?
    – J-M
    Jul 4, 2017 at 16:12
  • I updated my answer Jul 4, 2017 at 16:46
  • 1
    I saw. I'm trying to understand it.
    – J-M
    Jul 4, 2017 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.