Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Teensy 3.2 Holds I2C Bus Low

  1. #1
    Junior Member
    Join Date
    Dec 2018
    Posts
    4

    Teensy 3.2 Holds I2C Bus Low

    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.

    Click image for larger version. 

Name:	i2c.jpg 
Views:	18 
Size:	28.4 KB 
ID:	15396

    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.

    Click image for larger version. 

Name:	Capture.PNG 
Views:	21 
Size:	519.9 KB 
ID:	15395

    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("");
    }
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	i2cmsg.jpg 
Views:	10 
Size:	30.7 KB 
ID:	15394  

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,318
    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.

  3. #3
    Junior Member
    Join Date
    Dec 2018
    Posts
    4
    Multi Master Mode with the assumption that arbitration will not be needed.

  4. #4
    Junior Member
    Join Date
    Dec 2018
    Posts
    4
    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

  5. #5
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,939

    Cool

    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.

  6. #6
    Junior Member
    Join Date
    Dec 2018
    Posts
    4
    Michael - thanks for the suggestions! I have answered some of them below.

    Quote Originally Posted by MichaelMeissner View Post
    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.

    Quote Originally Posted by MichaelMeissner View Post
    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

    Quote Originally Posted by MichaelMeissner View Post
    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?

  7. #7
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,511
    For the Teensy, they don't need to run at +5V - +3v3 are better But some old devices need 5V.

  8. #8
    Senior Member
    Join Date
    May 2017
    Posts
    195
    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 by rcarr; 12-20-2018 at 03:07 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •