Arduino master to arduino slave code not working correctly

Great, good to know.
Was that situation different from the Sercom usage with sercom4 in I2C Slave mode as in the newest code ?
I hope you can make it work again. Can you try it with a single byte, without 'String' and without 'Serial' in the onRequest and onReceive interrupt handlers ?

That is not how it works. The official standard is the official standard. Only if you go back in time to about 1980 and tell the developers of the I2C bus that they are doing it wrong and they should do it differently, then you can change it. But you would no longer be in the same universe as us, because you have created a new time line.
You see what happens when you don't follow the standard of the I2C bus ? The whole universe is in danger.

It is too long ago that I used a ATSAMD21G, so I don't know anymore how those USB and native ports turned out.

The I2C bus works best with packages of data of a fixed length with binary data. For example an array of 'float' numbers or a 'struct'.
No one uses readable ASCII over the I2C bus.

When you use a Serial function inside an interrupt (such as the onRequest or onReceive handler), then you use a interrupt driven function inside a interrupt. That can go bad.
When you use the String class inside an interrupt, then the heap is used a lot. A interrupt routine should be shorter and simpler.

1 Like

yes, that was using the default i2c Wire. i cant get the new SERCOM i2c to work. i wonder if the Wire.h library is written in a way that prevents the

slaveWire.onRequest(requestEvent); // Register the onRequest event handler
slaveWire.onReceive(receiveEvent); // register event

from working on other SERCOM?

I still have 3 unmodified modules to play with.

the communication speed desired is so slow i would think using ASCII is fine?

I tried removing serial.prints and transmitting a byte. worked fine on unmodified module (default wire). got nothing on one using sercom4.

SLAVE CODE FOR TEST:

#include <Wire.h>
#include <Adafruit_SleepyDog.h>
#include "wiring_private.h" // pinPeripheral() function

#define slaveSDA PIN_PA12 //22 PA12
#define slaveSCL PIN_PA13 //38 PA13

TwoWire slaveWire(&sercom4, slaveSDA, slaveSCL);

String responseToSend; // This will hold the response to be sent

String command = "";

//#define Serial SerialUSB

/*********************************************************************************************************************
Setup and initilization function
*********************************************************************************************************************/

void setup() {

  Watchdog.enable(10000); // turn on watchdog timer with 10 seconds

  Serial.begin(9600);
  while (!Serial) delay(10);     // pause the serial port

  Serial.println(F("testing"));

//  Wire.begin();


  slaveWire.begin(0x20);                // join i2c bus with address 0x20

  // Assign pins to SERCOM functionality
  pinPeripheral(slaveSDA, PIO_SERCOM_ALT);
  pinPeripheral(slaveSCL, PIO_SERCOM_ALT);

  slaveWire.onReceive(receiveEvent); // register event

}

int x = 0;

void loop() {

  Watchdog.reset(); //resets the watchdog timer. basically, this makes sure the code doesnt lock up.

  delay(500);
  if (x != 0){
    Serial.println("XXX");
    x = 0;
  }

}

/*********************************************************************************************************************
i2c Slave Request and Recieve functions
*********************************************************************************************************************/

// I2C communication function for receiving data
void receiveEvent(int howMany){

//  while(1 < Wire.available()); // loop through all but the last

  x = slaveWire.read();    // receive byte as an integer
}

MASTER CODE FOR TEST:

#include <Wire.h>

