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

Thread: #include file hell, again :(

  1. #1
    Senior Member
    Join Date
    Jun 2017
    Posts
    249

    #include file hell, again :(

    I've been trying to bring my projects up to date with respect to using #include <Wire.h> vs #include <i2c_t3.h>. I thought I had everything completely worked out, but after converting my project from i2c_t3.h to Wire.h, it won't compile and produces errors like the following

    Code:
    T35_WallE3_V5.ino: 603:48: error: 'I2C_PULLUP_EXT' was not declared in this scope
       Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT); \\MPU6050,IR_DET. MPU6050 has 4.7K pullups

    Here's the relevant portions of the code (I've attached the entire program as a ZIP file)

    Code:
    #pragma region INCLUDES
    #include <Wire.h>
    #include "FlashTxx.h"		// TLC/T3x/T4x flash primitives
    #include <elapsedMillis.h>
    //#include "MPU6050_6Axis_MotionApps_V6_12.h"  //changed to this version 10/05/19
    //#include "MPU6050_6Axis_MotionApps_V6_12.h"  //01/18/22 changed to use the \I2CDevLib\Arduino\MPU6050\ version
    #include "MPU6050_6Axis_MotionApps612.h"  //01/18/22 changed to use the \I2CDevLib\Arduino\MPU6050\ version
    #include "I2Cdev.h" //02/19/19: this includes SBWire.h
    #include "I2C_Anything.h" //needed for sending float data over I2C
    #include "I2C_Anything1.h" //01/16/22 added for Wire1 bus
    #include <PID_v2.h> //new version 05/16/21 
    #include "timelib.h" //added 01/01/22 for charge monitoring support
    #include "TeePrint.h" //added 01/04/22 to print to both ports in one line
    #pragma endregion Includes
    
    void setup()
    {
    #pragma region PIN INITIALIZATION
    
      //init ALL pins to OUTPUT_LOW, then change as necessary
      //01/08/22 - THIS MUST BE FIRST STEP IN SETUP() (ask me how i know!)
      //InitAllPins(); 
    
      pinMode(LED_BUILTIN, OUTPUT);
    
    #pragma region Teensy VL53L0X Array Init
      //11/15/20 force VL53L0X Teensy to reset whenever main controller does
      pinMode(VL53L0X_TEENSY_RESET_PIN, OUTPUT);
      digitalWrite(VL53L0X_TEENSY_RESET_PIN, LOW);
      delay(50);
      digitalWrite(VL53L0X_TEENSY_RESET_PIN, HIGH);
    #pragma endregion Teensy VL53L0X Array Init
    
    #pragma region Second Deck Pins
      pinMode(RED_LASER_DIODE_PIN, OUTPUT);
      pinMode(LIDAR_MODE_PIN, INPUT);
      pinMode(VL53L0X_TEENSY_RESET_PIN, OUTPUT);
    #pragma endregion Second Deck Pins
    
    #pragma region Charge_Support_Pins
      //current sensor pins
      pinMode(RUN_CURR_PIN, INPUT); //02/24/19 now connected to 'Run Current' 1NA619 charge current sensor
      digitalWrite(RUN_CURR_PIN, LOW); //turn off the internal pullup resistor
    
      pinMode(TOT_CURR_PIN, INPUT);//02/24/19 now connected to 'Total Current' 1NA619 charge current sensor
      digitalWrite(TOT_CURR_PIN, LOW); //turn off the internal pullup resistor
    
      //Battery Voltage Monitor pin
      pinMode(BATT_MON_PIN, INPUT);
      digitalWrite(BATT_MON_PIN, LOW); //turn off the internal pullup resistor
    
      //charge connect
      pinMode(CHG_CONNECT_PIN, INPUT_PULLUP);  //goes LOW when chg cable connected
      digitalWrite(CHG_CONNECT_PIN, HIGH); //01/09/22 needed now that InitAllPins() forces it LOW
    
      //charge connect status display pin (this will eventually be one of the LEDs on the rear LED panel)
      pinMode(CHG_CONNECT_LED_PIN, OUTPUT);  //12/16/20 lights LED when chg cable connected
      digitalWrite(CHG_CONNECT_LED_PIN, HIGH); //01/09/22 needed now that InitAllPins() forces it LOW
    
      //Charge status LED en/dis pins
      pinMode(_60PCT_LED_PIN, OUTPUT);
      pinMode(FIN_LED_PIN, OUTPUT);
      pinMode(_80PCT_LED_PIN, OUTPUT);
      pinMode(_40PCT_LED_PIN, OUTPUT);
      pinMode(_20PCT_LED_PIN, OUTPUT);
    #pragma endregion Charge_Support_Pins
    
    #pragma region Motor_Pins
      //motor pins
      pinMode(InA_Left, OUTPUT);
      pinMode(InB_Left, OUTPUT);
      pinMode(Spd_Left, OUTPUT);
    
      pinMode(InA_Right, OUTPUT);
      pinMode(InB_Right, OUTPUT);
      pinMode(Spd_Right, OUTPUT);
    #pragma endregion Motor_Pins
    
    #pragma endregion PIN INITIALIZATION
    
    #pragma region SERIAL_PORTS
      Serial.begin(115200);
      delay(2000); //10/06/21 - just use fixed delay instead
    
      Serial1.begin(115200); //used HC-05 'AT' commands to set this speed
      delay(2000); //11/20/21 use fixed delay instead of waiting
    
      //I2C bus
      Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT); //MPU6050,IR_DET. MPU6050 has 4.7K pullups
      Wire1.begin(I2C_MASTER, 0x00, I2C_PINS_37_38, I2C_PULLUP_EXT, 400000);//VL53L0X Array
    
    ...
    ...
    ...
    After thinking about this for a while, it occurred to me that I may been using the #include<i2c_t3.h> style up to now, and maybe the #include <Wire.h> style doesn't incorporate the above identifiers. If this is so, how do you initialize Wire, Wire1, & Wire2?

    I created a very short test program, as follows:

    Code:
    /*
        Name:       T35_WireTest.ino
        Created:	1/18/2022 7:09:09 PM
        Author:     NEWXPS15\paynt
    */
    
    //#include <i2c_t3.h>
    #include <Wire.h>
    
    
    void setup()
    {
      
      Wire.begin();
      Wire1.begin();
    
    
    }
    
    void loop()
    {
    
    
    }
    With #include <i2c_t3.h> style, I get the expected Wire.begin() style where I can use the 'I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT' identifiers. However, if I switch to the #include <Wire.h> style, the only parameter available for the Wire.begin() call is the target address. I looked for other Wire member functions using VS2022's 'auto-complete' feature, but didn't find anything useful.

    I tried looking for examples using #include <Wire.h> for multiple I2C busses, but the examples included in the \teensy\avr\libraries\Wire\ tree are just the default single-bus ones that everyone has.

    Am I on the right track thinking the 'I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT' stuff is all i2c_t3.h specific? If so, can anyone point me to some multiple bus examples using #include <Wire.h>?

    TIA,

    Frank
    Attached Files Attached Files

  2. #2
    Senior Member
    Join Date
    Jun 2017
    Posts
    249
    While waiting for enlightenment from this august body, I decided to try a small experiment on my own. I started by loading the 'slave_sender.ino' example on a T3.2 and the companion 'master_reader.ino' example on a T3.5. I connected the two using pins 18 & 19 (default for Wire0) and got the expected output ('read: hello' printout from master_reader).

    Then I modified 'master_reader' to use Wire1 vs Wire, and moved the connecting wires from pins 19, 18 to pins 37, 38, and again got the expected output.

    This confirmed that the 'Wire.begin()' call uses the default pin numbering, so no need to include that information. I didn't try adjusting the pin numbering using Wirex.setSCL() or Wirex.setSDA() as I wasn't really sure what that does. I also didn't try adjusting the clock (from my scope readout, it appeared that the clock was set to 100KHz by default).

    Here are the two programs:

    Code:
    /*
        Name:       Wire_Master_Reader.ino
        Created:	1/18/2022 9:11:05 PM
        Author:     NEWXPS15\paynt
    
        First trial was with all default settings, and 
        connected to Wire_Slave_Sender.ino via pins 18,19
        on both ends. This worked as expected
    
        Second trial was to change all 'Wire.*' to 'Wire1.*'
        in this program, and physically move the SCL & SDA
        wires from 19,18 to 37,38 on a T3.5.  This also worked
    */
    
    // Wire Master Reader
    // by Nicholas Zambetti <http://www.zambetti.com>
    
    // Demonstrates use of the Wire library
    // Reads data from an I2C/TWI slave device
    // Refer to the "Wire Slave Sender" example for use with this
    
    // Created 29 March 2006
    
    // This example code is in the public domain.
    
    
    #include <Wire.h>
    
    int led = LED_BUILTIN;
    
    void setup()
    {
      pinMode(led, OUTPUT);
      //Wire.begin();             // join i2c bus (address optional for master)
      Wire1.begin();             // join i2c bus (address optional for master)
      Serial.begin(9600);       // start serial for output
      Wire.set
    }
    
    void loop()
    {
      Serial.print("read: ");
    
      digitalWrite(led, HIGH);  // briefly flash the LED
      //Wire.requestFrom(8, 6);   // request 6 bytes from slave device #8
      Wire1.requestFrom(8, 6);   // request 6 bytes from slave device #8
    
      //while (Wire.available()) { // slave may send less than requested
      //  char c = Wire.read();   // receive a byte as character
      while (Wire1.available()) { // slave may send less than requested
        char c = Wire1.read();   // receive a byte as character
        Serial.print(c);        // print the character
      }
    
      Serial.println();
      digitalWrite(led, LOW);
      delay(500);
    }
    Code:
    /*
     Name:		Wire_Slave_Sender.ino
     Created:	1/18/2022 9:08:53 PM
     Author:	paynt
    */
    // Wire Slave Sender
    // by Nicholas Zambetti <http://www.zambetti.com>
    
    // Demonstrates use of the Wire library
    // Sends data as an I2C/TWI slave device
    // Refer to the "Wire Master Reader" example for use with this
    
    // Created 29 March 2006
    
    // This example code is in the public domain.
    
    
    #include <Wire.h>
    
    int led = LED_BUILTIN;
    
    void setup()
    {
      pinMode(led, OUTPUT);
      Wire.begin(8);                // join i2c bus with address #8
      Wire.onRequest(requestEvent); // register event
    }
    
    void loop()
    {
      delay(100);
    }
    
    // function that executes whenever data is requested by master
    // this function is registered as an event, see setup()
    void requestEvent()
    {
      digitalWrite(led, HIGH);  // briefly flash the LED
      Wire.write("hello ");     // respond with message of 6 bytes
                                // as expected by master
      digitalWrite(led, LOW);
    }
    And some output:

    Code:
    Opening port
    Port open
    read: hello 
    read: hello 
    read: hello 
    read: hello 
    read: hello 
    read: hello

    I guess I have been a little spoiled by the richness of the <i2c_t3.h> progamming style - right up to the point where I crashed and burned due to library incompatibilities . While the <Wire.h> style seems to be pretty basic it does seem to get the job done. Thoughts?

    Frank

  3. #3
    Am I on the right track thinking the 'I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT' stuff is all i2c_t3.h specific?
    Yes, those are defined in i2c_t3.h. What tools are you using, Frank? IIRC you are using PlatformIO. It probably has some good search tools. I use the Arduino IDE to build, but I use Notepad++ for editing. It lets me specify, for example, the hardware\teensy\avr folder as a workspace, and from there I can easily search all of the TeensyDuino core and library files for any function or macro or whatever. As your programs get more complex, you have to get into the source code to find the answers to these kinds of questions.

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,885
    Does post #2 show post#1 issue resolved?

    Was going to suggest an example after p#1 - then p#2 that worked ...

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,350
    Also you don't need to create multiple new threads on the same thing...
    The previous thread: https://forum.pjrc.com/threads/69275...e-lt-Wire-h-gt
    Is still an appropriate place for this.

    And as I mentioned on that thread:
    As you probably already know, your sketch can use one or the other, but not both. And that includes all of the libraries that your sketch may include.

    So for example if you are using some sensor that communicates with I2C and it's library includes <Wire.h> and you choose to include I2c_t3.h, The sketch will not build.

    Why? Because they both define some of the same objects like Wire, plus they both define their own versions of things like Interrupt handlers, using the same default names.

    Also they are not 100% source level compatible. Especially the defining of the objects and how or if you can use some pin combinations.
    Like on T3.5/6 I believe you can use I2C_PINS_18_19 or I2C_PINS_16_17
    But you can not use 17,19 or 18,16 which would work using Wire.h ...
    Why - because he chose to do it that way... versus using Wire.setSCL(16); Wire.setSDA(18)....

    But I2C_t3 has other capabilities not in Wire... Like DMA transfers or the like.
    They are not source level compatible especially how you define objects ...

  6. #6
    Senior Member
    Join Date
    Jun 2017
    Posts
    249
    If anyone is interested in reading all the gory details about interfacing MPU6050/DMP with T3.5's and multiple I2C busses, here is my (hopefully last) post on the subject

  7. #7
    Senior Member
    Join Date
    Jun 2017
    Posts
    249
    One last piece of the puzzle. I use Nick Gammon's 'I2C_Anything.h' a lot, but as currently written it doesn't support multiple I2C busses. So, I modified it to do so by plagiarizing Kurt E's modifications to I2CDev.h/cpp. I hope to be able to make a pull request to have the original I2C_Anything.h support multiple I2C busses in the future, but in the meantime here's my 'I2C_AnythingMultiwire.h' file:

    Code:
    // Written by Nick Gammon
    // May 2012
    // Jan 2022 Rev by Frank Paynter to accomodate multiple I2C busses
    
    #include <Arduino.h>
    #include <Wire.h> //07/06/20 chg back for I2C hangup testing
    
    template <typename T> unsigned int I2C_writeAnything (const T& value, void *wireObj = 0)
      {
    
      //01/20/22 allow use of Wire1, Wire2, etc
      TwoWire* useWire = &Wire; //default is 'original' Wire
      if (wireObj) useWire = (TwoWire*)wireObj;//use this if a non-default addr was supplied
      const byte * p = (const byte*) &value;
        unsigned int i;
        for (i = 0; i < sizeof value; i++)
          useWire->write(*p++);
    
        return i;
      }  // end of I2C_writeAnything
    
    template <typename T> unsigned int I2C_readAnything(T& value, TwoWire* wireObj = 0)
      {
      //01/20/22 allow use of Wire1, Wire2, etc
      TwoWire* useWire = &Wire; //default is 'original' Wire
      if (wireObj) useWire = (TwoWire*)wireObj;//use this if a non-default addr was supplied
    
        byte * p = (byte*) &value;
        unsigned int i;
        for (i = 0; i < sizeof value; i++)
              *p++ = useWire->read();
    
        return i;
      }  // end of I2C_readAnything

    Frank

Posting Permissions

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