#include file hell, again :(

paynterf

Well-known member
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
 

Attachments

  • T35_WallE3_V5.ino
    133.4 KB · Views: 25
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
 
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.
 
Does post #2 show post#1 issue resolved?

Was going to suggest an example after p#1 - then p#2 that worked ...
 
Also you don't need to create multiple new threads on the same thing...
The previous thread: https://forum.pjrc.com/threads/69275-include-lt-i2c_t3-h-gt-vs-include-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 ...
 
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
 
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
 
Back
Top