Teensy 3.2 Holds I2C Bus Low

Status
Not open for further replies.

labianco

New member
Hi All,

Firstly - I am no I2C expert and am trying to connect the Teensy 3.2 to another, custom, digital I2C master device.

This other device uses a customized version of I2C as shown below. The first byte is the typical I2C address & R/W bit with the other bytes being custom data. There are no special commands like read or write to certain registers like the I2C data link layer uses.

i2c.jpg

Once the other device receives the payload4 it responds with a message like the one above. Below is a screen shot of the bus when the other device sends that response to the teensy. It appears that once the teensy latches the address, it pulls the bus low and keeps it low forever (shown in the picture). I did try changing "Wire.begin(MY_ADDR);" to "Wire.begin();", and that prevented the teensy from pulling the bus low, but it never did enter the onReceive callback. In another modified version of the attached code I would send another message to the other device from the Teensy after it pulled the bus low, and it would send, but it would return low again afterwards.

Capture.PNG

So, what do I need to do to get the teensy to correctly receive this message format over I2C?

Code:
#include <Wire.h>

#define MY_ADDR 0x3A
#define YOUR_ADDR 0x00
int number;

byte payload4[] = {0x20, 0xFA, 0x10, 0x11, 0x03, 0x01, 0x0F, 0x0F, 0xFF, 0xFF, 0x00, 0xBA};

void setup() {
  Serial.begin(115200);
  delay(5000);
  Serial.println("working");
  Wire.begin(MY_ADDR);  
  Wire.onReceive(receiveData);

}

void loop() {
  Serial.println("\nHERE 1");
  Wire.beginTransmission(YOUR_ADDR);
  Wire.write(payload4, 9);
  Wire.endTransmission();
  delay(5000);
  
  // 2nd device sends data to teensy here
  
  // do nothing
  while(1){};

}

void receiveData(int howMany){
  while(Wire.available() > 0) {
    char c = Wire.read();
    // Serial.print(c, HEX);
    // Serial.print(" ");
  }
  // Serial.println("");
}
 

Attachments

  • i2cmsg.jpg
    i2cmsg.jpg
    30.7 KB · Views: 102
Wire.begin(adr) puts the Teensy in slave mode, while Wire.begin() puts the Teensy in master mode where the target address will be determined by beginTransmission(adr).

You did not make clear, neither in your description nor in your code, which device should take the master and which the slave role. So, first step would be studying the data sheet of your I2C device and the role it takes.
 
Registers after teensy sends to other device and before teensy receives address byte from other device.

I2C0_A1 : 74
I2C0_F : 28
I2C0_C1 : 80
I2C0_S : 80
I2C0_D : ba
I2C0_C2 : 20
I2C0_FLT : 3
I2C0_RA : 0
I2C0_SMB : 0
I2C0_A2 : c2
I2C0_SLTH: 0
I2C0_SLTL: 0

Registers after Teensy receives address byte from other device (and bus pulled low)

I2C0_A1 : 74
I2C0_F : 28
I2C0_C1 : 80
I2C0_S : e2
I2C0_D : 74
I2C0_C2 : 20
I2C0_FLT : 3
I2C0_RA : 0
I2C0_SMB : 0
I2C0_A2 : c2
I2C0_SLTH: 0
I2C0_SLTL: 0
 
A common problem with Teensys and i2c is that on the Teensy you need to have 2 pull-up resistors, 1 between SDA and 3.3v, and the other between SCL and 3.3v somewhere on the bus. Typically, for a Teensy and 3.3v, you would use 2.2K. But you could use a higher value (4.7K is common on 5v Arduino systems).

A second problem might be the i2c bus speed. Make sure both systems are configured to use the same speed. By default, the Teensy uses the default 100kbs.

A third problem could be the other i2c device needs to be running at 5v and not 3.3v. There you would need to use voltage level shifters to convert the voltage in both directions.

A fourth problem could be the wires are too long, or this is other electrical noise that is corrupting the communication.

There is an alternative Teensy i2c driver. To use it, you would need to change the Wire.h include file to i2c_t3.h. Note, you have to do it in all of the libraries, so it is problematical if you are using a standard i2c device with its own library.
 
Michael - thanks for the suggestions! I have answered some of them below.

A common problem with Teensys and i2c is that on the Teensy you need to have 2 pull-up resistors, 1 between SDA and 3.3v, and the other between SCL and 3.3v somewhere on the bus. Typically, for a Teensy and 3.3v, you would use 2.2K. But you could use a higher value (4.7K is common on 5v Arduino systems).

I am using 4.7k to +3.3V.

A second problem might be the i2c bus speed. Make sure both systems are configured to use the same speed. By default, the Teensy uses the default 100kbs.

The other device is running at 100k

A third problem could be the other i2c device needs to be running at 5v and not 3.3v. There you would need to use voltage level shifters to convert the voltage in both directions.

My other device is running at 3.3V. Why does it need to run at +5V?
 
Your waveform seems to show an address of 0x74 on the bus, not 0x3A. And yet it seems it was ACK'd successfully. Something funny is happening.

Edit: Those bits are shifted, so it is sending 0x3A as you say.
 
Last edited:
Status
Not open for further replies.
Back
Top