MCP23s17 Blink example

Hello all,

I’m trying to use the example on build to get this io expander to work. The code is supposed to turn pin 7 high and low but I’m getting no activity.

What code?

  /*********/
 /* Blink */
/*********/
#include "mcp23s17.h"

const int LED_PIN = 7;
mcp23s17 gpio_x(mcp23s17::HardwareAddress::HW_ADDR_0); // All addressing pins set to GND

void setup (void) {
    gpio_x.pinMode(LED_PIN, mcp23s17::PinMode::OUTPUT);
}

void loop (void) {
    gpio_x.digitalWrite(LED_PIN, mcp23s17::PinLatchValue::HIGH);
    delay(2000);
    gpio_x.digitalWrite(LED_PIN, mcp23s17::PinLatchValue::LOW);
    delay(2000);
    //Serial.println("Hello Koo");
}

i just used the example on Build

Hi @Ali

I looked at your wiring circuit and I think you have your LED connected to GPB6 which means you should have LED_PIN=15. In your code example you are toggling LED_PIN=7 which is GPA6 and that would be pin 27 on the MCP23S17 IC.

Also looking at the MCP23S17 arduino library here (not sure if this is the one you are using) it’s setup to use the standard SPI function calls. For SPI usage on the Photon you want the connection setup as described here

SS => A2 (default)
SCK => A3
MISO => A4
MOSI => A5 

I don’t think you have the correct connections between your Photon and MCP23S17. I suggest you rewire your project as follows -

Photon A2 => MCP23S17 PIN 11
Photon A3 => MCP23S17 PIN 12
Photon A4 => MCP23S17 PIN 14
Photon A5 => MCP23S17 PIN 13

Hope that helps!

These are correctly wired just the way you've suggested.

I do not understand how the pins are numbered though. I have previously used the i2c version of this chip where I would write to a register a decimal value which would enable a certain bit pattern.

Can you provide some basic explanation for what's going on here?

Thanks in advance.

I read the link from https://playground.arduino.cc/Main/MCP23S17. I understand how this works. Thanks for pointing me in the right direction.

Great!

Does this mean your setup works now?
The reason I ask is that it seems as if you were powering the setup from the TX pin of the Photon - is this intended, or did you not want the red wires at the bottom of your pic attached to Vin?

BTW

That's the same on all integrated DIL chips.
Start with the pin nearest to the dot or groove on the chip with 1 count along side change over to the other side and count up again.

The pins on the 23S17 are numbered using the small circle indent that references pin 1. (See red arrow in picture below) It's the lower right corner pin. Then they go up the right side, around the top and down the other side. So across the chip from pin 1 is pin 28.

The 'S' version of the chip is for SPI communications, the I2C version is without the 'S'. Here is the data sheet.

When you communicate over SPI the pins MISO (Microcontroller Input, Slave Output) are for receiving data from the external device, the pin MOSI (Microcontroller _O_utput, _S_lave Input) are for sending data to the external device.

There are a bunch of different registers on the device to control it's behavior. I won't go into them as the library you are using provides a good API for setting up and using the device.

1 Like

No ! Still doesn't work.

Photo angle makes it look like that. They're connected to the GND pin. I used red for GND as i had more of them on hand than the black ones. [quote="ScruffR, post:8, topic:34671"]
That's the same on all integrated DIL chips.
Start with the pin nearest to the dot or groove on the chip with 1 count along side change over to the other side and count up again.
[/quote]

The class actually changes the way the pins are numbered according to here. I have not studied the code yet but i will do so shortly to understand why this does not work.

Thank you @mtnscott. I was referring to the way the the library changes GPA0 at pin 21 to 1.

The library on build is quite different from the arduino library. A quick read through the src file and the datasheet solved the confusion.

LED_PIN = 7 in this case point to GPA7(Pin 28) and LED_PIN = 15 points to GPB7(Pin 8)

Now to see how interrupts work on this guy.

The hardware pin numbers on the chip don’t usually corespond to the GPIO numbers.
For that relationship you need to consult the datasheets.

I got 2 mcp23s17’s working using different ss pins. But i am trying to make them work using a single slave select using different addresses. I set the addresses on one of them to all GND and the other one to be A2 to 5V and the rest to GND. However on setting the address to 1 i do not get any response from the chip.

mcp23s17 mcp(mcp23s17::HardwareAddress::HW_ADDR_0,A2);
mcp23s17 mcp2(mcp23s17::HardwareAddress::HW_ADDR_1,A2);

@Ali, you cannot use a single slave select since the MISO lines from each device will clash as both will no longer be in tri-state mode. You MUST use separate select lines. BTW, the SPI MCP23S17 doesn’t support device addresses, just the I2C version.

Ok! The data sheet does not mention this though.

@Ali, this is defined in the SPI specification. The MCP datasheet is clear in their block diagram showing address selection of the I2C interface but not on the SPI interface. In short, I2C is a 2-wire bus which can address up to 127 devices (each with a unique address) whereas SPI is a 4-wire (typically) bus with no addressing and only single device actively communicating at a time.

Got it! I am reading up on this discussion MCP23017 Library Port regarding interrupts on the MCP23017. The MCP23S17 should work in a similar fashion right? Attach the INT pin on the chip to one of the pins on the photon and call attachinterrups.

i wired up the int pin to D2 of the photon and initialized these lines in setup

pinMode(D7,OUTPUT);
	pinMode(D2,INPUT);
	attachInterrupt(D2,handler,FALLING);
	mcp2.attachInterrupt(button,change,mcp23s17::InterruptMode::FALLING);

In the handler

void handler() {
	digitalWrite(D7, !digitalRead(D7));
	digitalRead(button);
}

When i push the button D7 lights up once. I cannot seems to get interrupts to trigger again.
The datasheet says a subsequent read from the GPIO or INTCAP registers will clear the bit. But it does not seem to be working. Any ideas on what i am doing wrong?

How do you read the GPIO or INTCAP after you had an interrupt?
Can’t see that code in your post :wink:

digitalRead(button) only reads that pin on the Particle device but not on the MCP where this should be read in order to reset the INT flag on that device.