Struggling with I2C on Teensy 3.5

Status
Not open for further replies.

edringel

Member
Trying to use the real time clock library that connects to a DS1307. In my case, it is actually connecting to a DS3231. This is fine. The DS3231 uses the same instruction set and register addresses as the 1307, and funs on 3.3V rather than 5. Great fit for the Teensy 3.5, and also is much more stable and more accurate. The connection to the TS3.5 is via I2C. I also have a "digital tube" 4 place 7 segment display, a GPS module, and a TFT module attached.

It appears that every time I try to read from the DS3231, the program stops.

SCL on the 3231 is connected to pin 16, SDA is connected to pin 17.

I am frankly confused about how to use the Wire library on the Teensy 3.5 since it seems as though I can connect to pins 7 & 8 , 16 and 17, or 18 and 19. How do I specify? Also, if I were to use SDA1/SCL1, how would I initialize a wire object?

Same concerns about Serial and SPI.

My code is below. Forgive the large amounts of commented out stuff. I'm debugging.
Ed

Code:
#include <ILI9341_t3.h>
#include <font_Arial.h> // from ILI9341_t3
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
#include <TM1637.h>
#include <TinyGPS++.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h> //uses the wire0, which is wire


#define CS_PIN  8
#define TFT_DC  9
#define TFT_CS 10
// MOSI=11, MISO=12, SCK=13
//make LED display portable
#define tm_CLK 34
#define tm_DIO 33
/*
// set up touch screen and glcd
XPT2046_Touchscreen ts(CS_PIN);
#define TIRQ_PIN  2
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
*/
// create tiny gps and time objects, related variables.
TinyGPSPlus gps;
TM1637 tmLED(tm_CLK, tm_DIO);
int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
TimeElements myTime;
time_t mySeconds;
boolean colon_blink = true;
long tzOffset = -5; //time zone set for est.
int oldSeconds;
int oldMinutes;

void setup() {

  Serial.begin(9600);
  Serial1.begin(4800);
    tmLED.init();
  tmLED.set(BRIGHTEST);

  tmLED.display(TimeDisp);
/*  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);
  ts.begin();
  */
  while (!Serial && (millis() <= 1000));
//  RTC.read(myTime);
  Serial.println(myTime.Year);
  Serial.println(myTime.Month);
  Serial.println(myTime.Day);
  Serial.println(myTime.Hour);
  Serial.println(myTime.Minute);
  Serial.println(myTime.Second);
}

boolean wastouched = true;

void loop() {
  Serial.println("Hello World");
  //initially, comment out touch management so we can get display working correctly
  /* boolean istouched = ts.touched();
    if (istouched) {
     TS_Point p = ts.getPoint();
     if (!wastouched) {
       tft.fillScreen(ILI9341_BLACK);
       tft.setTextColor(ILI9341_YELLOW);
       tft.setFont(Arial_60);
       tft.setCursor(60, 80);
       tft.print("Touch");
     }

     tft.fillRect(100, 150, 140, 60, ILI9341_BLACK);
     tft.setTextColor(ILI9341_GREEN);
     tft.setFont(Arial_24);
     tft.setCursor(100, 150);
     tft.print("X = ");
     tft.print(p.x);
     tft.setCursor(100, 180);
     tft.print("Y = ");
     tft.print(p.y);
     Serial.print(", x = ");
     Serial.print(p.x);
     Serial.print(", y = ");
     Serial.println(p.y);
    } else {
     if (wastouched) {
       tft.fillScreen(ILI9341_BLACK);
       tft.setTextColor(ILI9341_RED);
       tft.setFont(Arial_48);
       tft.setCursor(120, 50);
       tft.print("No");
       tft.setCursor(80, 120);
       tft.print("Touch");
     }
     Serial.println("no touch");
    }
    wastouched = istouched;
    delay(100);
  */
  // get current time
 // RTC.read(myTime);
  // Serial.println("Unsuccessful RTC read");
  // update clock displays
  if (myTime.Minute  != oldMinutes) {
    TimeDisp[0] = myTime.Hour / 10;
    TimeDisp[1] = myTime.Hour % 10;
    TimeDisp[2] = myTime.Minute / 10;
    TimeDisp[3] = myTime.Minute % 10;
    oldMinutes = myTime.Minute;
  }
  if (myTime.Second != oldSeconds) {
    tmLED.point(colon_blink);
    tmLED.display(TimeDisp);
    colon_blink = !colon_blink;
    oldSeconds = myTime.Second;
  Serial.println(myTime.Year);
  Serial.println(myTime.Month);
  Serial.println(myTime.Day);
  Serial.println(myTime.Hour);
  Serial.println(myTime.Minute);
  Serial.println(myTime.Second);
  }
}
 
Thanks tonton81 and KurtE. tonton81, you are absolutely right. I checked the i2c_t3 code more closely and the only change is at initialization. Both libraries are robust and helpful. Thanks again to you both.
Ed
 
