New I2C library for Teensy3

Great! Hopefully there are no regressions. It was interesting to find that the LC Wire1 is as fast as the T3.1 buses.
 
Teensy 3.1 I2C Not working

Hello Everybody,

I have several issues using the Teensy 3.1. I am working with OS X 10.10.3 , Arduino 1.6.3, Teensyduino 1.22. I can compile and upload simple programs like the blink- or the HelloWorld-example and they are working fine.
The problems are starting when I2C is involved. I try to build a "Network" of Teensies wich are communicating over I2C. One device is the master and is asking the clients with Wire.request for Data. To test the basic communication I have written these little sketches.

Master:
Code:
#include <i2c_t3.h>


void setup()
{
  Wire.begin(I2C_MASTER, 0, I2C_PINS_18_19, I2C_PULLUP_INT, I2C_RATE_100);
  Serial.begin(9600);
}


void loop()
{ 
  Serial.println("send Request");
  Wire.requestFrom(1,5);
  
  while(Wire.available()){
    Serial.print(Wire.read());
    Serial.print(" ");
  }

  delay(1000);
}

Client:
Code:
#include <i2c_t3.h>



void setup()
{
    
  Serial.begin(9600);
  Wire.begin(I2C_SLAVE, 1, I2C_PINS_18_19, I2C_PULLUP_INT, I2C_RATE_100);
  Wire.onRequest(answer);
  
}
  
void loop()
{
  
}

void answer(){
  Wire.write("Hello");
}

The two Teensy 3.1 are on a breadboard connected with Pin18 to Pin18 and Pin19 to Pin19.
The Problem is: the Master is not getting any response and if I open the serial monitor the connection or the Teensy freezes. It must have been running before I opened the monitor because the log shows some printlns:

Serial Monitor:
send Request
send Request
send Request
send Request
send Request

Another Problem is that if several Teensies are plugged in, the IDE is choosing a random device on which the sketch will be uploaded. The choice of the serial port in the IDE is completely ignored. The only way to guarantee that the correct device programmed is to unplug all other Teensies.

I hope somebody can help me.
Thanks,
best regards from germany,
Andi



//EDIT: I have just seen there is a dedicated thread for support. Is it possible to move this post to the support-thread?
 
Last edited:
You could move this 'text' to a new Thread and just leave behind a link to it here perhaps.

Did you do pull-up resistors? I didn't search much, there may be other thread details out there.

Multiple Teensy's 'Does That' - the solution is to 'VERIFY' build only - then button push the device to trigger the desired upload.

With Multiple devices - Serial through IDE is one only - I've found TYQT to be quite useful as you can monitor multiple devices with it - and having the monitor open typically stops TeensyDuino from doing an upload until you button press.
 
If you are connecting multiple teensies, make sure the grounds are inter-connected if you are using separate power supplies for each Teensy. One Teensy needs pull-up resistors (usually 4.7K resistors, 2 separate resistors, one between pin 18 and 3.3v, and the other between pin 19 and 3.3v).
 
A few things:

1) Your Master and Slave devices are configured to start with zero delay. You might want to put a delay in the setup() of the Master, which will give time for the Slaves to fully configure.

2) Second the T3.1 internal pullups are very low resistance. This is even more so if you have both your Master device and multiple Slave devices all configured using internal pullups. The pullup resistance in that case will be excessively low, and likely won't work at all. Set all the Slave devices to I2C_PULLUP_EXT, instead of I2C_PULLUP_INT.

3) Your choice of Slave address (0x01) is not ideal. You should use addresses in the range of 0x08 to 0x77. IIRC, above and below that are reserved by the I2C protocol. Also, I am assuming you are doing this, your Slaves obviously need to be configured on different addresses.


You might also want to add checking of the return values from the functions. In the Master sketch add this function and call it after the Wire.requestFrom() call:
Code:
void print_i2c_status(void)
{
    switch(Wire.status())
    {
    case I2C_WAITING:  Serial.print("I2C waiting, no errors\n"); break;
    case I2C_ADDR_NAK: Serial.print("Slave addr not acknowledged\n"); break;
    case I2C_DATA_NAK: Serial.print("Slave data not acknowledged\n"); break;
    case I2C_ARB_LOST: Serial.print("Bus Error: Arbitration Lost\n"); break;
    case I2C_TIMEOUT:  Serial.print("I2C timeout\n"); break;
    case I2C_BUF_OVF:  Serial.print("I2C buffer overflow\n"); break;
    default:           Serial.print("I2C busy\n"); break;
    }
}

Then in the Master code:
Code:
Wire.requestFrom(...);
print_i2c_status();
 
