I am seeking a solution to communicating to Teensy 3.2 and issuing a command to play a WAV file. The summary of my challenge is that as soon as Teensy gets to the playSdWav1.play("XXX.WAV"); command, everything stops for all controllers on the I2C bus. A cold boot is in order to restore the Teensy.
I see this behavior using SDA0/SCL0 on the Teensy 3.2, and SDA1/SCL1. (For the record, I was also able to repeat this behavior using my Teensy 3.6, although I did not also try SDA2/SCL2 there.)
So my question is what it is about the Audio board that, when instructed to play a WAV file, ties up the I2C bus so harshly?
To investigate I built a small proto set up and reduced my code down to the minimum, adding back a little button-driven test logic.
- I have one Arduino Pro Mini with 3 buttons and an LED attached to the I2C bus (address 99). Pushing any button with cause the local LED to light.
- I have a second Pro Mini on the I2C bus (address 33), with an LED. Pushing the first button on my primary Pro Mini will send over a command to this second Pro Mini and cause the LED to blink.
- I also have my Teensy 3.2 with Audio Board on the I2C bus (address 22) and this Teensy has an LED and an Audio board with a proven micro SD and WAV file inserted.
- Pushing the second button on the primary Pro Mini will cause the local LED on the Teensy to blink.
- Pushing the third button on the primary Pro Mini is supposed to cause the Teensy to blink the LED and play the WAV file.
The behavior I am experiencing is:
- push button 1 and the LED on the remote Pro Mini blinks and goes dark (the local LED lights up and then goes dark).
- push button 2 and the LED on the Teensy blinks and goes dark (the local LED lights up and then goes dark).
I can go back and forth between these two buttons all day just fine.
- push button 3 and the local LED lights up and stays lit. The primary Pro Mini no longer responds to any button pushing. The LED on the Teensy is not lit. No WAV file is played. This remains the state as long as I care to wait.
(Also, as soon as I disconnect Teensy from either SDA or SCL, the other controllers might resume processing, or they might remain locked up and require a warm boot. It is inconsistent.)
Here is my connection diagram:
Here is the code for my primary Pro Mini:
Here is the code for my Teensy 3.2:
Here is my code for my secondary Pro Mini:
It's not a surprise to me at all that Teensy and an Audio board communicate via I2C. What surprises me is the impact that has on other controllers on an I2C bus, especially when I go out of my way to use alternate I2C buses.
Any guidance is, as always, greatly appreciated.
- Eric
I see this behavior using SDA0/SCL0 on the Teensy 3.2, and SDA1/SCL1. (For the record, I was also able to repeat this behavior using my Teensy 3.6, although I did not also try SDA2/SCL2 there.)
So my question is what it is about the Audio board that, when instructed to play a WAV file, ties up the I2C bus so harshly?
To investigate I built a small proto set up and reduced my code down to the minimum, adding back a little button-driven test logic.
- I have one Arduino Pro Mini with 3 buttons and an LED attached to the I2C bus (address 99). Pushing any button with cause the local LED to light.
- I have a second Pro Mini on the I2C bus (address 33), with an LED. Pushing the first button on my primary Pro Mini will send over a command to this second Pro Mini and cause the LED to blink.
- I also have my Teensy 3.2 with Audio Board on the I2C bus (address 22) and this Teensy has an LED and an Audio board with a proven micro SD and WAV file inserted.
- Pushing the second button on the primary Pro Mini will cause the local LED on the Teensy to blink.
- Pushing the third button on the primary Pro Mini is supposed to cause the Teensy to blink the LED and play the WAV file.
The behavior I am experiencing is:
- push button 1 and the LED on the remote Pro Mini blinks and goes dark (the local LED lights up and then goes dark).
- push button 2 and the LED on the Teensy blinks and goes dark (the local LED lights up and then goes dark).
I can go back and forth between these two buttons all day just fine.
- push button 3 and the local LED lights up and stays lit. The primary Pro Mini no longer responds to any button pushing. The LED on the Teensy is not lit. No WAV file is played. This remains the state as long as I care to wait.
(Also, as soon as I disconnect Teensy from either SDA or SCL, the other controllers might resume processing, or they might remain locked up and require a warm boot. It is inconsistent.)
Here is my connection diagram:
Here is the code for my primary Pro Mini:
Code:
// I2C Teensy Audio Board Conflict Test
// Arduino Pro Mini "MASTER"
// I2C 99
// blink local LED when any button pushed
// pushing "BlinkArdy" button instructs slave Arduino to blink its local LED
// pushing "BlinkTeensy" button instructs slave Teensy to blink its local LED
// pushing "PlayTeensy" button instructs slave Teensy to play WAV file
#include <Wire.h>
byte SendCode = 1;
const int BlinkArdy = 10;
const int BlinkTeensy = 11;
const int PlayTeensy = 12;
const int ledPin = 3;
int BlinkArdybuttonState = 0;
int BlinkTeensybuttonState = 0;
int PlayTeensybuttonState = 0;
void setup() {
Wire.begin(99); // join i2c bus as 99
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(BlinkArdy, INPUT);
pinMode(BlinkTeensy, INPUT);
pinMode(PlayTeensy, INPUT);
}
void loop() {
BlinkArdybuttonState = digitalRead(BlinkArdy);
BlinkTeensybuttonState = digitalRead(BlinkTeensy);
PlayTeensybuttonState = digitalRead(PlayTeensy);
if (BlinkArdybuttonState == HIGH) {
SendCode = 1;
digitalWrite(ledPin, HIGH);
Wire.beginTransmission(33);
Wire.write(SendCode);
Wire.endTransmission(33);
}
else if (BlinkTeensybuttonState == HIGH) {
SendCode = 1;
digitalWrite(ledPin, HIGH);
Wire.beginTransmission(22);
Wire.write(SendCode);
Wire.endTransmission(22);
}
else if (PlayTeensybuttonState == HIGH) {
SendCode = 2;
digitalWrite(ledPin, HIGH);
Wire.beginTransmission(22);
Wire.write(SendCode);
Wire.endTransmission(22);
}
else {
digitalWrite(ledPin, LOW);
}
delay(100);
}
Here is the code for my Teensy 3.2:
Code:
// I2C Teensy Audio Board Conflict Test
// Teensy 3.2 with Audio Board
// I2C 22
// blink local LED if receive char 1 via I2C
// play WAV file if receive char 2 via I2C
#include <Wire.h>
#include <Audio.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
int receivedChar;
const int ledPin = 5;
AudioPlaySdWav playSdWav1; //xy=220,179
AudioMixer4 mixer1; //xy=664,179
AudioOutputI2S i2s1; //xy=911,186
AudioConnection patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord2(playSdWav1, 1, mixer1, 1);
AudioConnection patchCord3(mixer1, 0, i2s1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=911,388
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
Wire.setSCL(16);
Wire.setSDA(17);
Wire.begin(22); // join i2c bus as 22
Wire.onReceive(receiveEvent);
}
void loop()
{
delay(100);
}
void receiveEvent(int howMany) {
if (Wire.available() > 0) {
receivedChar = Wire.read();
}
switch (receivedChar) {
case 1:
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
break;
case 2:
delay(1000); // just give us a sec to let anything else get out of the way
playSdWav1.play("/FX/VOLCANO.WAV");
delay(1000); // and give us another sec to let the audio board do its thing
break;
default:
Serial.println("Cannot decipher transmission");
Serial.println(String(receivedChar));
Serial.println(String(howMany));
break;
}
}
Here is my code for my secondary Pro Mini:
Code:
// I2C Teensy Audio Board Conflict Test
// Arduino Pro Mini "SLAVE"
// I2C 33
// blink local LED if receive char 1 via I2C
#include <Wire.h>
int receivedChar;
const int ledPin = 3;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
Wire.begin(33); // join i2c bus as 33
Wire.onReceive(receiveEvent);
}
void loop()
{
delay(100);
}
void receiveEvent(int howMany) {
if (Wire.available() > 0)
{
receivedChar = Wire.read();
}
switch (receivedChar) {
case 1:
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
break;
default:
Serial.println("Cannot decipher transmission");
Serial.println(String(receivedChar));
Serial.println(String(howMany));
break;
}
}
It's not a surprise to me at all that Teensy and an Audio board communicate via I2C. What surprises me is the impact that has on other controllers on an I2C bus, especially when I go out of my way to use alternate I2C buses.
Any guidance is, as always, greatly appreciated.
- Eric