Teensy LC I2C communication issues

Status
Not open for further replies.

ErkelByte

Member
I'm trying to get my TeensyLC to communication with the FRAM chip on Adafruits website(Details here). I used a slightly modified master_writer code (below) to try and test a read, write, and re-read in a loop. However it never seems to work as it gets stuck after printing "Reading from address". At first I thought it was the pull up resistors not being there, but they are included on the board. My circuit is super simple. I just connect the 3.3v and GND to VCC and GND respectively. Then pin 19 to SCL and pin 18 to SDA. No idea why this isn't working.

Code:
#include <Wire.h>

void setup() 
{
  delay(5000);
  Wire.begin();
  Serial.begin(9600);
}

void loop() 
{
  byte write_num = 0;
  byte read_num = 0;
  
  // set the 24C256 eeprom address to 0
  Serial.println("Setting address");
  Wire.beginTransmission(80);
  Wire.write(0);  // address high byte
  Wire.write(0);  // address low byte
  Wire.endTransmission();
  
  // read 1 byte, from address 0
  Serial.println("Reading from address");
  Wire.requestFrom(80, 1);
  while(Wire.read()) {
    read_num = Wire.receive();
  }
  Serial.print("read_num = ");
  Serial.println(read_num, DEC);
  
  // increment num
  write_num = write_num + 1;
  
  // write "num" to 24C256 eeprom at address zero
  Serial.println("Writing new value");
  Wire.beginTransmission(80);
  Wire.write(0);    // address high byte
  Wire.write(0);    // address low byte
  Wire.write(write_num);  // any more send starts writing
  Wire.endTransmission();
  
  // next time loop runs, it should retrieve the
  // same number it wrote last time... even if you
  // shut off the power
  delay(5000);
}
 
Did the i2c scanner sketch run and find the device at the expected address?

Running wire speed at 400 MHz the adafruit site indicated?
 
Did the i2c scanner sketch run and find the device at the expected address?

Running wire speed at 400 MHz the adafruit site indicated?

I ran the i2c_t3 basic_scanner and nothing happened on the serial monitor.

I hadn't previously, but nothing changed when I set the clock speed. The data sheet says standard mode supports 100kHz(it's max for std mode). But when I manually set the clock no change occurred.

Edit: Added code
Code:
// -------------------------------------------------------------------------------------------
// I2C Bus Scanner
// -------------------------------------------------------------------------------------------
//
// This creates an I2C master device which will scan the address space and report all
// devices which ACK.  It does not attempt to transfer data, it only reports which devices
// ACK their address.
//
// Pull the control pin low to initiate the scan.  Result will output to Serial.
//
// This example code is in the public domain.
// -------------------------------------------------------------------------------------------

#include <i2c_t3.h>

// Function prototypes
void print_scan_status(uint8_t target, uint8_t all);

uint8_t found, target, all;

void setup()
{
    pinMode(LED_BUILTIN,OUTPUT);    // LED
    pinMode(12,INPUT_PULLUP);       // pull pin 12 low to show ACK only results
    pinMode(11,INPUT_PULLUP);       // pull pin 11 low for a more verbose result (shows both ACK and NACK)

    // Setup for Master mode, pins 18/19, external pullups, 400kHz, 10ms default timeout
    Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
    Wire.setDefaultTimeout(10000); // 10ms

    Serial.begin(115200);
}

void loop()
{
    // Scan I2C addresses
    //
    if(digitalRead(12) == LOW || digitalRead(11) == LOW)
    {
        all = (digitalRead(11) == LOW);
        found = 0;
        
        Serial.print("---------------------------------------------------\n");
        Serial.print("Starting scan...\n");
        digitalWrite(LED_BUILTIN,HIGH); // LED on
        for(target = 1; target <= 0x7F; target++) // sweep addr, skip general call
        {
            Wire.beginTransmission(target);       // slave addr
            Wire.endTransmission();               // no data, just addr
            print_scan_status(target, all);
        }
        digitalWrite(LED_BUILTIN,LOW); // LED off

        if(!found) Serial.print("No devices found.\n");
        
        delay(500); // delay to space out tests
    }
}

//
// print scan status
//
void print_scan_status(uint8_t target, uint8_t all)
{
    switch(Wire.status())
    {
    case I2C_WAITING:  
        Serial.printf("Addr: 0x%02X ACK\n", target);
        found = 1;
        break;
    case I2C_ADDR_NAK: 
        if(all) Serial.printf("Addr: 0x%02X\n", target); 
        break;
    default:
        break;
    }
}
 
Try the i2c_t3.h version perhaps? >> ...\hardware\teensy\avr\libraries\i2c_t3\examples\basic_scanner\basic_scanner.ino

looked again at adafruit and it says : "can run at up to 1MHz I2C rates" - so 100 or 400 should work.
 
Try the i2c_t3.h version perhaps? >> ...\hardware\teensy\avr\libraries\i2c_t3\examples\basic_scanner\basic_scanner.ino

looked again at adafruit and it says : "can run at up to 1MHz I2C rates" - so 100 or 400 should work.

