I2C and Port Expander

Hi rapidM2M Community!

I am a beginner with M2M Base Starter. I need to control a PortExpander with I2C. Are there any examples of how to send the right Bytes (start, address, R/W, ACK, Data and Stop bits)?
I am using the command: rM2M_I2cCom(i2c, adr, data{}, txlen, rxlen); however, I am not for sure if I use this command right.

Best regards,
Jakob

Hi Jakob,

There are several examples available using I2C (see Basic_Examples_Collection).
Currently we do not have an example for a port expander, but the device address and the right data bytes are dependent on your used device. Usually this information can be found in the device datasheet.

best regards,
Gregor

Hi,
Thank you for your answer.

I am using the commands which I found in the documentation and in some examples in the Basic_Examples_Collection.

	new Data{8} = 0xFF;

	Result = rM2M_I2cInit(PORT_I2C, 40000, 0);
	#log("rM2M_I2cInit(%d) \r\n", Result);

	i2cResult = rM2M_I2cCom(PORT_I2C, 01000000, Data, 1 , 0);
	printf("rM2M_I2cCom(%d) \r\n", i2cResult);

The device address ist 0100, A0, A1 and A2 are on GND => 0 and the W/R is on 0 for write.
But the line:
printf("rM2M_I2cCom(%d) \r\n", i2cResult);
shows:
11:15:32.034 rM2M_I2cCom(-11)

But I don’t understand why this error is thrown?
Does someone know what I am doing wrong?

best regards
Jakob

Hi Jakob,

The correct binary numeric constant for your address is 0b01000000.
In your code the address is decimal 1000000 and therefor you get the -11 error (see rM2M.inc file for explanation) because this address is not available on the I2C bus -> I2C communication is aborted.

best regards,
Gregor

Hi Gregor,

I changed the binary numeric constant for my address to 0b01000000.
But I still get the -11 error.

I also changed the Data to: new data{0} = 0xFF;

So I have:
rM2M_I2cCom(PORT_I2C, 0b01000000, data,1,0);
When I run the Programm I still have the -11 error.
But when I changed the txlen from 1 to 0 the error is gone.

Do I have a Problem with the data (data : {} - buffer to send and receive) in the rM2M_I2cCom().

best regards,
Jakob

Hi Jakob,

I would suggest that you check the electrical connection to the I2C device.
The rapidM2M Module is not able to find it on the I2C bus.
Which I2C port expander are you using?

When you set txlen to 0, then nothing will be transmitted over I2C and the function returns immediately.

best regards,
Gregor

Hi Gregor,

I use the port expander MCP23017.
My partner and I ckecked the elecrical connection and there shouldn’t be any problem.

best regards,
Jakob

Hello @Jakob,

I took a quick look at the data sheet. With your code example, you write only one byte (0xFF) to the MCP23017. For a write access, the first byte that will be transferred to the MCP23017 must be the register address. After that, at least one byte must be read back (see Page 13 of the MCP23017/MCP23S17 Datasheet). Your “0xFF” is not a valid register address. You should also read at least one byte back:

rM2M_I2cCom(PORT_I2C, 0b01000000, data,1,1);

Since I don’t have an MCP23017, I couldn’t test it more closely. I recommend you to take a closer look at the data sheet, especially from page 12.

Kind regards
Josef

Hello @Josef,

After a while, I found the Error that I have to write the registers first.
0x00 is the address for the first register. The register describes whether the Ports are Inputs or Outputs. That all are Outputs the Byte should be 0x00.

So:
addr (0b01000000) is the device address.
Then I have to write the two Bytes, first the address byte (0x00) and then the “data” byte (0x00) into the Array, data?
rM2M_I2cCom( i2c, addr, data, txlen, rxlen);
Or do I have to use the Command rM2M_I2cCom different and addr is the register address?

best regards
Jakob

Hello @Jakob,

The parameter “addr” of the “rM2M_I2cCom()” function always corresponds to the I²C address of the component. In your case “0b01000000”.
How the component interprets the data sent to it (parameter “data”) depends on the component itself. For the MCP23017 the first data byte is register address and the second is the value to be set for this register.

new data{2} = {0x00, 0x00};
rM2M_I2cCom(PORT_I2C, 0b01000000, data,2,0);

Kind regards
Josef

Hello @Josef,

Thanks for your answer!
I tried the example that you sent me but I still have the Error -11.
What could be another reason for the Error?

best regards
Jakob

Hello @Jakob,

I would recommend you to perform the following checks:

  • Examine the description of the i²C interface of the MCP23017 once again carefully (protocol, register addresses, values to be set) I only took a quick look at it and unfortunately can’t do any tests as I don’t have an MCP23017.
  • Check the electrical connection between rapidM2M Base Starter and MCP23017 (see rapidM2M Base Starter Board Schematic)
  • Check the pull-up resistors required on the two I²C lines
    image
  • Check whether the logic levels (high, low) of rapidM2M Base Starter and MCP23017 are compatible (see Datasheet rapidM2M M22x 2G/3G EU/3G US page 9 and Datasheet MCP23017/MCP23S17 page 4)
  • Check the supply voltage of the MCP23017
  • Check the two signals “SCL” and “SDA” directly on the pins of the MCP23017 with an oscilloscope
  • Disconnect rapidM2M Base Starter and MCP23017. Make sure that the rapidM2M module on the rapidM2M Base Starter is connected to the temperature and humidity sensor and try to establish I²C communication with this sensor. To do this, use the demo examples on Github (see Examples on Github

Kind regards
Josef

Hello @Josef,

The error was not due to the code or the wiring. After I discovered that the module had an update and I did that and tried the code again it worked.
Because I was rarely in the rapidM2M portal, I didn’t immediately notice that there was an update.
Thank you for your help and I apologize for the circumstances

Kind regards
Jakob