Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Some I2C observations on T3.2 vs T.36 with Wire.h and i2c_t3.h

  1. #1
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    170

    Some I2C observations on T3.2 vs T.36 with Wire.h and i2c_t3.h

    I've been working on improving my BAGuitar library, and doing additional testing. I had some odd results I didn't expect. Perhaps someone might have some insight.

    I'm using teensyduinio 1.40.

    FIRST ISSUE:

    I use the default I2C configuration to configure my codec. I noticed that on my T3.2, I can send transactions to the I2C and never see a failure. If I switch to my T3.6, I see random failures where Wire.endTransmission() returns errors. The errors on the T3.6 occur even at 10Khz. As a work around, I modified my write command to loop and keep retrying until it succeeds.

    It's almost like the library when operating on the T3.6 is not checking a done flag correctly on the peripheral and corrupts a transfer that is in progress. This happens both on the default Wire.h library and the i2c_t3.h library.

    Code:
    // Without this loop, failures occur on T3.6, but never on T3.2
    bool BAAudioControlWM8731::write(unsigned int reg, unsigned int val)
    {
    	bool done = false;
    
    	while (!done) {
    		Wire.beginTransmission(WM8731_I2C_ADDR);
    		Wire.write((reg << 1) | ((val >> 8) & 1));
    		Wire.write(val & 0xFF);
    		if (byte error = Wire.endTransmission() ) {
    			Serial.println(String("Wire::Error: ") + error + String(" retrying..."));
    		} else {
    			done = true;
    			Serial.println("Wire::SUCCESS!");
    		}
    	}
    
    	return true;
    }
    SECOND ISSUE:

    I was calling Wire.begin() in a class constructor that was being declared as a global, so the class would be constructed before the sketch setup() gets called. With the default Wire.h library, things generally work fine. However, when I switch to the i2c_t3.h, it would hang the system before ever getting to setup(). I had to move the call to Wire.begin() out of the constructor and into a member function I call in setup().

    I presume there is something about the i2c_t3 library that when setting up the peripheral, it is not yet ready and a hang occurs. Is calling begin() on the peripherals in a global instance constructor generally a bad idea?

    Code:
    #include "i2c_t3.h"
    MyClass object;  // if Wire.begin() is called inside MyClass::MyClass() constructor, this will hang
    
    setup() {
      object.begin(); // call Wire.begin() here instead and it works fine
    }

  2. #2
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,512
    for issue number #1, does this happen if you set t3.6 to 24mhz?

  3. #3
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    170
    Quote Originally Posted by tonton81 View Post
    for issue number #1, does this happen if you set t3.6 to 24mhz?
    Good call! I'm so used to running my Teensy at full speed I forget it has a gas pedal. At 96 MHz, the problem still happens occasionally (say 1 in 10 transfers). At 72 Mhz and below it seems to have no issues, al least over sample of say 50 transfers.

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    17,435
    I'm trying to reproduce this problem. Since I don't have your hardware, I'm running a Teensy 3.6 with the audio shield. I have a 25K pot added to the shield. The audio shield has a SD card with the 4 test WAV files. I've got all setting at defaults, clock is 180 MHz.

    Here's the code I'm running, adapted from the WavFilePlayer example. It repetitively reads the pot and updates the SGTL5000 volume. If the Wire lib give an error, it will print the error code.

    Code:
    // https://forum.pjrc.com/threads/47931
    #include <Audio.h>
    #include <Wire.h>
    #include <SD.h>
    
    AudioPlaySdWav           playWav1;
    AudioOutputI2S           audioOutput;
    AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);
    AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);
    AudioControlSGTL5000     sgtl5000_1;
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7
    #define SDCARD_SCK_PIN   14
    
    unsigned int writeCount=0;
    
    // set the volume, and print info if Wire lib gives any error
    void setVolume(float vol) {
      int n = vol * 127.0 + 0.4999;
      if (n < 0) n = 0;
      if (n > 127) n = 127;
      n = 127 - n;
      Wire.beginTransmission(0x0A);
      Wire.write(0);
      Wire.write(0x22); // CHIP_ANA_HP_CTRL
      Wire.write(n);
      Wire.write(n);
      int r = Wire.endTransmission();
      if (r != 0) {
        Serial.println("Wire write error, r=");
        Serial.println(r);
      }
      if ((++writeCount % 50000) == 0) {
        Serial.print(writeCount);
        Serial.println(" writes performed");
      }
    }
    
    void setup() {
      Serial.begin(9600);
      AudioMemory(8);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
      SPI.setMOSI(SDCARD_MOSI_PIN);
      SPI.setSCK(SDCARD_SCK_PIN);
      if (!(SD.begin(SDCARD_CS_PIN))) {
        // stop here, but print a message repetitively
        while (1) {
          Serial.println("Unable to access the SD card");
          delay(500);
        }
      }
    }
    
    void playFile(const char *filename)
    {
      Serial.print("Playing file: ");
      Serial.println(filename);
      playWav1.play(filename);
      delay(5);
      while (playWav1.isPlaying()) {
        float vol = analogRead(15);
        vol = vol / 1024;
        //sgtl5000_1.volume(vol);
        setVolume(vol);
      }
    }
    
    void loop() {
      playFile("SDTEST1.WAV");  // filenames are always uppercase 8.3 format
      delay(500);
      playFile("SDTEST2.WAV");
      delay(500);
      playFile("SDTEST3.WAV");
      delay(500);
      playFile("SDTEST4.WAV");
      delay(1500);
    }
    Here's the result I see in the serial monitor:

    Click image for larger version. 

Name:	sc.png 
Views:	17 
Size:	59.6 KB 
ID:	12192

    After more than one million I2C writes without any error, I'm going to say I can't reproduce the problem. Well, at least not with the audio shield and this code. I intentionally chose the WAV file player example to have the audio lib and SPI running during this test. Not sure what else I should try.

  5. #5
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    170
    Hi Paul,

    I have recently picked up an Audio Shield to compare against my own board for issues just like this. I'll try to reproduce the problem with that. If I cannot, it must be either in my board or in my library. I appreciate you taking some time to investigate.

    If I can reproduce on the Audio Shield board, I'll post some code.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •