I2C - wire.h issue

Status
Not open for further replies.

danko

Member
I am using a teensy 3.2. I have an IO extender I2C chip which controls a bunch of relays. I previously had my code tested and working. I just went back and it no longer works. It almost seems as if the begin, write and end transmissions are just being glossed over. When i call Wire.begin() to setup i can successfully init to as desired state. After that point, i get inside the function in my code that changes the bytes to be set via I2C but no change occurs. I also have a test code program that i count up from 0 to 255 and each increment I update the peripheral successfully. So I know that the hardware works, its something in software that is causing me issues. Have you guys noticed any odd dependencies, initialization issues, update issues, etc. that would not throw an error flag and also not write a new transmission?

I know one of the forum rules is that i have to post my source code. Unfortunately, at this time, that is not possible for me. I guess i am just looking for troubleshooting guidance, a direction to head down in trying to find the issue.

With gratitude,
danko
 
To answer your question "have you guys noticed any odd dependencies, initialization issues, update issues", yes we've seem lots of strange problems reported on this forum. Sometimes "odd dependencies" turn out to be code that writes past the end of an array, sometimes an off-by-1 error, sometimes a mistake in declaring the array, sometimes other reasons. These can be very odd since the problem manifests in other places, depending on what other variables got overwritten.

Actual conflicts like i2c_t3.h vs Wire.h almost always result in compiler errors. Strange hardware issues like noise coupling onto the SDA or SCL signals causing an arbitration loss error (Teensy believe some other I2C master took control) are properly reported with error status.

There are *lots* of these old threads on this forum. I'm sure you can find many by searching. Unfortunately that's about the best help anyone can give if you can't show us your code & hardware. If you're really stuck, maybe try reducing the code and hardware to something simpler which you can share. We're pretty good at helping when we can see the complete code and photos of the real hardware...
 
Hi Paul,

I will get some code snippets up in a couple hours. Here is what I have learned in the past 24 hours.

When I init the I2C bus I hard code a state (say 0xAA). I then proceed to update with a new hard coded value (say 0xFF). It inits fine but will never update. Upon observing on a scope, the uC is continually sending the init hard code. It never changes to the updated value and my scope keeps triggering on the init value. I'm not an I2C except by any stretch of the imagination but it was my understanding that it is a once and done transmission (not continually sending until it gets different data to send).

To muddy the water even more, I can no longer open the serial monitor. I have been troubleshooting the issue and found this: https://forum.pjrc.com/threads/4607...-on-serial-port-already-tried-troubleshooting
I tried the steps in the guide and it doesn't appear to be a windows issue but a code issue (my suspicion is that its closely related to this I2C issue). I come to that conclusion because if I upload my simple I2C sketch to control the relays (referenced in last post -- counts from 0-255 turning on and off 8 relays -- each bit mapped to a relay) it not only controls each relay but it also send my serial prints to the monitor.

The behavior in my other program is that it can't find the com port in the tools drop down menu. If it does find the com port it will not open the com port. It will either say that the com port does not exist or that it tried to open but failed. It seems to me that there is a wider communication issue I am dealing with here (especially considering I had all of this working only a few short weeks ago).

I'll upload some code shortly.
 
Step 1: Run setup function
Code:
void setupI2C(uint8_t *x, uint8_t *y)
{
//not using *x and *y at the moment due to debugging
//Wire.begin();
// Setup for Master mode, pins 18/19, external pullups, 400kHz, 200ms default timeout
Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
Wire.setDefaultTimeout(200000); // 200ms
uint8_t address = (ADDRESS_HARDCODE | ADDRESS_0 | ADDRESS_1 | ADDRESS_2);
Wire.beginTransmission(address);
Wire.write(0xAA); //normally init to off but hardcoding for debugging purposes
Wire.write(0x11); //normally init to off but hardcoding for debugging purposes
Wire.endTransmission();
Serial.println("I2C setup complete");
}

Step 2: run decode function on incoming message from external PC
Code:
void decodeAndCall(struct messageVar *sortedRx, uint8_t *returnStatus, uint8_t index, uint8_t
*I2C_word1, uint8_t *I2C_word2, uint32_t status2)
{
//deleted non‐pertinent code for demonstration purposes
else if (String("@PwrOn").compareTo(sortedRx[index].prefix) == 0)
{
//Serial.println("POWER ON");
// Serial.flush();
Serial.print(*I2C_word1); Serial.print(" "); Serial.println(*I2C_word2);
Serial.flush();
powerOn(sortedRx[index].data, I2C_word1, I2C_word2, status2);
Serial.print(*I2C_word1); Serial.print(" "); Serial.println(*I2C_word2);
Serial.println();
Serial.flush();
}
//deleted non‐pertinent code for demonstration purposes
}