void setup()
{
  pinModulesSetup();

  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 1;

void loop()
{
  selectModule(1);
  Wire.beginTransmission(0x20); // transmit to device #4
  Wire.write(x);              // sends one byte  
  Wire.endTransmission();    // stop transmitting

  delay(500);
}

/*********************************************************************************************************************
Pin Modules Setup Code
*********************************************************************************************************************/
//all four pin modules share an address. They are selected using a digital pin going "HIGH". This triggers an interupt in the selected slave and lets it recieve commands.

#define pinmoduleaddress 0x20

#define pinmodule3 49 //PA07 { PORTA, 7, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
#define pinmodule2 50 //PA15 { PORTA, 15, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
#define pinmodule1 51 //PB00 { PORTB, 0, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
#define pinmodule4 52 //PB01 { PORTB, 1, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },

void pinModulesSetup(){
  //Wire.begin(); // Start I2C
  pinMode(pinmodule1,OUTPUT);
  pinMode(pinmodule2,OUTPUT);
  pinMode(pinmodule3,OUTPUT);
  pinMode(pinmodule4,OUTPUT);
  selectModule(0); //deselect all modules
}

/*********************************************************************************************************************
Module Select Function
*********************************************************************************************************************/

int selectModule(int selection) {
  // Set all module pins to LOW initially
  digitalWrite(pinmodule1, LOW);
  digitalWrite(pinmodule2, LOW);
  digitalWrite(pinmodule3, LOW);
  digitalWrite(pinmodule4, LOW);

  // Select the appropriate module based on the input
  switch (selection) {
    case 1: digitalWrite(pinmodule1, HIGH); break;
    case 2: digitalWrite(pinmodule2, HIGH); break;
    case 3: digitalWrite(pinmodule3, HIGH); break;
    case 4: digitalWrite(pinmodule4, HIGH); break;
    case 0: return 0; // Deselection
    default: return 1; // Invalid selection, return error
  }
  return 0; // Successful selection
}

here are the wire.cpp and wire.h files for SAMD. perhaps a conflict that's preventing these commands is shown in here.

slaveWire.onRequest(requestEvent); // Register the onRequest event handler
slaveWire.onReceive(receiveEvent); // register event

/*
 * TWI/I2C library for Arduino Zero
 * Copyright (c) 2015 Arduino LLC. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef TwoWire_h
#define TwoWire_h

#include "Stream.h"
#include "variant.h"

#include "SERCOM.h"
#include "RingBuffer.h"

 // WIRE_HAS_END means Wire has end()
#define WIRE_HAS_END 1

class TwoWire : public Stream
{
  public:
    TwoWire(SERCOM *s, uint8_t pinSDA, uint8_t pinSCL);
    void begin();
    void begin(uint8_t, bool enableGeneralCall = false);
    void end();
    void setClock(uint32_t);

    void beginTransmission(uint8_t);
    uint8_t endTransmission(bool stopBit);
    uint8_t endTransmission(void);

    uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit);
    uint8_t requestFrom(uint8_t address, size_t quantity);

    size_t write(uint8_t data);
    size_t write(const uint8_t * data, size_t quantity);

    virtual int available(void);
    virtual int read(void);
    virtual int peek(void);
    virtual void flush(void);
    void onReceive(void(*)(int));
    void onRequest(void(*)(void));

    inline size_t write(unsigned long n) { return write((uint8_t)n); }
    inline size_t write(long n) { return write((uint8_t)n); }
    inline size_t write(unsigned int n) { return write((uint8_t)n); }
    inline size_t write(int n) { return write((uint8_t)n); }
    using Print::write;

    void onService(void);

  private:
    SERCOM * sercom;
    uint8_t _uc_pinSDA;
    uint8_t _uc_pinSCL;

    bool transmissionBegun;

    // RX Buffer
    RingBufferN<256> rxBuffer;

    //TX buffer
    RingBufferN<256> txBuffer;
    uint8_t txAddress;

    // Callback user functions
    void (*onRequestCallback)(void);
    void (*onReceiveCallback)(int);

    // TWI clock frequency
    static const uint32_t TWI_CLOCK = 100000;
};

#if WIRE_INTERFACES_COUNT > 0
  extern TwoWire Wire;
#endif
#if WIRE_INTERFACES_COUNT > 1
  extern TwoWire Wire1;
#endif
#if WIRE_INTERFACES_COUNT > 2
  extern TwoWire Wire2;
#endif
#if WIRE_INTERFACES_COUNT > 3
  extern TwoWire Wire3;
#endif
#if WIRE_INTERFACES_COUNT > 4
  extern TwoWire Wire4;
#endif
#if WIRE_INTERFACES_COUNT > 5
  extern TwoWire Wire5;
#endif

#endif
/*
 * TWI/I2C library for Arduino Zero
 * Copyright (c) 2015 Arduino LLC. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern "C" {
#include <string.h>
}

#include <Arduino.h>
#include <wiring_private.h>

#ifdef USE_TINYUSB
// For Serial when selecting TinyUSB
#include <Adafruit_TinyUSB.h>
#endif

#include "Wire.h"

TwoWire::TwoWire(SERCOM * s, uint8_t pinSDA, uint8_t pinSCL)
{
  this->sercom = s;
  this->_uc_pinSDA=pinSDA;
  this->_uc_pinSCL=pinSCL;
  transmissionBegun = false;
}

void TwoWire::begin(void) {
  //Master Mode
  sercom->initMasterWIRE(TWI_CLOCK);
  sercom->enableWIRE();

  pinPeripheral(_uc_pinSDA, g_APinDescription[_uc_pinSDA].ulPinType);
  pinPeripheral(_uc_pinSCL, g_APinDescription[_uc_pinSCL].ulPinType);
}

void TwoWire::begin(uint8_t address, bool enableGeneralCall) {
  //Slave mode
  sercom->initSlaveWIRE(address, enableGeneralCall);
  sercom->enableWIRE();

  pinPeripheral(_uc_pinSDA, g_APinDescription[_uc_pinSDA].ulPinType);
  pinPeripheral(_uc_pinSCL, g_APinDescription[_uc_pinSCL].ulPinType);
}

void TwoWire::setClock(uint32_t baudrate) {
  sercom->disableWIRE();
  sercom->initMasterWIRE(baudrate);
  sercom->enableWIRE();
}

void TwoWire::end() {
  sercom->disableWIRE();
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
{
  if(quantity == 0)
  {
    return 0;
  }

  size_t byteRead = 0;

  rxBuffer.clear();

  if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG))
  {
    // Read first data
    rxBuffer.store_char(sercom->readDataWIRE());

    // Connected to slave
    for (byteRead = 1; byteRead < quantity; ++byteRead)
    {
      sercom->prepareAckBitWIRE();                          // Prepare Acknowledge
      sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_READ); // Prepare the ACK command for the slave
      rxBuffer.store_char(sercom->readDataWIRE());          // Read data and send the ACK
    }
    sercom->prepareNackBitWIRE();                           // Prepare NACK to stop slave transmission
    //sercom->readDataWIRE();                               // Clear data register to send NACK

    if (stopBit)
    {
      sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);   // Send Stop
    }
  }

  return byteRead;
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{
  return requestFrom(address, quantity, true);
}

void TwoWire::beginTransmission(uint8_t address) {
  // save address of target and clear buffer
  txAddress = address;
  txBuffer.clear();

  transmissionBegun = true;
}

// Errors:
//  0 : Success
//  1 : Data too long
//  2 : NACK on transmit of address
//  3 : NACK on transmit of data
//  4 : Other error
uint8_t TwoWire::endTransmission(bool stopBit)
{
  transmissionBegun = false ;

  // Start I2C transmission
  if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) )
  {
    sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
    return 2 ;  // Address error
  }

  // Send all buffer
  while( txBuffer.available() )
  {
    // Trying to send data
    if ( !sercom->sendDataMasterWIRE( txBuffer.read_char() ) )
    {
      sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
      return 3 ;  // Nack or error
    }
  }
  
  if (stopBit)
  {
    sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
  }   

  return 0;
}

uint8_t TwoWire::endTransmission()
{
  return endTransmission(true);
}

size_t TwoWire::write(uint8_t ucData)
{
  // No writing, without begun transmission or a full buffer
  if ( !transmissionBegun || txBuffer.isFull() )
  {
    return 0 ;
  }

  txBuffer.store_char( ucData ) ;

  return 1 ;
}

size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
  //Try to store all data
  for(size_t i = 0; i < quantity; ++i)
  {
    //Return the number of data stored, when the buffer is full (if write return 0)
    if(!write(data[i]))
      return i;
  }

  //All data stored
  return quantity;
}

int TwoWire::available(void)
{
  return rxBuffer.available();
}

int TwoWire::read(void)
{
  return rxBuffer.read_char();
}

int TwoWire::peek(void)
{
  return rxBuffer.peek();
}

void TwoWire::flush(void)
{
  // Do nothing, use endTransmission(..) to force
  // data transfer.
}

void TwoWire::onReceive(void(*function)(int))
{
  onReceiveCallback = function;
}

void TwoWire::onRequest(void(*function)(void))
{
  onRequestCallback = function;
}

void TwoWire::onService(void)
{
  if ( sercom->isSlaveWIRE() )
  {
    if(sercom->isStopDetectedWIRE() || 
        (sercom->isAddressMatch() && sercom->isRestartDetectedWIRE() && !sercom->isMasterReadOperationWIRE())) //Stop or Restart detected
    {
      sercom->prepareAckBitWIRE();
      sercom->prepareCommandBitsWire(0x03);

      //Calling onReceiveCallback, if exists
      if(onReceiveCallback)
      {
        onReceiveCallback(available());
      }
      
      rxBuffer.clear();
    }
    else if(sercom->isAddressMatch())  //Address Match
    {
      sercom->prepareAckBitWIRE();
      sercom->prepareCommandBitsWire(0x03);

      if(sercom->isMasterReadOperationWIRE()) //Is a request ?
      {
        txBuffer.clear();

        transmissionBegun = true;

        //Calling onRequestCallback, if exists
        if(onRequestCallback)
        {
          onRequestCallback();
        }
      }
    }
    else if(sercom->isDataReadyWIRE())
    {
      if (sercom->isMasterReadOperationWIRE())
      {
        uint8_t c = 0xff;

        if( txBuffer.available() ) {
          c = txBuffer.read_char();
        }

        transmissionBegun = sercom->sendDataSlaveWIRE(c);
      } else { //Received data
        if (rxBuffer.isFull()) {
          sercom->prepareNackBitWIRE(); 
        } else {
          //Store data
          rxBuffer.store_char(sercom->readDataWIRE());

          sercom->prepareAckBitWIRE(); 
        }

        sercom->prepareCommandBitsWire(0x03);
      }
    }
  }
}

#if WIRE_INTERFACES_COUNT > 0
  /* In case new variant doesn't define these macros,
   * we put here the ones for Arduino Zero.
   *
   * These values should be different on some variants!
   */
  #ifndef PERIPH_WIRE
    #define PERIPH_WIRE          sercom3
    #define WIRE_IT_HANDLER      SERCOM3_Handler
  #endif // PERIPH_WIRE
  TwoWire Wire(&PERIPH_WIRE, PIN_WIRE_SDA, PIN_WIRE_SCL);

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

  #if defined(__SAMD51__)
    void WIRE_IT_HANDLER_0(void) { Wire.onService(); }
    void WIRE_IT_HANDLER_1(void) { Wire.onService(); }
    void WIRE_IT_HANDLER_2(void) { Wire.onService(); }
    void WIRE_IT_HANDLER_3(void) { Wire.onService(); }
  #endif // __SAMD51__
#endif

#if WIRE_INTERFACES_COUNT > 1
  TwoWire Wire1(&PERIPH_WIRE1, PIN_WIRE1_SDA, PIN_WIRE1_SCL);

  void WIRE1_IT_HANDLER(void) {
    Wire1.onService();
  }

  #if defined(__SAMD51__)
    void WIRE1_IT_HANDLER_0(void) { Wire1.onService(); }
    void WIRE1_IT_HANDLER_1(void) { Wire1.onService(); }
    void WIRE1_IT_HANDLER_2(void) { Wire1.onService(); }
    void WIRE1_IT_HANDLER_3(void) { Wire1.onService(); }
  #endif // __SAMD51__
#endif

#if WIRE_INTERFACES_COUNT > 2
  TwoWire Wire2(&PERIPH_WIRE2, PIN_WIRE2_SDA, PIN_WIRE2_SCL);

  void WIRE2_IT_HANDLER(void) {
    Wire2.onService();
  }

  #if defined(__SAMD51__)
    void WIRE2_IT_HANDLER_0(void) { Wire2.onService(); }
    void WIRE2_IT_HANDLER_1(void) { Wire2.onService(); }
    void WIRE2_IT_HANDLER_2(void) { Wire2.onService(); }
    void WIRE2_IT_HANDLER_3(void) { Wire2.onService(); }
  #endif // __SAMD51__
#endif

#if WIRE_INTERFACES_COUNT > 3
  TwoWire Wire3(&PERIPH_WIRE3, PIN_WIRE3_SDA, PIN_WIRE3_SCL);

  void WIRE3_IT_HANDLER(void) {
    Wire3.onService();
  }

  #if defined(__SAMD51__)
    void WIRE3_IT_HANDLER_0(void) { Wire3.onService(); }
    void WIRE3_IT_HANDLER_1(void) { Wire3.onService(); }
    void WIRE3_IT_HANDLER_2(void) { Wire3.onService(); }
    void WIRE3_IT_HANDLER_3(void) { Wire3.onService(); }
  #endif // __SAMD51__
#endif

#if WIRE_INTERFACES_COUNT > 4
  TwoWire Wire4(&PERIPH_WIRE4, PIN_WIRE4_SDA, PIN_WIRE4_SCL);

  void WIRE4_IT_HANDLER(void) {
    Wire4.onService();
  }

  #if defined(__SAMD51__)
    void WIRE4_IT_HANDLER_0(void) { Wire4.onService(); }
    void WIRE4_IT_HANDLER_1(void) { Wire4.onService(); }
    void WIRE4_IT_HANDLER_2(void) { Wire4.onService(); }
    void WIRE4_IT_HANDLER_3(void) { Wire4.onService(); }
  #endif // __SAMD51__
#endif

#if WIRE_INTERFACES_COUNT > 5
  TwoWire Wire5(&PERIPH_WIRE5, PIN_WIRE5_SDA, PIN_WIRE5_SCL);

  void WIRE5_IT_HANDLER(void) {
    Wire5.onService();
  }

  #if defined(__SAMD51__)
    void WIRE5_IT_HANDLER_0(void) { Wire5.onService(); }
    void WIRE5_IT_HANDLER_1(void) { Wire5.onService(); }
    void WIRE5_IT_HANDLER_2(void) { Wire5.onService(); }
    void WIRE5_IT_HANDLER_3(void) { Wire5.onService(); }
  #endif // __SAMD51__
#endif

so i took another module, this time modifying it for

#define slaveSDA 11
#define slaveSCL 13

still doesnt work as slave. tried both 6K and 1K pullups. seems to just lockup after a short while.

so i tried another approach: hardcoding the interface into the variant file... and it works?! so i think i have pretty much proven that onReceive and onRequest only work in the hard defined i2c pins?? why might this be? is there a workaround?

  // Digital High
  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
  { PORTA, 16, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // TCC2/WO[0] D11 SDA U11
  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]

  // 13 (LED)
  { PORTA, 17, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // TCC2/WO[1] D13 SCL U13
/*
 * Wire Interfaces
 */
#define WIRE_INTERFACES_COUNT 3

#define PIN_WIRE_SDA         (26u)
#define PIN_WIRE_SCL         (27u)
#define PERIPH_WIRE          sercom3
#define WIRE_IT_HANDLER      SERCOM3_Handler

static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;


#define PIN_WIRE1_SDA         (11u) //D11
#define PIN_WIRE1_SCL         (13u) //D13
#define PERIPH_WIRE1          sercom1
#define WIRE1_IT_HANDLER      SERCOM1_Handler

static const uint8_t SDA1 = PIN_WIRE1_SDA;
static const uint8_t SCL1 = PIN_WIRE1_SCL;

#define PIN_WIRE2_SDA         (28u) //D22 PA12
#define PIN_WIRE2_SCL         (39u) //D38 PA13
#define PERIPH_WIRE2          sercom2
#define WIRE2_IT_HANDLER      SERCOM2_Handler

static const uint8_t SDA2 = PIN_WIRE2_SDA;
static const uint8_t SCL2 = PIN_WIRE2_SCL;

Which board are you using as a reference ? The Arduino Zero or the Arduino MKR Zero or the Arduino M0 (mzero) ? There is a big difference between them.

Arduino Zero: https://store.arduino.cc/products/arduino-zero
Arduino MKR Zero: https://store.arduino.cc/collections/mkr-family/products/arduino-mkr-zero-i2s-bus-sd-for-sound-music-digital-audio-data

The Zero has one I2C bus defined here: https://github.com/arduino/ArduinoCore-samd/blob/master/variants/arduino_zero/variant.h
Sercom3 is used.

The MKR Zero has one I2C bus defined here: https://github.com/arduino/ArduinoCore-samd/blob/master/variants/mkrzero/variant.h
Sercom2 is used.

The common Wire library that uses those settings is here: https://github.com/arduino/ArduinoCore-samd/blob/master/libraries/Wire/Wire.h

I have used information from Adafruit in the past to add ports, but you might use a combination that does not work. Can you stick with the Arduino settings ?

my modules are now 100% functional with two separate i2c ports. the issue is that i had to "hard define" them in the variant file as described. I could in the .ino create new i2c ports as master, but it wouldn't work as slave.

Adafruit bootloader and board files. Feather M0 Express.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.