Has anyone used an RGB panel with GPIO expansion IC / shift registers / 74HC595 / MCP23S17

My projects ran out of GPIO pins… Im using lots of break beam sensors ( 26 or more with the teensy 3.5 and smart matrix shield ) and I need a way to a way to control them. has anyone any advice on how I might do this?

I’d like to use a shift register such as the MCP23S17, but some past playing around with this IC and an Arduino mega and I found that the panels didn’t like it when the main board began serial communication with another device. I imagine this to be the case here with the teensy. Can anyone offer any advice? perhaps moving the project to the RPI is one solution, but I prefer to stick to a good old micro controller.

thanks in advance guys :slight_smile:

I’ve had good luck with this family of chips, more specifically the SPI expanders as I needed the speed. I chained several of them together to get the number of I/Os I needed:

and that worked whilst controlling the RGB panels? :crossed_fingers:

Good question, no, those were separate projects.

Other than pin conflicts, I don’t see a reason why either the i2c or spi goop expander chips would be incompatible with SmartMatrix Library. Specifically, smartled shield for Teensy 4 has a conflict with the SPI pins. Otherwise I don’t see any conflicts

thanks for your response. i’ll give it a go and report back :+1:

Hi jackjaquejack,
Are each of the 26+ beam break sensors equally important, all the time, or are there some that take priority over others or override them if triggered? For example, if senor #1 is triggered at the same time senor #26 is triggered, are they both utilized for a function, or only one of them utilized and the other is reset or simply ignored? If so, you can add an OR gate IC or an XOR gate or some type of logic circuit that will free up input pins.

Not a bad idea at all. Some of the sensors run in groups, and precisely which one has been triggered is not important. This is something I can consider - thanks

I had thought to use a second controller to do a similar thing, reading all the data and sending a pin high for a period of time as a signal for the main controller.

the MCP23017 and an RGB panel with smartMatrix3 software do run together.

using pins 19 and 18 (a4 or a5) for the communication on the teensy and mcp23017. for anyone trying the same, I struggled to get it work at first. I spent ages and eventually found that I needed to place a 47kohm resistor from pin 19 to 5V, and pin 18 and 5v. this one took me a while to find, and the mcp23017 wouldn’t work without the resistors.

the code which is just a combination of example sketch ‘blink without delay’ and the adafruit mcp23017 example sketch ‘toggle’ is pasted below. thanks guys, great to have a responsive forum to help me with this stuff.


  • teh teensey, the rgb panel, the mcp23017 all work together. no flickering on the screen


#include <SmartLEDShieldV4.h> // comment out this line for if you’re not using SmartLED Shield V4 hardware (this line needs to be before #include <SmartMatrix3.h>)
#include <SmartMatrix3.h>

#include <Wire.h>
#include “Adafruit_MCP23017.h”

Adafruit_MCP23017 mcp;

#define COLOR_DEPTH 24 // known working: 24, 48 - If the sketch uses type rgb24 directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 32; // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 32; // known working: 16, 32, 48, 64
const uint8_t kRefreshDepth = 36; // known working: 24, 36, 48
const uint8_t kDmaBufferRows = 4; // known working: 2-4, use 2 to save memory, more to keep from dropping frames and automatically lowering refresh rate
const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN; // use SMARTMATRIX_HUB75_16ROW_MOD8SCAN for common 16x32 panels, or use SMARTMATRIX_HUB75_64ROW_MOD32SCAN for common 64x64 panels
const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE); // see http://docs.pixelmatix.com/SmartMatrix for options
const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);

const int ledPin = 13; // the number of the LED pin

int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;

SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer1, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kScrollingLayerOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer2, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kScrollingLayerOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer3, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kScrollingLayerOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer4, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kScrollingLayerOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer5, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kScrollingLayerOptions);

void setup() {

mcp.begin();      // use default address 0

Serial.begin (9600);
mcp.pinMode(0, OUTPUT);
//pinMode(13, OUTPUT);
// Variables will change:

pinMode(ledPin, OUTPUT);


scrollingLayer1.setColor({0xff, 0xff, 0xff});
scrollingLayer2.setColor({0xff, 0x00, 0xff});
scrollingLayer3.setColor({0xff, 0xff, 0x00});
scrollingLayer4.setColor({0x00, 0x00, 0xff});
scrollingLayer5.setColor({0xff, 0x00, 0x00});




scrollingLayer1.setOffsetFromTop((kMatrixHeight/2) - 5);
scrollingLayer2.setOffsetFromTop((kMatrixHeight/4) - 5);
scrollingLayer3.setOffsetFromTop((kMatrixHeight/2 + kMatrixHeight/4) - 5);
scrollingLayer4.setOffsetFromTop((kMatrixWidth/2 + kMatrixWidth/4) - 5);
scrollingLayer5.setOffsetFromTop((kMatrixWidth/2 + kMatrixWidth/4) - 5);

scrollingLayer1.start(“Layer 1”, -1);
scrollingLayer2.start(“Layer 2”, -1);
scrollingLayer3.start(“Layer 3”, -1);
scrollingLayer4.start(“Layer 4”, -1);
scrollingLayer5.start(“Layer 5”, -1);

void loop() {

unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
  ledState = HIGH;

  ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
mcp.digitalWrite(0, ledState);