Teensy 3.0 i2c endTransmission() bug

cTn

Active member
You might be aware of this, but the endTransmission() returns always 0 (as its hardcoded on line 164), where it should return transmission status (where 0 = success), having 0 hardcoded will make sketches like this completely useless.

Code:
#include <Wire.h>

uint8_t address;
int8_t status;

void setup() {
    Serial.begin(115200);
    Wire.begin();
}

void loop() {
    Serial.println("Scanning...");
    
    for (address = 0; address <= 127; address++) {
        Wire.beginTransmission(address);
        status = Wire.endTransmission();
        
        if (status == 0) {
            Serial.print("I2C device found at: ");
            Serial.println(address, HEX);
        }
    }
    
    Serial.println("done");
    
    delay(10000);
}
 
hmm, thank you (that helped quite a bit) but i am still getting quite "incorrect" reading on the i2c scanner script :/
 
What does quite "incorrect" mean?
I have four I2C devices on the bus and that one fix to wire.cpp enables an I2C scanner to see them all.
Your code also works although I don't think it should be starting at address zero.

Pete
 
i have mpu6050 gyro/accel sensor and ms5611 barometer on the "main" bus, mpu address is 0x68 which is correct on both arduino and teensy, ms5611 address is 0x77 (on arduino) which is correct, but it doesn't show up on teensy, also on teensy the i2c scanner detects "something" on 0x00, but there shouldn't be anyting...

Also, i have HMC5883L magnetometer hooked up to the mpu6050 auxiliary i2c bus, with proper mpu6050 initialization (in i2c bypass mode) i can communicate with the magnetometer without any problems (on arduino), on teensy my scanner also doesn't see it.

I should probably also state that i can communicate with mpu6050 on teensy without any problems, just the second 2 sensors seems completely "non-functional"
 
Paul, I notice beta 11 still has the I2C pins (18/19) set up in Wire.cpp as:

Code:
	CORE_PIN18_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_PE|PORT_PCR_PS;
	CORE_PIN19_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_PE|PORT_PCR_PS;

Am I the only one who found it necessary to set these to open drain? Perhaps only relevant for slave operation, though I'd have thought it could cause other issues too?

I have modified my local version to instead do:

Code:
	CORE_PIN18_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_ODE;
	CORE_PIN19_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_ODE;

Which means my two (I2C networked) teensy3s can at least talk to each other, within the previously discussed limitations of STOP detection.

Anyway, perhaps if anyone else is having issues with some I2C devices, the above might be worth a try...

- Peter
 
Am I the only one who found it necessary to set these to open drain?

Quite possibly yes. I tried numerous combinations. All resulted in open drain output.

I'm going to make another attempt at onReceive() soon... so I'll try this again while I'm at it. I really wanted to find a way to enable the pullups, as is done on AVR, but so far everything I've tried ends up open drain.
 
I thought perhaps I was imagining things, so I just went back and tested again. Using beta 11, with Wire_slave_mode_15jan13.zip, I am still seeing the same thing.

Test setup is pretty simple,
* 2x teensy3s
* GND and Vin connected, powered from USB on either
* SDA and SCL connected, with 1.5k pullups to 3.3V on one of the Teensys.

Master code:
Code:
#include <Wire.h>

void setup()
{
  pinMode(13, OUTPUT);
  
  Wire.begin();
}

void loop()
{
  int num = 0;

  Wire.requestFrom(1, 1);

  while(Wire.available())
    num = Wire.read();

  for (int i=0; i < num; i++)
  {
    digitalWrite(13, 1);
    delay(100);
    digitalWrite(13, 0);
    delay(100);
  }

  delay(1000);
}

Slave code:
Code:
#include <Wire.h>

uint8_t num = 1;

void requestEvent()
{
  Wire.write(num++);
}

void setup()
{
  Wire.begin(1);
  Wire.onRequest(requestEvent);
}

void loop()
{
}