The most common problem with i2c on the Teensy is that you need pull-up resistors between each of the SDA and SCL pins and 3.3v. I.e. you connect one resistor to SDA and 3.3v, and you connect another resistor between SCL and 3.3v. By default, the SCL for the first i2c bus is 18/A4, and the SDA for the first i2c bus is 19/A5. Typically you want to use 2.2K or 2.4K resistors on a 3.3v system. You can use higher resistors (such as the 4.7K resistors common for 5v Arduino systems), though the higher resistors will reduce the maximum length or speed of the i2c bus.

The standard Wire library only supports the first i2c bus. KurtE has a version that supports all 3 i2c buses, as he mentioned above. The i2c_t3.h library by nox771 also supports all 3 buses.

Note, if you are using a library that does i2c commands, you will need to modify the library to use Wire1 or Wire2 if you want to use the secondary or tertiary i2c buses. Typically you would copy it, and rename it to something else to do the changes. Alternatively, some libraries have been modified to take an additional argument to the constructor to indicate alternate i2c buses.
 
MichaelMeissner,
After some fiddling around, I discovered that the Wire library indeed works as you describe. The first I2C bus is active on 18 and 19, and the DS1307 library works without alteration. I'm using 4.7K resistors and the circuit works. I may try lowering the resistance some, since part of the fiddling was with an oscilloscope and the wave forms are anything but square.
For now, I have things working.
Thanks for everyone's comments.
 
what do i need to do to get the i2c_t3.h library to work with Adafruit_VL6180X

Assuming you already have the appropriate pull-up resistors in place (see reply #7 in this thread), you need to copy the library to a new directory and change its name. In the copy change:

Code:
#include <Wire.h>

to:

Code:
#include <i2c_t3.h>

If you get a compilation error, there are some functions like setting the i2c speed or other options that are different, and the code would need to be changed.

The Adafruit_VL6180X library is pretty simple. On other more complex libraries, you would need to inspect all of the other libraries it calls, and similarly change Wire.h to i2c_t3.h.

If you wish to use the alternate i2c buses, you would need to change the references to Wire to either Wire1 or Wire2.

Or, you can change it globally by providing your own Wire.h:
 
i think i need more thorough instructions. i copied the Adafruit_VL6180X library but i don't know what you mean by rename it. do i just rename the folder that contains the .h and .cpp files or do i need to change their names as well? i have tried renaming and relocating everything but still can not compile. i tried putting the new library folder in the sketch folder. i thought that is the first place that the compiler looks for includes.

do i need to specify the full path to the edited adafruit.h file?

i have not tried using the alternate i2c busses yet, just trying to get it to compile first. where are the references to wire that i need to change to wire1 or wire2, i though i could just change the begin statement.

i have tried everything i can think of in terms of library names locations and includes in the sketch. can not get it to compile.



Code:
#include <Adafruit_VL6180X-i2c_t3.h>


//#include <i2c_t3.h> // to use more i2c pin options  this is called by the new adafruit library?
//#include <Wire.h>
// probably need to edit adafruit to call i2c_3.h or just not call wire at all?[6
//  Wire1    3.5/3.6  I2C_PINS_37_38    37     38
//#include "Adafruit_VL6180X.h"
Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
Adafruit_VL6180X vl = Adafruit_VL6180X();
// pin 18 data
// pin 19 clock

 uint8_t old_range;
void setup() {
  Serial.begin(115200);
  delay(2000);

  // wait for serial port to open on native usb devices
  while (!Serial) {
    delay(1);
  }
  
  Serial.println("Adafruit VL6180x test!");
  if (! vl.begin()) {
    Serial.println("Failed to find sensor");
    while (1);
  }
  Serial.println("Sensor found!");
}

void loop() {
//  float lux = vl.readLux(VL6180X_ALS_GAIN_5);

//  Serial.print("Lux: "); Serial.print(lux);
  uint8_t display_range;
//  uint8_t old_range;
  uint8_t range = vl.readRange();
  uint8_t status = vl.readRangeStatus();

  if (status == VL6180X_ERROR_NONE) {
     if (old_range != range){
//     if (abs(old_range - range) >1){   
        Serial.print(" Range: "); Serial.print(range);Serial.print(" oldrange: ");Serial.println(old_range);
        old_range = range;
     }
//    old_range = range;
  }
 
other options

i just want to use a different bus. can i edit the wire.h in some simple way to change the address?
 
i need to use i2c for both the audio shield and also for the Adafruit_VL6180X i thought i needed to use a different i2c bus for each. the info on the audio shield suggest that the i2c can be shared but does not give details. can i just use one bus and it will all work out just fine? i can not get the additional buses to work no matter what i try.
 
I2c can be shared. Each device has its own address and only respond to requests that are specified for your specific address.

As for using different busses. You can go into the library you wish to change and simply change all references to the wire object to instead use the wire1 object or wire2... some libraries are setup to allow you to pass in which wire object to use, but these are the exception. Hopefully over time, we can get people to make the changes to do this.
 
Status
Not open for further replies.
Back
Top