I don't have a i2c_t3 folder at this path ".\hardware\teensy\avr\libraries\"

Screen Shot 2019-12-22 at 6.44.49 PM.png
 
If TeensyDuino is installed it should appear under examples with the T_LC selected.

Not sure of reading that GUI (truncated path?)- not sure it is in hardware\teensy\avr\libraries\ ?
 
The 10k pullups on the Adafruit's Fram breakout may not be low enough. You might try adding 3.3k pullups at the LC end.

Worked here. Cheers.
 
If TeensyDuino is installed it should appear under examples with the T_LC selected.

Not sure of reading that GUI (truncated path?)- not sure it is in hardware\teensy\avr\libraries\ ?

I was in the wrong folder, found it. It is the same file I mentioned running in my first response to you.
 
The 10k pullups on the Adafruit's Fram breakout may not be low enough. You might try adding 3.3k pullups at the LC end.

Worked here. Cheers.

So I added a two 2k resistors each connecting the SDA and SCL pins(On the Teensy LC) to the VCC(3.3v). Sadly I only have 2k and 5k resistors. However I saw no change when running the master writer program
 
Photo of your setup? Using breadboard? Pins soldered?

I was pondering asking the same - I have two fresh AdaFruit i2c devices here (clock freq gen and DS3231 Precision RTC) - each seem to have 10K pullups - but for proper test I'd have to open and solder them.
 
Photo of your setup? Using breadboard? Pins soldered?

Bread board. Teensy was pre-soldered and I soldered the FRAM breakout board
3gFKuhMr.jpg

Edit: I was messing around before the photo. Currently it looks almost the same. Except I run the VCC and GND to the red and blue rails and connect the breakout to them via the rail
 
I was pondering asking the same - I have two fresh AdaFruit i2c devices here (clock freq gen and DS3231 Precision RTC) - each seem to have 10K pullups - but for proper test I'd have to open and solder them.

Once I get the FRAM running I actually have the breakout for the DS3231 sitting next me. Maybe it would solve both issues potentially.

Edit: I measure 3.3v when I use my voltmeter on the VCC and GND pins. Not sure how soldering the board would change that tho.
 
I don’t see any power going to your pull up resisters. You probably need a jumper to the power rail to 3.3v signal
 
I don’t see any power going to your pull up resisters. You probably need a jumper to the power rail to 3.3v signal

Yeah, I took the pic too early. See the edit for that exact issue. Here it is updated. Still no change, it gets caught in the while loop reading "0" forever.

XhTpT9Vr.jpg
 
Ok I think I solved it. Seemed to be a code issue with provided Teensy code. Using Wire.read for the while loop would read 0 the default value. Instead I switched Wire.receive with Wire.read(the updated version I've found out) and it worked! Seemed to solely a code issue.

I was able to remove the two resistors and it continued to work.

THANK YOU all for the help. I was very confused and everyone provided great advice. :)
 
Great to hear it is working. Interesting one of the scanners didn't ID the device though. Does it now?

Soldered then connected to breadboard is good. Problem is sometimes when pins in breadboard or other are not soldered to Teensy as needed and that can't be seen.
 
Odd - so much for a baseline reference diagnostic tool :)

What version of TeensyDuino is installed? IDE version? Not Windows I see?
 
One other common note on i2c devices not mentioned is a bit of a delay in setup before .begin()

It may be the FRAM unit takes some time to come to life longer than it takes the Teensy to power up.

Like this in basic_scanner:
Code:
void setup()
{
    pinMode(LED_BUILTIN,OUTPUT);    // LED
    pinMode(12,INPUT_PULLUP);       // pull pin 12 low to show ACK only results
    pinMode(11,INPUT_PULLUP);       // pull pin 11 low for a more verbose result (shows both ACK and NACK)

[B]delay(1000); // let i2c power up
while ( !Serial && millis() <4000 );[/B]  // wait to be sure SerMon online, doesn't matter Serial.begin() is below - it always starts when included on Teensy.

    // Setup for Master mode, pins 18/19, external pullups, 400kHz, 10ms default timeout
    Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
    Wire.setDefaultTimeout(10000); // 10ms

    Serial.begin(115200);
}
 
Good to hear it is software issue. I did not look carefully last night as I was doing it from my iPad...

Now at computer, yes the code looks wrong:
Example:
Code:
  Wire.requestFrom(80, 1);
  while(Wire.read()) {
    read_num = Wire.receive();
  }

Note: Wire.read() and Wire.receive() do the same thing receive is the old code and is a wrapper around a call to Wire.read(). Specifically:
From WireKinetis.h...
Code:
	uint8_t receive(void) {
		int c = read();
		if (c < 0) return 0;
		return c;
	}

What the above loop should be:
Code:
  Wire.requestFrom(80, 1);
  while(Wire.available()) {
    read_num = Wire.read();
  }
Examples in the Arduino documentation: https://www.arduino.cc/en/Reference/WireRead
 
Status
Not open for further replies.
Back
Top