Thanks!

The pullups did the trick, works like a charm now!

@defragster: Thank you for the tipp with the TYQT-program. This makes a lot of things easier. Also the upload-button makes a lot more sense now^^

@MichaelMeissner: I've done the pullup-wiring as you described and it works perfectly. Thank you!

@nox771: Your print_i2c_status funktion is quite helpful. Thanks for that! I think the addresses do not matter for now because I have only "self defined" I2C devices in this bus, but I keep this in mind for the case I add other devices than the Teensies.

Thanks to everybody for the quick and helpful answers! It's great to see an active and kind community like this.
 
Request fixing the scanner example

Hi nox771,

The i2c scanner example hangs. I'm not sure who is responsible for the scanner example, but if I use the i2c_t3 library, the app hangs on two teensy 3.1 devices that I use and another user reported it. I believe the default behavior of the i2c_t3 library is to wait infinitely. I made it work by adding a timeout value. I think the only people using the scanner example would be newbies, and so it really would help to modify the example.


https://forum.pjrc.com/threads/28608-I2C-Lock-up-i2c_t3-questions
 
kito, did you modify if(digitalRead(12) == LOW || digitalRead(11) == LOW) to //if(digitalRead(12) == LOW || digitalRead(11) == LOW)

that is what I do to make sure I do successful scanning without the need to hook pin12 / pin11 to GND.
 
kito, did you modify if(digitalRead(12) == LOW || digitalRead(11) == LOW) to //if(digitalRead(12) == LOW || digitalRead(11) == LOW)

that is what I do to make sure I do successful scanning without the need to hook pin12 / pin11 to GND.

Yes I did that. I see all my i2c devices when the timeout is set. Using the scanner without it will hang somewhere in the i2c_t3 library. No output and the led stay lit.

Are you saying you can download the latest v8 on the website and run the scanner example without hanging? I have two teensy 3.1 devices which both hang with v8 lib?
 
I'll look into the scanner example. It is a little odd that it would hang, it is doing only a simple address ACK/NAK check. Regardless the timeout is a good idea for that example, I'll make a note to modify it.
 
Is there an updated version of the i2c_t3 library, which should be distributed with Teensyduino?

Arduino is likely to release version 1.6.5 today. If they do, I'll be making a beta release today or early tomorrow, and probably a final 1.24 release within a week.
 
I haven't had a chance to do any updates recently. Aside from the scanner example I haven't gotten any bug reports. GitHub is current.

I can run some compile tests against your new beta once it's out though.
 
Spoofing <Wire.h> to <i2c_t3.h>

As Headroom mentioned there is no reason to run i2c_t3 and Wire together. The i2c_t3 library is a superset of the Wire API, so it implements all the functions already. Moreover they use the same hardware peripheral, so running both of them at once is likely to cause problems.

Hi

thank you for this great library! I have a project where I use many i2c devices. So libraries by other people are involved. These typically #include <Wire.h>.

Am I correct that there is no way but to modify these libraries to switch them over to i2c_t3?
(Modifying these libraries means losing easy update capability and integratability of my own code, of course.)

Or is there an "Arduino way" to spoof libs?

In other environments I might be creating a stub Wire.h in a priority include directory that just includes i2c_t3.h instead and adds some typedefs for compatibility. But I think this will not work within the Arduino petting zoo, right?

Thanks for all your help!

-Markk
 
Yes, you may want to replace wire.h in these libraries with i2c_t3.h but in the arduino environment you can make this conditional with #defines based on what board is selected.
In essence if done right you can add i23_t3.h features to Teensy 3.1 and Teesy LC and the library will switch back to wire.h automatically if you have selected a non Teensy board. You don't loose any compatibility rather you create a win win situation ;-)
 
Just added this to WIKI list - I posted here on the end of this thread - but never read the start - how to swap out WIRE for better i2c_t3.h is something I could have used already!

The speed of I2C may not be the best - but two wires and the number of devices makes it so common and easy when done right!

I understood external pull-ups were required for I2C to work when I started with Digistump SPARKS and OLED's - and since internal pull-ups are not sufficient on Teensy - a section on that up front could save lots of the traffic I've seen on that issue. The software 'I2C_PULLUP_INT' could be tagged as on the PJRC.com page-
Teensy 3.0 requires pullup resistors to +3.3V. The on-chip pullups are not used. 4.7K resistors are recommended for most applications. :: "I2C_PULLUP_EXT" required.

 
Thanks for the quick reply!

>Yes, you may want to replace wire.h in these libraries with i2c_t3.h

