Teensy 4.0 I2C Slave issue.

weirdwolf

Member
Hello there,

I'm currently working on a project in which i am trying to include a visualizer, for which i am using the Teensy 4.0 to run FFT on my audio signal,
which gets read through the Audio Adapter Shield (Rev D), and should then transfer the FFT values over to my main controller / display.

However i've run into a bit of an issue, as it seems the Teensy is refusing to communicate with the main controller over I2C,
and I'm unsure if the problem is a hardware or software issue, the I2C lines are pulled up to 3.3V with 4.7Kohm, and the grounds are connected,
but the Teensy doesn't get found by the I2C scanner application loaded onto the main controller.

I found a thread from back in june (2019) about the Wire.h library not supporting slave functionality for the Teensy, is this still the case?
Or do i have some other problem i just haven't discovered yet?

Any and all help is very appreciated.
Thanks.


Source Code:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s;           //xy=347,467
AudioMixer4              mixer;         //xy=491,480
AudioAnalyzeFFT1024      fft1024;      //xy=669,479
AudioConnection          patchCord1(i2s, 0, mixer, 0);
AudioConnection          patchCord2(i2s, 1, mixer, 1);
AudioConnection          patchCord3(mixer, fft1024);
AudioControlSGTL5000     audioShield;    //xy=366,225
// GUItool: end automatically generated code


//Needed FFT Bands are 1, 2, 3, 6, 12, 24, 47, 94, 187, 373.
//These represent the 10 bands i am attempting to read, which are
//32Hz, 64Hz, 125Hz, 250Hz, 500Hz, 1KHz, 2KHz, 4KHz, 8KHz & 16KHz.
//although they're slightly off because the FFT has a resolution of 43Hz, however it should be close enough to give
//usable data, if not i will have to modify the components the equalizer is comprised of.

const int addr = 16; //I2C communication address, device will work as slave.

const int myInput = AUDIO_INPUT_LINEIN; //Defines Audio Input pins for FFT function.

float levelF[10]; //array to hold the frequency band levels
int   levelI[10];


void setup() {
  AudioMemory(12); //Audio library requires memory to function properly.

  //Enable the Audio Shield (SGTL5000) and select input
  audioShield.enable();
  audioShield.inputSelect(myInput);
  //Mute Outputs, as we aren't using those.
  audioShield.muteHeadphone();
  audioShield.muteLineout();

  //configure mixer to equally add left & right channels.
  mixer.gain(0, 0.5);
  mixer.gain(1, 0.5);

  while(!Serial && millis() < 1000){} //wait for a Serial connection to start, timeout after 1000ms
  Serial.println("Serial Start");
  
  //Begin I2C
  Wire1.begin(addr);
  Wire1.onRequest(SendFFT);

}

void loop() {
  if(fft1024.available()){
    //The FFT library works linearly, but music works in octaves
    //because of that, we read multiple bins for the higher frequencies, 
    //so we don't throw away useful data.

    //NOTE TO SELF: Bins should be in order now. 24/03 kl.4:10 ... du skal virkelig have fikset hvornår du sover...
    levelF[0] =  fft1024.read(0);
    levelF[1] =  fft1024.read(1);
    levelF[2] =  fft1024.read(2, 4);
    levelF[3] =  fft1024.read(5, 8);
    levelF[4] =  fft1024.read(9, 17);
    levelF[5] =  fft1024.read(18, 35);
    levelF[6] =  fft1024.read(36, 72);
    levelF[7] =  fft1024.read(73, 140);
    levelF[8] =  fft1024.read(141, 280);
    levelF[9] =  fft1024.read(281, 511);

    for(int i = 0; i > 9; i++){
      levelF[i] = levelF[i] + 0.5;
      levelI[i] = (int) levelF[i];    
    }
  }
  //Serielt Output for at tjekke FFT værdier
  for(int j = 0; j > 9; j++){
    Serial.print("Band ");
    Serial.print(j);
    Serial.print(": ");
    Serial.println(levelF[j]);
  }
}

//When the I2C Master (the Touch Display) requests updated values, send them over.
void SendFFT() {
  Serial.println("I2C Requested");
  for(int i = 0; i > 9; i++){
      Wire1.write(levelI[i]);
  } 
  Serial.println("I2C Sent"); 
}
 
Thank you for the response, I'll look into that and see if i can make it work.

Edit: I got a little further, but hit another snag.

So I've changed the dependencies in the main sketch and the audio library dependencies over to "I2C_driver_wire.h" from the standard wire library, and I'm getting a weird error, which seems to say Wire.write() has been defined in two places and doesn't know which one to use, at least as far as i can tell.

Do you have any ideas on how to get around / fix this, or should i head over to github and post an issue about it there instead?

I'll continue looking through it and see if i can't figure it out myself, but I'm not the most experienced in troubleshooting libraries, so I'm in deep waters here.

Error Message looks like so:
Code:
Arduino: 1.8.11 (Windows 10), TD: 1.50, Board: "Teensy 4.0, Serial, 600 MHz, Faster, US English"

C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio\control_tlv320aic3206.cpp: In member function 'bool AudioControlTLV320AIC3206::aic_goToPage(byte)':

C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio\control_tlv320aic3206.cpp:561:18: error: call of overloaded 'write(int)' is ambiguous

   Wire.write(0x00); delay(10);// page register  //was delay(10) from BPF

                  ^

In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio\control_tlv320aic3206.cpp:11:0:

C:\Users\Weirdwolf\Documents\Arduino\libraries\teensy4_i2c\src/i2c_driver_wire.h:52:12: note: candidate: virtual size_t I2CDriverWire::write(uint8_t)

     size_t write(uint8_t data) override;

            ^

In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/Stream.h:24:0,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/HardwareSerial.h:106,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:46,

                 from C:\Users\WEIRDW~1\AppData\Local\Temp\arduino_build_875490/pch/Arduino.h:6,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio\control_tlv320aic3206.h:58,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio\control_tlv320aic3206.cpp:10:

C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/Print.h:59:9: note: candidate: size_t Print::write(const char*)

  size_t write(const char *str)   { return write((const uint8_t *)str, strlen(str)); }

         ^
 
Last edited:
Hi weirdwolf,

sorry I should have had a closer look to your code. You are using the audio lib and right you have to change all the includes of Wire.h to I2C_driver_wire.h. But nevertheless I had nearly the same problem with control_tlv320aic3206.cpp. The easiest for me was to skip control_tlv320aic3206.cpp because I don' t need it (rename it, so that it is not compiled).

Regards,
Helmut
 
Thanks a ton for that fix!
code is now compiling and running, although i can't seem to properly read the data sent, but that could be an issue on my master, so i'll have to test that out next.

Many thanks,
Weirdwolf
 
Thought i'd add a quick update just to close this out.

The error i got while compiling, after having switched to Richard Gemmels I2C Library has been fixed, and there should be no need to remove/rename 'control_tlv320aic3206.cpp' from the audio library folder anymore.

And i couldn't read the data i was sending because i wasn't sending any data, had reversed a '<' symbol in a for loop, so the loop was never running, Hah.

But none the less, Thanks for the help, hbit!

Cheers,
Weirdwolf.
 
Back
Top