Go Down

Topic: [SOLVED] I2C Communication on pins D3/D4 (Read 3690 times) previous topic - next topic

Rfuzer

Jun 26, 2015, 04:55 pm Last Edit: Jul 06, 2015, 03:54 pm by cmaglie
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?

cmaglie

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!
C.

Rfuzer

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?

Rfuzer

#3
Jul 02, 2015, 02:20 pm Last Edit: Jul 06, 2015, 03:53 pm by cmaglie
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!

cmaglie

Rfuzer,

thank you for sharing your solution!  8)
C.

cartero7d

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

MartinL

Hi cartero7d,

The easiest way to set-up an additional I2C port is to follow Adafruit's excellent tutorial: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/overview.

cartero7d

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.



MartinL

#8
Nov 20, 2018, 05:30 pm Last Edit: Nov 20, 2018, 05:44 pm by MartinL
Hi cartero7d,

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

Code: [Select]
#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:

Code: [Select]
TwoWire myWire(&sercom2, 4, 3);
Start I2C communication using "myWire":

Code: [Select]
myWire.begin();
Connect digital pins 3 and 4 to the SERCOM2 peripheral:

Code: [Select]
// 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.

cartero7d

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.

Go Up