[SOLVED] I2C Communication on pins D3/D4

Hi,

Is there a functionally I2C Communication on Arduino Zero?

In Arduino Zero's Schematic there is two ports with I2C communication, D3/D4(PA09/PA08) e I2C_SDA/I2C_SCL(PA22/PA23). The two ports are marked as I2C. Can I use D3/D4 ports for I2C communitacion without any change in variant.cpp?

The two pins SDA/SCL can be used with the usual Wire library.

The other two pins requires a change in the variant.h and to the Wire.h/cpp, in particular the begin() method do not yet support multiple I²C pins definitions from the variant.h. Moreover we must figure out how to share the SERCOM instances between multiple I²C / SPI / UARTS, and allocate them only as needed.
Making this simple for the final user is a complex topic :-), if you have any suggestion, you're more than welcome!

I tried to change the variant.h in this line:

...

#define PIN_WIRE_SDA (4u)
#define PIN_WIRE_SCL (3u)

...

for use the D3/D4 as I2C ports, and not work! I want to use just one device in communication I2C, but i need to use this pins (D3/D4). Is there other change that i need to do for work?

SOLVED!

I solved my problem by changing the following code lines:

in "variant.h" :

#define PIN_WIRE_SDA         (4u)  
#define PIN_WIRE_SCL         (3u)

in variant.cpp

  { PORTA,  9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL/*|PIN_ATTR_PWM|PIN_ATTR_TIMER*/), No_ADC_Channel, NOT_ON_PWM,   NOT_ON_TIMER,     EXTERNAL_INT_9 }, 
  { PORTA,  8, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL/*|PIN_ATTR_PWM|PIN_ATTR_TIMER*/), No_ADC_Channel, NOT_ON_PWM,   NOT_ON_TIMER,     EXTERNAL_INT_NMI },

in Wire.cpp

TwoWire Wire(&sercom2);

void SERCOM2_Handler(void) {
  Wire.onService();
}

Now, I have the I2C communication working on ports D3/D4(PA09/PA08) very well!

Regards!

Rfuzer,

thank you for sharing your solution! 8)

Did you modify wire.cpp or did you add the lines

TwoWire Wire(&sercom2);

void SERCOM2_Handler(void) {
Wire.onService();
}

into the file?

Any help would be appreciated!

Thanks

Hi cartero7d,

The easiest way to set-up an additional I2C port is to follow Adafruit's excellent tutorial: Overview | Using ATSAMD21 SERCOM for more SPI, I2C and Serial ports | Adafruit Learning System.

MartinL,

I may not understand this correctly. However, I am trying to use an LCD screen over I2C using the LiquidCrystal_I2C.h Library. This library work on the current I2C pins and I can have it lcd.print to the screen just fine. However, I am unable to get the same functionality on different I2C pins. I have tried to follow the Adafruit example but it doesn't explain enough of what is happening in the code for me to be able to adapt it to my needs(hence why I am interested in the way Rfuzer fixed this issue).

Any further clarification would be appreciated.

I am using the SAMD21 Mini Breakout from sparkfun. D3 (PA09) and D4(PA08) are the pins I want to use.

Hi cartero7d,

The Adafruit tutorial has an I2C example that uses D3 and D4:

#include <Wire.h>
#include "wiring_private.h" // pinPeripheral() function
 
TwoWire myWire(&sercom2, 4, 3);
 
#define MCP4725_CMD_WRITEDAC            (0x40)
#define MCP4725_ADDR                    (0x62)
void setup() {
  Serial.begin(115200);
  myWire.begin();
  
  // Assign pins 4 & 3 to SERCOM functionality
  pinPeripheral(4, PIO_SERCOM_ALT);
  pinPeripheral(3, PIO_SERCOM_ALT);
}
 
uint8_t i=0;
void loop() {
  Serial.println(i);
  myWire.beginTransmission(MCP4725_ADDR); // start transmission to device 
  myWire.write(MCP4725_CMD_WRITEDAC);
  myWire.write(i++);
  myWire.write((uint8_t)0x0);  // bottom four bits are 0x0
  myWire.endTransmission(); // end transmission, actually sending
}

Just replace the I2C address and sub-addresses with your LCD screen's ones.

Instantiate (create) an I2C Wire library object called "myWire", using the SAMD21's serial communciation (SERCOM) module 2 on digtial pins 3 and 4:

TwoWire myWire(&sercom2, 4, 3);

Start I2C communication using "myWire":

myWire.begin();

Connect digital pins 3 and 4 to the SERCOM2 peripheral:

// Assign pins 4 & 3 to SERCOM functionality
pinPeripheral(4, PIO_SERCOM_ALT);
pinPeripheral(3, PIO_SERCOM_ALT);

Use "myWire" as you would the "Wire" library.

The issue with using Rfuzer's approach is that it requires changing the "variant.h" and "variant.cpp" Arduino core files. Changes to these file will be overwritten each time the core files are updated, plus changes to "variant" files will also affect any other sketches using the Sparkfun SAMD21 Mini Breakout.

I tried the approach you stated. It does not work for some reason. This may have something to do with me wanting to use the Liquidcrystal_I2C library as well.

For further clarification, my end use with this is a custom board for a very specific project. This means modifying the variant.h and .cpp files won't be changed because it has its own variant.h and .cpp files. The mini dev board is just for me to test with for the time being. However, I was able to find and modify the varient.h and .cpp files and get the i2c working with the liquidcrystal library. That being said I didn't need to change anything in the wire.cpp file.

Thank you for your quick responses.