Teensy 3.0 and I2C

Status
Not open for further replies.
I'm having troubles interfacing my Teensy 3.0 w/ a MPU 6050. From my research, it seemed like a pretty simple task but I'm having troubles getting the devices to even communicate properly. This is the breakout board I'm using:

https://www.sparkfun.com/products/11028

I'm using pins 18,19 on the teensy 3.0. I have tried the I2C scanner, is that even compatible with the Teensy? its not returning anything. I'm using 1.6k pullups and just 4 pins on the breakout - GND, VDD, SDA and SCL.

Code:
#include <i2c_t3.h>

void setup() 
{
  int error;
  
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
    
  Wire.beginTransmission(0x68);  //0x68 is the I2C DEVICE ADDRESS
  
  Wire.write(0x1B);   //SEND GYRO CONFIG REGISTER!!!!
  Wire.write(B00011000); //2000degrees per minuite
  
  Wire.write(0x1C); //Accel. config register
  Wire.write(B00000000); //+-2gs
  
  Wire.write(0x6B);  //disable sleep and whatnot
  Wire.write(0);
  
  Wire.endTransmission(); 

}

void loop() 
{
  byte AxL, AxH, AyL, AyH, AzL, AzH;
  byte GxL, GxH, GyL, GyH, GzL, GzH;
  
  while(1)
  {
    Wire.beginTransmission(0x68); //I2C Adress
    Wire.write(0x43);  //gyro data register 
    Wire.endTransmission();
    //Begin data transfer from acce
  
    Wire.requestFrom(0x68,1); //I2C Adress
    while(Wire.available())
    {
      AxH = Wire.receive();
      Serial.print("GoTdAtA");
    }
  
    Wire.requestFrom(0x68,1);
    while(Wire.available())
    {
      AxL = Wire.receive(); 
      Serial.print("GoTdAtA");
    }  
    
    Wire.endTransmission();
      
    Serial.print(AxH,HEX);
    Serial.println(AxL,HEX);
    delay(1000);
  }
}

When I open the serial terminal, its not printing "GoTdAtA" indicating I'm not even reading the device properly. Thanks in advance for any guidance.
 
Hi

the loop() routine is being called over and over by code which looks roughly like this
Code:
while(1) {
  ..
  ..
  loop();
}
point being that your while(1) in the loop() routine is blocking that outer loop from executing and some things you ask some libraries to do just won't get done if you do that.

It's rushed and I am not feeling the best but does the following even compile in the IDE?
Code:
#include <i2c_t3.h>

volatile byte action;

volatile byte AxL, AxH, AyL, AyH, AzL, AzH;
volatile byte GxL, GxH, GyL, GyH, GzL, GzH;

void setup() 
{
  int error;
  
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
    
  Wire.beginTransmission(0x68);  //0x68 is the I2C DEVICE ADDRESS
  
  Wire.write(0x1B);   //SEND GYRO CONFIG REGISTER!!!!
  Wire.write(B00011000); //2000degrees per minuite
  
  Wire.write(0x1C); //Accel. config register
  Wire.write(B00000000); //+-2gs
  
  Wire.write(0x6B);  //disable sleep and whatnot
  Wire.write(0);
  
  Wire.endTransmission(); 
  
  action=0;

}

void loop() 
{
  /* better declared with broader scope, didn't realise this at first posting...
  byte AxL, AxH, AyL, AyH, AzL, AzH; // These would be 'scrubbed' between calls...
  byte GxL, GxH, GyL, GyH, GzL, GzH; */
  
  switch(action++) {
  case 0:
    Wire.beginTransmission(0x68); //I2C Adress
  break;
  case 1:
	Wire.write(0x43);  //gyro data register 
  break;
  case 2:
    Wire.endTransmission();
  break;
  case 3:
    //Begin data transfer from acce
    Wire.requestFrom(0x68,1); //I2C Adress
  break;
  case 4:
	if(!Wire.available()) action--; // repeat this till we see data
  break;
  case 5:
      AxH = Wire.receive();
      Serial.print("High=");
	  Serial.println(AxH,HEX);
  break;
  case 6:
    Wire.requestFrom(0x68,1);
  break;
  case 7:
	if(!Wire.available()) action--;
  break;
  case 8:
      AxL = Wire.receive();
      Serial.print("Low=");
	  Serial.println(AxL,HEX);
  break;
  case 9:
    Wire.endTransmission();
  break;
  case 10:
    Serial.print(AxH,HEX);
  break;
  case 11:
    Serial.println(AxL,HEX);
  break;
  default:
    delay(10); // this line is executed (256-12) times so delay is now more like 2440 between repeats of job.
  }
}
If it compiles then I expect it to work but I've been wrong before so...
 
Last edited:
maybe 1.6K is low enough to make a stuck pin on the I2C interface but even if it works with those resistors it is still worth changing for 4.7K just for the reduction in current required to drive each line to ~0 volts.
 
For a 3.3V circuit a 1.6k ohm resistor is perfectly fine and within the I2C spec. The resulting current is about 2mA, the allowed limit is 3mA for normal I2C components and 30mA for FM+ components.
 
Hi

the loop() routine is being called over and over by code which looks roughly like this
Code:
while(1) {
  ..
  ..
  loop();
}
point being that your while(1) in the loop() routine is blocking that outer loop from executing and some things you ask some libraries to do just won't get done if you do that.

It's rushed and I am not feeling the best but does the following even compile in the IDE?
Code:
#include <i2c_t3.h>

volatile byte action;

volatile byte AxL, AxH, AyL, AyH, AzL, AzH;
volatile byte GxL, GxH, GyL, GyH, GzL, GzH;

void setup() 
{
  int error;
  
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
    
  Wire.beginTransmission(0x68);  //0x68 is the I2C DEVICE ADDRESS
  
  Wire.write(0x1B);   //SEND GYRO CONFIG REGISTER!!!!
  Wire.write(B00011000); //2000degrees per minuite
  
  Wire.write(0x1C); //Accel. config register
  Wire.write(B00000000); //+-2gs
  
  Wire.write(0x6B);  //disable sleep and whatnot
  Wire.write(0);
  
  Wire.endTransmission(); 
  
  action=0;

}

void loop() 
{
  /* better declared with broader scope, didn't realise this at first posting...
  byte AxL, AxH, AyL, AyH, AzL, AzH; // These would be 'scrubbed' between calls...
  byte GxL, GxH, GyL, GyH, GzL, GzH; */
  
  switch(action++) {
  case 0:
    Wire.beginTransmission(0x68); //I2C Adress
  break;
  case 1:
	Wire.write(0x43);  //gyro data register 
  break;
  case 2:
    Wire.endTransmission();
  break;
  case 3:
    //Begin data transfer from acce
    Wire.requestFrom(0x68,1); //I2C Adress
  break;
  case 4:
	if(!Wire.available()) action--; // repeat this till we see data
  break;
  case 5:
      AxH = Wire.receive();
      Serial.print("High=");
	  Serial.println(AxH,HEX);
  break;
  case 6:
    Wire.requestFrom(0x68,1);
  break;
  case 7:
	if(!Wire.available()) action--;
  break;
  case 8:
      AxL = Wire.receive();
      Serial.print("Low=");
	  Serial.println(AxL,HEX);
  break;
  case 9:
    Wire.endTransmission();
  break;
  case 10:
    Serial.print(AxH,HEX);
  break;
  case 11:
    Serial.println(AxL,HEX);
  break;
  default:
    delay(10); // this line is executed (256-12) times so delay is now more like 2440 between repeats of job.
  }
}
If it compiles then I expect it to work but I've been wrong before so...


Thanks so much, but no dice still. Its compiles fine but I get no output on the serial monitor.
 
