0

Second I2C Port on ItsyBitsy M4
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Second I2C Port on ItsyBitsy M4

by RocketScientist on Wed Nov 11, 2020 3:50 pm

I have an application (PocketQube satellites - 5cm cubes) with many sensors. I like the M4 because of performance, but find it is I/O bound with the speed of sensors on the I2C bus. So I am moving to an architecture with two I2C busses - one slow (400 kb/s) and one fast (3400 Kbs/s) to connect to sensor collection boards with their own processor. And adding in a more flexible software architecture with FreeRTOS.

I am trying to debug adding the second I2C port. After pouring over variant.h and variant.cpp and several web tutorials - including Adafruit's - https://learn.adafruit.com/using-atsamd ... a-new-wire. I decided that ports PA22/PA23 were available on Sercom5. Possibly A2/A3 on Sercom4.

I put together an expanded test program to test connectivity using a simple I2C peripheral (an MCP4725 DAC) to test as well as several other known I2C sensors. I put Wire2 on D13/D12 (PA22/PA23) with 1k pull-ups. The test program compiles, runs, successfully finds all the devices on the standard Wire, finds the MCP4725 when moved to that Wire, but finds nothing on the second Wire2 even when I exchange the SCL and SDA pins.

This is convoluted enough that I am positive I am making a mistake but unclear what mistake.

Help?

Here is a sample output of the test program:

Setup standard Wire
11:22:58.450 -> Setup second Wire
11:22:58.450 -> 0
11:22:58.450 -> First check the standard Wire
11:22:58.450 -> I2C Scanning...
11:22:58.450 -> I2C device found at address 0x10 !
11:22:58.450 -> I2C device found at address 0x28 !
11:22:58.450 -> I2C device found at address 0x40 !
11:22:58.450 -> I2C device found at address 0x76 !
11:22:58.450 -> 4 I2C devices found
11:22:58.450 -> I2C scan done
11:22:58.450 -> Fail
11:22:58.450 -> Now check the new second Wire
11:22:58.450 -> I2C Second Wire Scanning...
11:22:58.484 -> No I2C devices found
11:22:58.484 -> I2C second Wire scan done


Code: Select all | TOGGLE FULL SIZE
#include <Wire.h>
#include "wiring_private.h" // pinPeripheral() function

#define SDA2  13
#define SCL2  12

TwoWire Wire2(&sercom5, SDA2, SCL2);

#define MCP4725_CMD_WRITEDAC            (0x40)
#define MCP4725_ADDR                    (0x60)

void setup() {
  Serial.begin(115200);

  delay(2000);

  Serial.println("Setup standard Wire");
  Wire.begin();
  Serial.println("Setup second Wire");
// Assign SDA2 & SCL2 to SERCOM functionality
  pinPeripheral(SDA2, PIO_SERCOM_ALT);
  pinPeripheral(SCL2, PIO_SERCOM_ALT);
  Wire2.begin();
 

}

uint8_t i=0;
void loop() {
  int result;
  Serial.println(i);

  // First check Wire

  Serial.println("First check the standard Wire");

  I2Cscan();

  Wire.beginTransmission(MCP4725_ADDR); // start transmission to device
  Wire.write(MCP4725_CMD_WRITEDAC);
  Wire.write(i++);
  Wire.write((uint8_t)0x0);  // bottom four bits are 0x0
  result = Wire.endTransmission(); // end transmission, actually sending

  if (result == 0) Serial.println("Success"); else Serial.println("Fail");
 
  // Now check Wire2

  Serial.println("Now check the new second Wire");

  I2Cscan2();

  Wire2.beginTransmission(MCP4725_ADDR); // start transmission to device
  Wire2.write(MCP4725_CMD_WRITEDAC);
  Wire2.write(i++);
  Wire2.write((uint8_t)0x0);  // bottom four bits are 0x0
  result = Wire2.endTransmission(); // end transmission, actually sending

  if (result == 0) Serial.println("Success"); else Serial.println("Fail");
 
  delay(1000);
}

void I2Cscan() {
// scan for i2c devices
  uint8_t error, address;
  int nDevices;
  String msg;

  Serial.println("I2C Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission(true);
    if (error == 0)
    {
      msg = "I2C device found at address 0x";
      if (address<16) msg += "0";
      msg += String(address,HEX);
      msg += " ! ";
      Serial.println(msg);
      nDevices++;
    } else if (error==4) {
      msg = "Unknown error at address 0x";
      if (address<16)
        msg += "0";
      msg += String(address, HEX);
      Serial.println(msg);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found");
  else {
    msg = String(nDevices) + " I2C devices found";
    Serial.println(msg);
  }
  Serial.println("I2C scan done");
}

void I2Cscan2() {
// scan for i2c devices on Wire2
  uint8_t error, address;
  int nDevices;
  String msg;

//  Serial.println("test");
  Serial.println("I2C Second Wire Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
    Wire2.beginTransmission(address);
    error = Wire2.endTransmission(true);
    if (error == 0)
    {
      msg = "I2C device found at address 0x";
      if (address<16) msg += "0";
      msg += String(address,HEX);
      msg += " ! ";
      Serial.println(msg);
      nDevices++;
    } else if (error==4) {
      msg = "Unknown error at address 0x";
      if (address<16)
        msg += "0";
      msg += String(address, HEX);
      Serial.println(msg);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found");
  else {
    msg = String(nDevices) + " I2C devices found";
    Serial.println(msg);
  }
  Serial.println("I2C second Wire scan done");
}

RocketScientist
 
Posts: 87
Joined: Wed Jan 11, 2017 11:43 pm

Re: Second I2C Port on ItsyBitsy M4

by 42volts on Tue Feb 09, 2021 9:40 am

1k pull-ups may be a bit much. Try 2.2 or 4.7k.

And when in doubt as to communications, try a logic probe to see what is actually going on with the wires. You should put an analog lead to the SDA pin to see what is going on with the wave -- make sure that the slopes are nice and steep, and that its using the full range of 0-3V.

As for your performance issues, are you polling your sensors? Or are you making use of interrupt? Interrupt is a vastly better approach for sensors that support it, since it will only check the sensor data when it knows there is something to check.

42volts
 
Posts: 103
Joined: Sat Jan 19, 2019 11:20 am

Re: Second I2C Port on ItsyBitsy M4

by RocketScientist on Fri Apr 30, 2021 10:06 pm

Thanks for thoughts. In this application LOTS of sensors .. not enough interrupts. Too much wire. So some interrupts and lots of polling for sensors with known timing.

K

RocketScientist
 
Posts: 87
Joined: Wed Jan 11, 2017 11:43 pm

Please be positive and constructive with your questions and comments.