But if I change the 3rd party library I lose the update capability. If a new version is released I have to re-modify it. With many libs this becomes a nightmare.

Also, if I want to distribute my code I need to include all the modified 3rd party libs. Not nice.

Of course I could try to persuade the original author to include the #ifdefs in his/her original code. But I guess this is improbable for companies (i.e. Adafruit) that prefer their libs to be readable and simple.

Yet it seems I have to live with it.

Thanks,
Markk
 
Yes, that is a bit of a dilemma when upgrading these libraries. In the case of Adafruit it may be possible to persuade them to make modifications to the library. They have modified a number of their libraries to include Teensy specifics and they also sell Teensy boards. The easiest way is to create a pull request on Adafruits GitHub repository for that library.
It's worth a try.
 
First, at least get your project working, even if that means editing a file you got from Adafruit.

Later, only after the edits have been proven to work well, can we even begin to talk about asking Adafruit to revise their code.
 
Yes but it's not about my sketch, it's about the 3rd party library.

For instance I use the Adafruit_INA219 lib and it's header Adafruit_INA219.h includes <Wire.h> (see the code there).

So I would need to modify that header.

--Markk

how about if you define TwoWire_h on the very top of your sketch. Anything that #includes Wire.h will then not use the wire library since TwoWire_h is already defined.
 
how about if you define TwoWire_h on the very top of your sketch. Anything that #includes Wire.h will then not use the wire library since TwoWire_h is already defined.

I think this will not work, because the library .cpp files are compiled independently without any influence from the sketch.
 
Yes but it's not about my sketch, it's about the 3rd party library.

For instance I use the Adafruit_INA219 lib and it's header Adafruit_INA219.h includes <Wire.h> (see the code there).

So I would need to modify that header.

In order to spoof the libraries into using i2c_t3 instead of Wire, without editing anything, you would probably need to either modify the build process, or rely on directory ordering, or simply swap in the i2c_t3 in place of the default Wire library.

There was a pull request on GitHub dealing with this (from April actually, but I was too busy to look into it):
https://github.com/nox771/i2c_t3/pull/1

The suggested method in that request is basically to modify the build process by setting up a "compatibility" directory that would have header files that would in-turn include i2c_t3. This doesn't work for Arduino, it is specific to build processes that you can modify as needed (makefiles, Eclipse, etc...). I'll probably close it for that reason, it is not universally workable.

There is a way to get Arduino to build it without editing your Arduino install (thus keeping upgrade compatibility). It relies on the way Arduino prioritizes sketchbook libraries over default libraries. It does require require renaming and slight editing to i2c_t3.cpp and i2c_t3.h, as follows:

1) I'm going to assume you are working in the following directory structure using the Arduino window to compile and upload. The <sketchbook> directory will refer to that defined in the Arduino preferences in the "Sketchbook location" box:
Code:
<sketchbook>/myproj/myproj.ino            <-- single-file Arduino project "myproj"
<sketchbook>/libraries/i2c_t3/i2c_t3.*    <-- original unpack location for i2c_t3.h and i2c_t3.cpp

2) Create a Wire directory in <sketchbook>/libraries:
Code:
<sketchbook>/libraries/Wire/

3) Copy i2c_t3.cpp and i2c_t3.h to that directory as Wire.cpp and Wire.h respectively
Code:
<sketchbook>/libraries/Wire/Wire.cpp
<sketchbook>/libraries/Wire/Wire.h

4) Edit the Wire.cpp and in the include just below the large comment block change the line from #include "i2c_t3.h" to:
Code:
#include "Wire.h"

5) Load and recompile your project. The Arduino window should say something like:
Code:
Multiple libraries were found for "Wire.h"

Used: <sketchbook>/libraries/Wire


Using this I was able to compile the Adafruit library you mentioned without errors, and it used the i2c_t3 library spoofed as Wire (or so it said, I didn't actually verify the linker output).

So if it's easy to setup this way, why not always do this? Well because sometimes you do in fact want the original Wire library. If you do this it will always use i2c_t3 in place of Wire.
 
I understood external pull-ups were required for I2C to work when I started with Digistump SPARKS and OLED's - and since internal pull-ups are not sufficient on Teensy - a section on that up front could save lots of the traffic I've seen on that issue. The software 'I2C_PULLUP_INT' could be tagged as on the PJRC.com page-
Teensy 3.0 requires pullup resistors to +3.3V. The on-chip pullups are not used. 4.7K resistors are recommended for most applications. :: "I2C_PULLUP_EXT" required.

You are correct, issues involving pullups are one of the most common questions. I'll see if I can add in a section on the top post regarding pullups and recommended configurations.
 
Back
Top