The slave will simply return an incrementing number to the master, which will then flash that many times. Without PORT_PCR_ODE set, nothing happens, with it set, all is fine.

Looking on the scope, it seems the pins are sitting at some inbetween voltage - my assumption was that perhaps both were driving the pin in opposite directions. I'm not sure what sort of output drivers the k20 has? Are they just pullups, or push-pull? If they are push-pull, this could definitely be an issue.

As for the pullups, I can't get much to happen either. The docs explicitly say they should work even if MUXed for I2C, but on the other hand it also says the pullup is only enabled if it's configured as an Input.

Anyway, I'm not sure what's different about my setup, but it seems to behave consistently this way, for me.

- Peter
 
Hi Paul, i tried the http://www.pjrc.com/teensy/beta/Wire_slave_mode_15jan13.zip wire version, yes that fixes the "bug" with return codes, however i am still experiencing the same problem (i2c scanner is returning only 1 device, instead of 2)

I also tried the different pin setup from ploveday, that seemed to "open" the main bus properly (i can see both i2c devices on the scanner), i am yet to try getting the auxiliary bus on one of the sensors running, ill get back to you on that.
 
Yup, ploveday s different pin 18,19 configuration seems to solve all the device issues that i was having, also accessing 3rd i2c device via auxiliary bus works properly now.
 
I did some more experimenting. It looks like "PORT_PCR_PE|PORT_PCR_PS" is actually turning on the pullups, but as an output at normal drive strength (not a weak pullup). I put a 100 resistor in series between a Teensy 3.0 and 2.0 (with the pullups disabled on the 2.0), and I measured approx 15 mA current. The AVR is able to pull the line down to about 0.7 volts, but I'm sure many other I2C chips can't. Ouch. I'm pretty sure that's a silicon bug!

I'm going to work on onReceive() today, hopefully with a new version available soon.....
 
Are you sure PORT_PCR_PE|PORT_PCR_PS is doing anything? I'm not seeing much difference with or without those. They seem to be input flags, and the output seems to be either ODE (open drain), or Push-Pull. At least, that's my current guess...

This freescale documentation is abysmal :-/

- Peter
 
When ODE is set, they seem to do nothing. When it's not set, they enable the pullup, but it's not a weak drive.

Yes, I'm pretty sure. I just spent a few hours experimenting while watching closely on a scope, using external pullups to different voltages, series resistors to try probing the current flow, and lots of other tricks to try observing what the chip is actually doing.

Indeed, Freescale's documentation sucks. It also really looks like there are undocumented silicon bugs with respect to how their I2C peripheral connects to the port mux. I really wanted to find a way to enable the weak pullups and have it be open drain, to give the same experience as Arduino. It looks like ODE without internal pullups is the best option.
 
I'm only testing with a single device (another Teensy3) and it's working fine for me.

What device are you using - and does it matter what single device you try with?

By removing the other devices, you haven't inadvertently removed your pullups have you?

- Peter
 
having a single mpu6050 connected (no other i2c devices) on the bus with the last library you posted will make the sensor unresponsive (doesn't even show up on the scanner i posted at the top)
 
I'm only testing with a single device (another Teensy3) and it's working fine for me.

What device are you using - and does it matter what single device you try with?

By removing the other devices, you haven't inadvertently removed your pullups have you?

- Peter

I am still using the internal pullups, previously i had mpu6050 and hmc5883l on the main bus (everything was working fine) if i remove the magnetometer i see no devices on the bus :/
 
You can't use the internal pullups. Perhaps the magnetometer has pullups integrated or something. in any case if you don't put pullups on SCL and SDA, it's not going to (reliably) work.

- peter
 
Pullup resistors on SDA and SCL are required.

Prior versions attempted to activate the on-chip pullups. However, the chip drives basically drives the line high, up to about 15 mA in that mode. Some I2C chips are able to work with such strong pullup, but it's clearly not good. This version disables the on-chip pullup.

You must use 2 resistors.
 
Back
Top