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

Thread: apparent bug in wire library (i2c_t3) with Teensy 3.5

  1. #1
    Junior Member
    Join Date
    Feb 2019
    Location
    Vancouver, BC
    Posts
    16

    apparent bug in wire library (i2c_t3) with Teensy 3.5

    I am trying to use a BMP085 pressure/temperature sensor with a Teensy 3.5. The BMP085 is on a Sparkfun board (their SEN-09694), connected through a level shifter (SparkFun BOB-11955). The code I'm using is from AdaFruit. To reduce complexity, I've merged the AdaFruit code into one program instead of using #includes, and I've eliminated some AdaFruit code that is not relevant.
    This works perfectly when the connection is made through the default I2C lines (pins D18 & D19), but it fails when I use the I2C lines at D03 & D04. In other words, the attached code fails (it does not find the expected 0x55 in the ChipID register) when the asterisk-heavy lines in
    Code:
    bool Adafruit_BMP085_Unified::begin(bmp085_mode_t mode)
      {
        // Enable I2C
        Wire.setSDA(pinBMP085SDA);  // Teensy-specific ************************
        Wire.setSCL(pinBMP085SCL);  // ..              ************************
        Wire.begin();
     
        /* Mode boundary check */
        if ((mode > BMP085_MODE_ULTRAHIGHRES) || (mode < 0))
          {   mode = BMP085_MODE_ULTRAHIGHRES;  }
    
        /* Make sure we have the right device */
        uint8_t id;
        read8(BMP085_REGISTER_CHIPID, &id);
        if (id != 0x55)
          {  return false;  }
    
        _bmp085Mode = mode;
    
        readCoefficients(); // coefficients need to be read once 
    
        return true;
      } // Adafruit_BMP085_Unified::begin(bmp085_mode_t mode)
    are left in place and the BMP085 is at D03 & D04, but it works when those lines are commented out and the sensor is moved to D18 & D19. Is there a known fix?
    Attached Files Attached Files

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,998
    The sparkfun library is based on Wire lib, but you have also included i2c_t3.h library which is not compatible with Wire.h -- you can't use them both in one sketch. For example, the begin() for each library differs, for i2c_t3.h, you specify alternate SDA/SCL pins in the begin() call. Read the documentation and choose one and carefully edit the sketch. I would stick with the Sparkfun default Wire lib and get rid of i2c_t3 references ... there could be other problems with your "reduced complexity"

    pins 3 and 4 are on I2C2 on T3.5, so your Wire.xxxx() calls need to be Wire2.xxxx()

  3. #3
    Junior Member
    Join Date
    Feb 2019
    Location
    Vancouver, BC
    Posts
    16
    Quote Originally Posted by manitou View Post
    The sparkfun library is based on Wire lib, but you have also included i2c_t3.h library which is not compatible with Wire.h -- you can't use them both in one sketch. For example, the begin() for each library differs, for i2c_t3.h, you specify alternate SDA/SCL pins in the begin() call. Read the documentation and choose one and carefully edit the sketch. I would stick with the Sparkfun default Wire lib and get rid of i2c_t3 references ... there could be other problems with your "reduced complexity"

    pins 3 and 4 are on I2C2 on T3.5, so your Wire.xxxx() calls need to be Wire2.xxxx()
    Thanks for your quick response.

    I had not run across any mention of Wire2 before, but it makes sense, analogous to Serial1, Serial2, etc. After a quick look, I don't see where any of the Wire<n> entities are declared; are they present whenever one includes the Teensy version of Wire.h?

    I had had the impression that i2c_t3 was a drop-in replacement, but obviously that's not true.

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,783
    source search shows Wire2 in these two files for current Teensy:
    ...\hardware\teensy\avr\libraries\Wire\WireKinetis .cpp:
    ...\hardware\teensy\avr\libraries\Wire\WireKinetis .h:
    i2c_t3 uses the same hardware generally to the same net effect - with some alternate/added Teensy specific features.

    @manitou's note was that when doing include of i2c_t3.h the include of wire.h must be removed.

  5. #5
    Junior Member
    Join Date
    Feb 2019
    Location
    Vancouver, BC
    Posts
    16

    Teensy library code providing i2c services

    This situation is messier than I had thought. There are at least 3 Teensy library packages providing I2C services. The AdaFruit code to control the BMP085 makes explicit use of a Wire object, and it expects that object to have methods write(unsigned char), endTransmission(unsigned char), and requestFrom(unsigned char, unsigned char, unsigned char) (the "old methods").
    1. Wire.h/Wire.cpp is the old package. Its TwoWire class has setSDA and setSCL methods, but the implementations of those methods are empty. It defines a TwoWire instance called Wire. If my code
      • #includes Wire.h
      • adds calls to setSDA and setSCL to the AdaFruit code to control the BMP085

      then my code compiles, but because the setSDA & setSCL calls have no effect, the AdaFruit code cannot talk to any I2C device that is not connected to the default pins (on Teensy 3.5, D18 & D19).
    2. WireKinetis.h/Wirekinetis.cpp is newer. Its TwoWire class has nondegenerate setSDA and setSCL methods, and in the Teensy 3.5 environment it defines TwoWire instances called Wire, Wire1, Wire2, and Wire3. Its write, endTransmission, and requestFrom methods take uint8_t arguments instead of unsigned chars. if my code
      • #includes WireKinetis.h
      • adds calls to setSDA and setSCL to the AdaFruit code to control the BMP085

      then my code does not compile, because of the missing old methods.
    3. i2c_t3.h/i2c_t3.cpp is the new, Teensy 3.5-specific package. The i2c_t3 class has nondegenerate setSDA and setSCL methods, and it defines i2c_t3 instances called Wire, Wire1, Wire2, and Wire3.
      if my code
      • #includes i2c_t3.h
      • adds calls to setSDA and setSCL to the AdaFruit code to control the BMP085

      then my code compiles, but the setSDA and setSCL calls don't work to make the Wire object use pins other than those of Wire1.


    Is there a non-ugly option? I think I may be stuck with generating
    • my own version of WireKinetis.h, to provide the old methods
    • my own version of the AdaFruit BMP085 code, replacing Wire by Wire2

    Neither of those tasks will be intellectually demanding, but I'm disappointed that I can't see any better way to finish off this tiny piece of a much bigger project.
    Last edited by Fenichel; 06-10-2019 at 12:36 AM. Reason: typo

  6. #6
    Junior Member
    Join Date
    Feb 2019
    Location
    Vancouver, BC
    Posts
    16

    Smile solved

    A good solution turns out to be
    • to not use Wire.h
    • to not use WireKinetis.h
    • to use i2c_t3.h
    • to not use setSDA or setSCL, and
    • to revise the Adafruit BMP085 code, replacing every instance of Wire with Wire2

    This solution won't allow my code to switch easily among two or more BMP085s on different I2C interfaces, but I don't anticipate that need.

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,783
    A #define Wire Wire2 in the code/.h worked for the one I tried - when swapping in i2c_t3.h and removing the wire.h include

  8. #8
    Junior Member
    Join Date
    Feb 2019
    Location
    Vancouver, BC
    Posts
    16
    Quote Originally Posted by defragster View Post
    A #define Wire Wire2 in the code/.h worked for the one I tried - when swapping in i2c_t3.h and removing the wire.h include
    I thought of that, but I dislike using #defines to do more than set parameters. Using them to change the meaning of code makes me nervous. It's just a matter of style.

Posting Permissions

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