If you put a Serial.println("hello world") at the beginning of loop(), do you at least see that printing over and over?
 
Just as a quick(ish) experiment please change case 4 and case 7 to be like;
Code:
  ..
  case 4:
    action++; // skips read action in 5 because thought is that Wire.available() must be remaining 0
  break;
  ..
  ..
  ..
  case 7:
    action++;
  break;
  ..
If you start getting '00' (or any numerical output at all) equally as much as you see 'hello world' then the Wire.requestFrom() call is not resulting in a response, Wire.available() is remaining 0, and my quick re-write didn't include protection against that...
 
Hey guys, to test the IMU I downloaded freeIMU from this thread:

http://forum.pjrc.com/threads/23946-Teensy-3-0-Free-IMU

from what I can tell it should be compatible already, but when I check the serial monitor the data isn't changing.

7142.png


I feel like I might be missing something key.

edit: Sorry I forgot to mention, I tested using the FreeIMU_raw example
 
oh, silly me - there will 256 instances of 'hello world' for every output of '00' (or whatever numbers...) - please move the hello world printing line into case 0 :)
 
Code:
#include <i2c_t3.h>

volatile byte action;

volatile byte AxL, AxH, AyL, AyH, AzL, AzH;
volatile byte GxL, GxH, GyL, GyH, GzL, GzH;

void setup() 
{
  int error;
  
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
    
  Wire.beginTransmission(0x68);  //0x68 is the I2C DEVICE ADDRESS
  
  Wire.write(0x1B);   //SEND GYRO CONFIG REGISTER!!!!
  Wire.write(B00011000); //2000degrees per minuite
  
  Wire.write(0x1C); //Accel. config register
  Wire.write(B00000000); //+-2gs
  
  Wire.write(0x6B);  //disable sleep and whatnot
  Wire.write(0);
  
  Wire.endTransmission(); 
  
  action=0;

}

void loop() 
{
  /* better declared with broader scope, didn't realise this at first posting...
  byte AxL, AxH, AyL, AyH, AzL, AzH; // These would be 'scrubbed' between calls...
  byte GxL, GxH, GyL, GyH, GzL, GzH; */
  
  switch(action++) {
  case 0:
    Wire.beginTransmission(0x68); //I2C Adress
    Serial.print("Hello World");
  break;
  case 1:
	Wire.write(0x43);  //gyro data register 
  break;
  case 2:
    Wire.endTransmission();
  break;
  case 3:
    //Begin data transfer from acce
    Wire.requestFrom(0x68,1); //I2C Adress
  break;
  case 4:
	if(!Wire.available()) action--; // repeat this till we see data
        action++;
  break;
  case 5:
      AxH = Wire.receive();
      Serial.print("High=");
	  Serial.println(AxH,HEX);
  break;
  case 6:
    Wire.requestFrom(0x68,1);
  break;
  case 7:
	if(!Wire.available()) action--;
        action++;
  break;
  case 8:
      AxL = Wire.receive();
      Serial.print("Low=");
	  Serial.println(AxL,HEX);
  break;
  case 9:
    Wire.endTransmission();
  break;
  case 10:
    Serial.print(AxH,HEX);
  break;
  case 11:
    Serial.println(AxL,HEX);
  break;
  default:
    delay(10); // this line is executed (256-12) times so delay is now more like 2440 between repeats of job.
  }
}

Serial output:
pfid.png
 
This confirms my suspicion that you are not getting a response from your slave device at all. Do you have an oscilloscope? (A friend with one perhaps?)

If it was in my hands I would double check that I have SDA to SDA and SCL to SCL as a certainty, double check neither is shorted to 3.3V, and then probe them to make sure they transition in a logical way each time 'Hello World' appears in terminal; SCL should present a burst of constant lo-hi-lo-hi transitions after "Hello World" appears in terminal and SDA should be less constant but transitioning none the less - would you like a picture of what I mean?
 