step 3: step 2 calls powerOn()
Code:
void powerOn(uint8_t powerOnMessage, uint8_t *I2C_Byte, uint8_t *I2C_NoChange, uint32_t Status2)
{
Serial.println(*I2C_Byte, HEX);
Serial.flush();
if (powerOnMessage & ON_RELAY1)
{
*I2C_Byte &= ~RELAY1;
Serial.print("Turning on relay\r\n");
}
if (powerOnMessage & ON_RELAY2)
{
*I2C_Byte &= ~RELAY2;
}
//deleted non‐pertinent code for demonstration purposes
uint8_t address = (ADDRESS_HARDCODE | ADDRESS_0 | ADDRESS_1 | ADDRESS_2);
Serial.println(*I2C_Byte, HEX);
Serial.flush();
Wire.beginTransmission(address);
Wire.write(0x00); //hardcoded to show a change from the init condition. No change occurs.
Wire.write(0xFF);
Wire.endTransmission();
}

Working simple program:
Code:
#include <i2c_t3.h>
// all signals | together below
#define ADDRESS_0 (0<<0) //(1<<0) if set
#define ADDRESS_1 (0<<1) //(1<<1) if set
#define ADDRESS_2 (0<<2) //(1<<2) if set
#define ADDRESS_HARDCODE (1<<5)
uint8_t counter = 0;
bool led = false;
void setupI2C()
{
Wire.begin();
Serial.println("I2C setup complete");
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
setupI2C();
Serial.println("INIT");
Serial.flush();
pinMode(13, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
uint8_t address = (ADDRESS_HARDCODE | ADDRESS_0 | ADDRESS_1 | ADDRESS_2);
Wire.beginTransmission(address);
Wire.write(counter);
Wire.write(255‐counter);
Wire.endTransmission();
led = !led;
digitalWrite(13, led);
delay(1000);
Serial.println(counter);
Serial.flush();
counter++;
}
 
Okay, using this post i switched to an emulated serial monitor: https://forum.pjrc.com/threads/639-Teensy-3-0-serial-monitor-not-working

That got my serial monitor back on line.

The display out is as follows, i have added comments to each line of the serial monitor output:

Code:
@PwrOn1     //from main
255   255     //word 1 and word 2 in main before decode function
255   255     //word 1 and word 2 decode function before powerOn function
FF              //word 2 in powerOn before being changed
Turning on relay //shows that it is getting in the else if statement to turn on relay
FE              //toggled the 1st bit to control the 1st relay
FAIL           //the output of Wire.getError() //runs at the end of powerOn when trying to set I2C bits //not shown in above code
255   254    //in decode and call after power on function

So for some reason the I2C is failing. Any ideas?
 
Do these problems happen if you use the Wire.h library?

They do. I originally was working from a tutorial on pjrc that used the wire.h library. In debugging this issue i found the teensy 3 I2C lib and thought that may be the issue. I see no change with either library.
 
SCL and SDA are both high. I'm hanging in the powerOn function when I try and transmit. If i comment out that code it is continually going through the loop. With that code, my hardware watchdog timer is resetting the uC.
 
With p#3 USB Serial Monitor not working - and p#8 triggering watchdog it seems the code is running the chip off into the 'weeds' with unexpected execution.

With a delay to assure PC connects to USB in setup() it should be able to print incremental progress - without a wait as below SerMon won't be online before the Teensy goes offline:
Code:
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 5000 )
  { Serial.print( "Teensy NOT Online @ millis=" );
    Serial.println( millis() );
    delay(30);
  }
  Serial.print( "Teensy Online @ millis=" );
  Serial.println( millis() );
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);

[B]  // more setup code here …[/B]

}

With a change like that the SerMon should connect and be usable up toward the point of failure. If that doesn't work - there is a larger problem.
 
defragster: That is an extremely helpful piece of code. Thank you for that.

Status update: Serial monitor works consistently now that I have the above code. My I2C bus works again. I was going through step by step disabling functionality and testing and it turns out I was accidentally using pin 19 for two different things. I switched my I2C bus to alternate pins and it fired right back up.

Thanks for all your guys help.
 
Status
Not open for further replies.
Back
Top