Help with mgos_mcp23xxx library

Hi, I have a board with an MCP23017 GPIO expander. It’s address is set to 0x27 and there are some things on bank A. Pins 0, 1 and 2 have LEDs and I am trying to get them to blink. I am able to make this work with the Arduino wire library so I know the hardware is good. Also, with the mongoose os app below I can see data on the I2C bus with my logic analyzer. On my board SDA is 4 and SCL is 5.

I have written the code I’ll paste below using the mongoose mgos_mcp23xxx library but I can’t get the LEDs to come on. I have tried many variations with no luck. It does say it successfully create the expander struct.

My expectation is, of course, that I learn to control the LEDs and they come on and blink. There are also other things on this expander like buttons and such I ultimately need to interface with.

I have this in my mos.yml file but as I mentioned, the logic analyzer shows data on the I2C bus.

# Enable I2C
  - ["i2c.enable", "b", true, {title: "Enable I2C"}]
#  - ["i2c.freq", "i", 100000, {title: "I2C bus speed"}]
#  - ["i2c.unit_no", "i", 0, {title: "Which hardware unit ot use, 0 or 1"}]
  - ["i2c.sda_gpio", "i", 4, {title: "GPIO to use for SDA"}]
  - ["i2c.scl_gpio", "i", 5, {title: "GPIO to use for SCL"}]

Here is the code. If someone could let me know what I did wrong I would appreciate it thank you!

#include "mgos.h"
#include "mgos_config.h"
#include "mgos_mcp23xxx.h"

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"

// Global for now
struct mgos_mcp23xxx *d;

static void vLEDTask(void* pvParameters)
    LOG(LL_ERROR, ("========>>> Toggle..."));

    mgos_mcp23xxx_gpio_toggle(d, 0);
    mgos_mcp23xxx_gpio_toggle(d, 1);
    mgos_mcp23xxx_gpio_toggle(d, 2);

enum mgos_app_init_result mgos_app_init(void)
  // I2C ADDR 0x27
  // EXP_INT IO0
  #define ADDRESS 0x27

    if (!(d = mgos_mcp23017_create(mgos_i2c_get_global(), ADDRESS, 0) ) )
      LOG(LL_ERROR, ("************>>> Could not create MCP230XX"));
      return MGOS_APP_INIT_ERROR;
      LOG(LL_ERROR, ("========>>> created MCP230XX"));

    mgos_mcp23xxx_gpio_set_mode(d, 0, MGOS_GPIO_MODE_OUTPUT);  // LED A
    mgos_mcp23xxx_gpio_set_mode(d, 1, MGOS_GPIO_MODE_OUTPUT);  // LED G
    mgos_mcp23xxx_gpio_set_mode(d, 2, MGOS_GPIO_MODE_OUTPUT);  // LED B

// Fails with and without the next 3 lines
//    mgos_mcp23xxx_gpio_write(d, 0, 1);
//    mgos_mcp23xxx_gpio_write(d, 1, 0);
//    mgos_mcp23xxx_gpio_write(d, 2, 1);

    mgos_set_timer(1000, MGOS_TIMER_REPEAT, vLEDTask, NULL);


try to add as in

for(i=0; i<4; i++) mgos_mcp23xxx_gpio_setup_input(d, i, MGOS_GPIO_PULL_UP);

Thanks, but that example has input and output, and that line is setting up the input pins. For now I’m just trying to get the output to work. Unless I missed something?

I don’t want to disturb you. I see, your experience with programming is much much more greater then mine. But i also know that, that forum is sometimes useless, nobody answers, so I try to help you as I can.
I found something like this:

bool mgos_mcp23xxx_gpio_setup_output(struct mgos_mcp23xxx *dev, int pin, bool level);

I spent a lot of hours to find answer like this one.

1 Like

You’re not disturbing me at all, I greatly appreciate your helping. I’ll check that out thank you!

After corresponding with the author of this library, we know there is a bug in the toggle function. Also, there are some other things to know. I’ll make a complete post with these things once I have a complete list.

This library has been patched by it’s author so the toggle method has been fixed, but the patch has not been posted yet. If anyone needs this in the meantime the patched version is available at:

- origin:

I have tested the change with the mcp23017 only.

One more important detail, if you are using the 16 pin version (the mcp23017), then note that the first pin of bank A is pin 8 and the first pin of bank B is pin 0. Therefore if you put LEDs on bank A expander pins A0, A1 and A2 you should address these using this library as pins 8, 9 and 10.

Thanks to Pim for squaring this away.

Hi Jim to used multiple mcp just do this right ?

struct mgos_mcp23xxx *mcp1;
struct mgos_mcp23xxx *mcp2;

MCP230XX devices have 3 bits to program the I2C address. You set the 2 devices to have different addresses and e.g.

struct mgos_i2c *i2c = mgos_i2c_get_global();
struct mgos_mcp23xxx *mcp1 = mgos_mcp23008_create(i2c, i2caddr_1, int_gpio_1);
struct mgos_mcp23xxx *mcp2 = mgos_mcp23008_create(i2c, i2caddr_2, int_gpio_2);


So the way I define is wrong ?

I found some bug with mcp2 on the I/O was very un-expected result. But if switch hardware / change the address to run under mcp1 it work fine.
below is full code.

struct mgos_mcp23xxx *mcp1;
struct mgos_mcp23xxx *mcp2;

 if (!(mcp = mgos_mcp23017_create(mgos_i2c_get_global(),MCP1_ADDR,-1))) {
     LOG(LL_ERROR, ("#### Could not create MCP230XX!!"));
  } else {
    LOG(LL_WARN, ("MCP Connected"));
    for(int i =0; i<16; i++) {  
      mgos_mcp23xxx_gpio_set_mode(mcp, i, MGOS_GPIO_MODE_OUTPUT);

 if (!(mcp2 = mgos_mcp23017_create(mgos_i2c_get_global(),MCP2_ADDR,-1))) {
     LOG(LL_ERROR, ("#### Could not create MCP230XX!!"));
  } else {
    LOG(LL_WARN, ("MCP2 Connected"));
    for(int i =0; i<16; i++) {  
      mgos_mcp23xxx_gpio_set_mode(mcp2, i, MGOS_GPIO_MODE_OUTPUT);

I don’t have any of these devices to test, so you have to be more specific about the bugs, errors you get.

There is no error. it show both of them are success connected to mcp.

But Output won’t work or work ab-normal with the logic.

For example I used PIN 8 , HIGH it should be active but it’s not

, the result for pin under mcp2 are un-predictable. But under mcp1 no matter which mcp hardware are it work find.

I Test this in Arduino with duplicate variable like this. it work normally.