In looking at your code:

Code:
#include <i2c_t3.h>

volatile byte action;

volatile byte AxL, AxH, AyL, AyH, AzL, AzH;
volatile byte GxL, GxH, GyL, GyH, GzL, GzH;

void setup() 
{
  int error;
  
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);

A few things come to mind. You may have already done these things, but it doesn't hurt to check the basics at times.

First of all, you are using i2c_t3.h, but you are using the standard pins. It might make sense to try it with the standard Wire.h to see if that is the issue.

Second, you are specifying a rate of 400 kHz. Maybe your chip can't handle 400 kHz. It might make sense to try it at 100 kHz, just to see if it can handle it.
 
Please give this version of the code a try, it includes Michael's advice about switching to the 'standard' library and speed + revelation of 'error' returned for first endTransmission and timeouts for cases 4 and 7; Please show us the output in Terminal :)
Code:
#include <Wire.h>

volatile byte action;

volatile byte AxL, AxH, AyL, AyH, AzL, AzH;
volatile byte GxL, GxH, GyL, GyH, GzL, GzH;

volatile uint16_t breaker;

void setup() 
{
  int error;
  
  Serial.begin(9600);
  // Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
  Wire.begin();
    
  Wire.beginTransmission(0x68);  //0x68 is the I2C DEVICE ADDRESS
  
  Wire.write(0x1B);   //SEND GYRO CONFIG REGISTER!!!!
  Wire.write(B00011000); //2000degrees per minuite
  
  Wire.write(0x1C); //Accel. config register
  Wire.write(B00000000); //+-2gs
  
  Wire.write(0x6B);  //disable sleep and whatnot
  Wire.write(0);
  
  error=Wire.endTransmission();
  Serial.print("Error=");
  Serial.println(error,DEC);
  
  action=0;

}

void loop() 
{
  /* better declared with broader scope, didn't realise this at first posting...
  byte AxL, AxH, AyL, AyH, AzL, AzH; // These would be 'scrubbed' between calls...
  byte GxL, GxH, GyL, GyH, GzL, GzH; */
  
  switch(action++) {
  case 0:
    Wire.beginTransmission(0x68); //I2C Adress
    Serial.println("Starting...");
  break;
  case 1:
	Wire.write(0x43);  //gyro data register 
  break;
  case 2:
    Wire.endTransmission();
  break;
  case 3:
    //Begin data transfer from acce
    Wire.requestFrom(0x68,1); //I2C Adress
	breaker=0;
  break;
  case 4:
	if(!Wire.available()) action--; // repeat this till we see data
	if(!(++breaker)) {
		action+=3; // move the 'action' pointer to 6
		Serial.println("Case 4 timed out.");
	}
  break;
  case 5:
      AxH = Wire.receive();
      Serial.print("High=");
	  Serial.println(AxH,HEX);
  break;
  case 6:
    Wire.requestFrom(0x68,1);
	breaker=0;
  break;
  case 7:
	if(!Wire.available()) action--;
	if(!(++breaker)) {
		action+=3; // move the 'action' pointer to 10
		Serial.println("Case 7 timed out.");
	}
  break;
  case 8:
      AxL = Wire.receive();
      Serial.print("Low=");
	  Serial.println(AxL,HEX);
  break;
  // case 9: // may as well become default, an extra 10ms isn't a big deal.
    // Wire.endTransmission(); // wut transmission? did I miss something else here???
  // break;
  case 10:
    Serial.print(AxH,HEX);
  break;
  case 11:
    Serial.println(AxL,HEX);
  break;
  default:
    delay(10); // this line is executed (256-12) times so delay is now more like 2440 between repeats of job.
  }
}
 
I tried using the standard library as well as reducing the speed to 100khz. No go.

Your code yields this result:

zx5.PNG


Here are some pictures of the cct. just in case I got it wrong... personally I don't see what I could have done wrong but anything's possible. (There are two 10k resistors in parallel to make 5k)
29x9.jpg


mafc.jpg


Thanks for the help guys :D
 
I just looked at the schematics for the breakout board and I am not sue the 10k resistors in series on the SDA/SCL lines make much sense to me. Have you measured signal levels on SCA/SDL ?
 
hmmm, I was expecting "Error=2" (or at least Error=# where I expect #!=0!) at the start of your output in terminal but it is missing, it should have been printed out in the 'setup()' function. I haven't spotted if there is anything wrong with the circuit yet, I am at work so I don't want to spend too long on it at a time right now...

Assuming you don't have (and can't borrow) an oscilloscope, have you a multimeter? Can you check the resistance between SCL and SDA is about 10K, resistance between each of those to GND is very very high and resistance between each of those and 3.3V is about 5K, continuity is there for 3V3 connection to slave and finally same for GND to slave ? All measurements while unplugged from USB/Power/VIN please.
 
Resistance:

SCL -> GND = 201k
SDA -> GND = 201k

SCL -> SDA = 4.82k

SDA -> +3.3 = 2.5k
SCL ->+3.3 = 2.5k

Continuity from +3.3 rail to pin on slave. Continuity from GND rail to pin on slave. I have a scope, I'll take a look at it in a bit.
 
Either my eyesight is failing me or there really is no square wave form visible on the scope. That's however what I'd be looking for ;-)
You have to run some I2C code to see a square wave signal on SCL. Does not matter if you sensor responds to the code.
 
Ok, so now I took a look at the schematic for your MPU-6050 breakout board because your (resistance) measurements were that different to my expectations, I wish I had looked at that sooner!

The SCL & SDA lines have got 10K pull-ups already on the breakout PCB and 10K should be OK on its own, please remove your external pullup resistors. Removing those should make the resistance between SCL & SDA more like 20K if I am not too mistaken now.

Can you probe SCL while the code is executing on the Teensy and confirm a ~100KHz burst each time "Starting..." appears in terminal please? Your oscilloscope is a bit older than the ones I can access in my workplace so I am guessing it doesn't have 'Measure' functions - if you can set the "time per division" to 10uS I think the trace will go back and forth between ~0V and ~3.3V roughly in line with the (time) division markers on the screen.
(I am home, sick with gastro, please forgive if my math is out here or anywhere really)

Do you see any signalling on SDA while the code is executing?

I could offer a revised version of the code based on information in "i2c summary - by Nick Gammon" to handle 'Wire.requestFrom()' (and Wire.available & my timeout) differently but my previous version is working fine with an I2C device I am playing with (on different I2C address, of course!) so I am convinced that it won't be that great a benefit for me to revise it yet.

@Headroom: Your eyesight is fine or mine is equally broken, I think shredability was showing us the nice steady 3.3V he has but I can't make the knobs out on the oscilloscope to any degree of certainty so I can't gaurantee being right :)
 
Sorry, to confirm;

Did you remove the four 10K resistors you had in pairs (in parallel to make ~5K)?
(Reviewing http://www.dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html makes me wonder if removing them is more benefit than detriment but on another hand I wonder if Wayne measured capacitance on the line(s) and did anything to minimise it - sticking by my statement that 10K should be OK but maybe worth re-adding one, or even both, 10K per signal back again.)

Did you see ~100KHz on SCL at any point?

What are the available 'interval per division' settings on your scope? Were you able to set it to 10µS?
(That is meant to be 10 micro seconds or 0.00001 seconds - I just checked your picture and the knob looks like it is marked "TIME/DIV" on your scope but I can't make out what limits it has.)

Since switching to my last batch of code, has the terminal output ever included "Error=#" at the start of output ?
(maybe I will post an update to the code to get the "Wire.endTransmission()" from "case 2:" return value sent to terminal too, expecting '2' but this a detail I would prefer confirmed rather than assumed too!)
 
Status
Not open for further replies.
Back
Top