Wire1 not working

Hey,

Just thought I’d let everyone know the secret to getting Wire1 to work on the Electron.

I’ve been trying to test an i2c slave device using the C5 and C4 i2c peripheral, which is mapped to the Wire1 object.

I kept getting to Wire1.endTransmission() and encountering an SOS hard fault.

If I switched to using Wire instead of Wire1, everything worked properly, with no fault.

After a few hours of trying to figure out the problem, I tried simply including the following code at the beginning of the setup() function:

pinMode(C5, OUTPUT); 
pinMode(C4, OUTPUT);

This got rid of the hard fault condition and allowed things to work properly.

Here is the program that results in a hard fault:

#include "Particle.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

SerialLogHandler logHandler(LOG_LEVEL_TRACE,  //Default logging level for non-application messages
   {
      { "app", LOG_LEVEL_ALL },       //Logging level for logs from "app" log category
      { "app.main", LOG_LEVEL_ALL},  //Logging level for logs from "app.main" log category
   });

Logger myLog("app.main");  //Logger object used in this "main" file

void setup(){

   Serial.begin(115200);

   delay(8000); //Time to open the serial monitor
   
   myLog.trace("Now calling Wire1.begin");
   Wire1.begin();
   delay(1000);
   myLog.trace("Now calling Wire1.beginTransmission()");
   delay(10);
   Wire1.beginTransmission(0b0110101);
   delay(10);
   myLog.trace("Now calling Wire1.write()");
   delay(10);
   Wire1.write(0xa8);
   delay(10);
   myLog.trace("Now calling Wire1.endTransmission()");
   delay(10);
   Wire1.endTransmission();
   delay(10);
   myLog.trace("Finished calling all Wire1 functions");
   delay(1000);
   myLog.trace("Now exiting setup()");
}
void loop(){
}

and here is the modified code that ends up working:

#include "Particle.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

SerialLogHandler logHandler(LOG_LEVEL_TRACE,  //Default logging level for non-application messages
   {
      { "app", LOG_LEVEL_ALL },       //Logging level for logs from "app" log category
      { "app.main", LOG_LEVEL_ALL},  //Logging level for logs from "app.main" log category
   });

Logger myLog("app.main");  //Logger object used in this "main" file

void setup(){

   Serial.begin(115200);

   pinMode(C5, OUTPUT);
   pinMode(C4, OUTPUT);

   delay(8000); //Time to open the serial monitor
   
   myLog.trace("Now calling Wire1.begin");
   Wire1.begin();
   delay(1000);
   myLog.trace("Now calling Wire1.beginTransmission()");
   delay(10);
   Wire1.beginTransmission(0b0110101);
   delay(10);
   myLog.trace("Now calling Wire1.write()");
   delay(10);
   Wire1.write(0xa8);
   delay(10);
   myLog.trace("Now calling Wire1.endTransmission()");
   delay(10);
   Wire1.endTransmission();
   delay(10);
   myLog.trace("Finished calling all Wire1 functions");
   delay(1000);
   myLog.trace("Now exiting setup()");
}
void loop(){
}
1 Like

Which system firmware are you using?

I tried 0.6.1 originally, and then 0.6.0 when that didn’t work. I haven’t tried the 0.5.x versions

@Bdub, i see that Wire atuff didn’t get changed for a while now. Did a regression got introduced somewhere?

Hey all! So I can confirm this is an issue. Unfortunately it’s been around for a long time (broken on 0.5.0). There is a work around, and seems to only be required for C5. I would suggest using INPUT so as not to change the state of the I2C bus prior to Wire1.begin(). I found another subtle thing to resolve and logged an issue here:

1 Like

Thanks so much! I was beating my head against the wall on this one, thinking I was doing something wrong that was too subtile for me to find.

Never mind! Syntax error bites again! I had Wire.endTransmission(); instead of Wire1.endTransmission();
I’m leaving this as a reminder to double check that you haven’t accidentally left off a “1” somewhere when getting unexpected behavior.
[Has anyone been successful in writing to any registers of a device via Wire1? After using this fix I have been able to read registers of a MCP23008, (verified by changing the GPIO inputs, as well as reading default values from various registers) but I’m unable to set the GPPU (0x06) register to enable the internal pull up resistors.]