I2S audio output and problems w/ I2C IMU

Status
Not open for further replies.

gash

Member
I have a project using the teensy audio adapter board + a pair of I2C devices -- a BNO055 IMU and a MCP23017 I/O expander, powered over USB. I2C bus uses SDA0/SCL0 on pins 18 & 19. With I2S audio output enabled, the IMU will give a few seconds of readings before locking up. Commenting out either the call to read quaternion data from the IMU or declaring a different audio output type (swapping AudioOutputI2S for AudioOutputAnalog, for instance), all is fine. I'm using a slightly modified version of the Adafruit BNO055 library. Audio library is unchanged. I'm using my own library for the MCP23017, but in the example code below, while the Expander is instantiated, it's not used. Serial output hums along for 3-4 seconds, then everything locks up. BNO055 hardware is my own breakout design and uses 10K pullups as well as an I2C address of 0x28. The code below distills the problem to its essentials. Note that in loop(), I'm not using the AudioOutput device at all. I'm doing something I shouldn't be doing, but it's not obvious to me what that is. Perhaps my pullups are too aggressive? Any insight would be greatly appreciated.

Code:
#include <Audio.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include "MCP23017.h"

AudioPlaySdWav           playWav1;
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S           audioOutput;
//AudioOutputSPDIF       audioOutput;
//AudioOutputAnalog      audioOutput;
AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);
AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;


// Use these with the audio adaptor board
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

imu::Quaternion q;
Adafruit_BNO055 bno = Adafruit_BNO055();
MCP23017 Expander(0x20);
uint16_t val;

// set interval for IMU samples

uint8_t sample_interval = 100;
uint32_t last_sample_time = 0;

void setup() {	
	Serial.begin(115200);
	// Audio connections require memory to work.  For more
	// detailed information, see the MemoryAndCpuUsage example
	AudioMemory(8);

	// Comment these out if not using the audio adaptor board.
	// This may wait forever if the SDA & SCL pins lack
	// pullup resistors
	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);
	 }
	}
	
	if(!bno.begin())
	{
		// here was a problem detecting the BNO055 ... check your connections
		//Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
		while(1); //lock up
	}
	bno.setExtCrystalUse(true);
	Expander.begin();
	delay(500);
}

void loop() {

    int n;
	
	// Update button and orientation state

	if(millis() - last_sample_time > sample_interval)
	{
		q = bno.getQuat();
		last_sample_time = millis();
		Serial.print("Qx: " );
		Serial.println(q.x());
	}

}
 
Nothing looks wrong in that program.

I'm using a slightly modified version of the Adafruit BNO055 library.
.....
I'm using my own library for the MCP23017, but in the example code below, while the Expander is instantiated, it's not used.

I have Adafruit's BNO055 board here, and some MCP23017 chips. Maybe I could use those to get a similar hardware setup?

Any chance you could post the exact code you're running, so I can try to reproduce the issue here? Please do not ask me to look into this with somewhat different code. Small details matter, and every time I've tried to investigate strange problems without the exact same code used, it turns into a wild goose chance.
 
Nothing looks wrong in that program.

I have Adafruit's BNO055 board here, and some MCP23017 chips. Maybe I could use those to get a similar hardware setup?

Any chance you could post the exact code you're running, so I can try to reproduce the issue here? Please do not ask me to look into this with somewhat different code. Small details matter, and every time I've tried to investigate strange problems without the exact same code used, it turns into a wild goose chance.

Thanks, Paul. I really appreciate your having a look. My MCP23017 and BNO055 libraries are attached. Problem is manifested in the previously posted code -- serial output will work fine for 3 to 4 seconds then everything locks up.

Might be useful info -- I'm working with my own PCB now, but problem was also present w/ DIP packaged MCP23017 and adafruit IMU on a breadboard. The time to failure was longer, sometimes several minutes, but problem was still present.

View attachment MCP23017.cpp
View attachment MCP23017.h
View attachment Adafruit_BNO055.cpp
View attachment Adafruit_BNO055.h
 
Sorry. Should have attached the sketch as well. Attached.

Just did a little experiment -- leaving the board undisturbed, it will hum along without issue. Once you start moving the device, it locks up. It does not lock up if the AudioOutputI2S instance and associated AudioConnections are commented out, or if another output type is used.

View attachment audio_imu_test.ino
 
This happened a few times during troubleshooting today. x value of Quaternion will return a value > 1, then the device will immediately lock. Quat components should all be < 1 (unit quaternion). Something's getting corrupted. Here's some representative output:

Qx: 0.23
Qx: 0.31
Qx: 0.40
Qx: 1.99
*lock*

Here's what I know:
- Locks happen during movement. I haven't seen a lock if the device isn't moving or perturbed.
- Locks don't happen if the AudioOutputI2S instance and the associated is disabled.

Audio shield uses 2.2K pullups. My IMU uses 10K pullups (everything running at 3.3V). When the audio device is enabled, could the combination of pullups result in timing issues?
 
I was unable to find a solution. I redesigned my PCB, adding a dedicated 1A LDO regulator and changing the pullups on the I2C bus from 10K to 4K7. The issue remained -- teensy locks if AudioOutputI2S is declared and enabled. Happens w/ all components on a breadboard as well. I ultimately redesigned everything to use two teensy 3.2s -- one teensy for I/O and orientation tracking and a second to play audio.
 
Reviving this thread as we have the exact same issue here and we can not find a solution after days of debugging. We have made a custom PCB with one BNO055 (0x28 address) and two SGTL5000 chips for quad channel output. Audio output and BNO055 they work fine individually, but when the MCLK starts clocking (Output enable bit set in the register by the Audio library), the system locks up as described above.
Adding
Code:
#include <Audio.h>
AudioOutputI2SQuad       i2s_quad1;
to an BNO055 example code, e.g. https://github.com/kriswiner/BNO055/blob/master/BNO_055_Nano_Basic_AHRS_t3.ino or the Adafruit BNO055 library examples will reproduce it. Motion does seem to be somewhat required, though the time to lockup varies and can also be quite early or later on. We also tried the i2c_t3 library and different clock speeds and I2C opmodes. The SCL line is held low and the system needs a hard reset. The signals look clean when they run in parallel, trace length is about one inch, I2C pullups are 2K2. We have reproduced the same issue with a second set of PCB and Teensy, as well as on a different standalone BNO055 module and the standard Audio Board by PJRC with a single SGTL5000.
Help with this would be greatly appreciated, we intend to share this design as open hardware later on.
 
Are you using i2c_t3.h or Wire.h?


Wire.h is used internally by the audio library to control the SGTL5000 chip. So if you mix that in a project with i2c_t3.h, problems are likely to happen!
 
Are you using i2c_t3.h or Wire.h?


Wire.h is used internally by the audio library to control the SGTL5000 chip. So if you mix that in a project with i2c_t3.h, problems are likely to happen!

Of course. I am using Wire.h. I wanted to try some options of i2c_t3 and also replaced the includes in the library, but both libraries result in the same problem.
 
j4n -- unfortunately the only way around it in my application was to use two teensies -- one to handle the audio, the other managing everything else I2C related. My findings were that whatever the issue is, it is -- as you pointed out -- independent of PCB layout/breadboard used, I2C library used, BNO055 library/implementation, pullup value, and power supply. Something quite fundamental is causing SCL to lock low, requiring a hard reset.
 
I found this reference: https://forums.adafruit.com/viewtopic.php?f=19&t=125734

by gammaburst on Wed Nov 01, 2017 2:30 am
My BNO055 was very intermittent when connected to a Feather M0 WiFi. I fixed it by simply adding unequal I2C pullup resistors: 2.2K on SDA, and 4.7K on SCL. (It helps overcome an unfortunate tight timing situation caused by the BNO055.) Maybe that will work for you too.

I tried this on a regular Audio Board, but I2C stops working (at least with the proximity sensor). PaulStoffregen, could you imagine a test setup that would allow us to better debug this? We did not see anything immediately on a mixed signal oscilloscope watching the SCLK and SDA/SCL lines.. Thanks!
 
Please show us a photo of your breadboard setup. Before I try connecting this here, I want to at least see what the hardware you're really using.
 
Also, please check which version of Teensyduino you're using. Click Help > About to check. It it's older than 1.41, please update and make sure the problem still happens.

I do have that adafruit imu and some of those I/O expander chips here somewhere....
 
When to wire this up, but it turns out I only have MCP23017 in surface mount. I've ordered a few DIP ones from Digikey just now. Will look at this problem next week when they arrive.

Please show me a photo of how you've really connected this on your breadboard. I'll try to match as closely as possible for testing.
 
Thank you for looking into this!

Fresh Arduino+ Latest Teensyduino and Adafruit Libs, same results.
180419-breadboard.jpg
Breadboard; with the two audio boards; the lego brick is the proximity sensor and can swap out for a custom BNO module.

180419-audioboard.jpg
Second audio board, only modifications shown, connects SDA/SCL/3V3/GND (same as on other audio board). Same issue with custom pcb roughly the size of the audio board.

View attachment ProxAudio.ino Test sketch that changes synth frequency based on proximity reading. This works.

View attachment rawdata.ino Adafruit rawdata BNO example; adding the lines
Code:
#include <Audio.h>

AudioOutputI2S      audioOutput;        // audio shield: headphones & line-out

breaks the sensor readout.
 
Really glad to see the photo. I must have missed the fact you have TWO audio boards connected.

Did you change the I2C address on either of the boards? If both use the same address, you can expect problems!
 
Really glad to see the photo. I must have missed the fact you have TWO audio boards connected.

Did you change the I2C address on either of the boards? If both use the same address, you can expect problems!

The photo was just for illustration, the problems occur of course also with only one board connected. Output of the rawdata sketch when it happens:

Current Temperature: 28 C

Calibration status values: 0=uncalibrated, 3=fully calibrated
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 360.00 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 359.94 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 359.94 Y: 2.25 Z: 5.81 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 1.06 Y: 2.69 Z: 5.63 CALIBRATION: Sys=0 Gyro=3 Accel=0 Mag=0
X: 0.63 Y: 7.50 Z: 1.25 CALIBRATION: Sys=3 Gyro=3 Accel=3 Mag=3
X: -0.06 Y: -0.06 Z: -0.06 CALIBRATION: Sys=3 Gyro=3 Accel=3 Mag=3
X: -0.06 Y: -0.06 Z: -0.06 CALIBRATION: Sys=3 Gyro=3 Accel=3 Mag=3
X: -0.06 Y: -0.06 Z: -0.06 CALIBRATION: Sys=3 Gyro=3 Accel=3 Mag=3
X: -0.06 Y: -0.06 Z: -0.06 CALIBRATION: Sys=3 Gyro=3 Accel=3 Mag=3
X: -0.06 Y: -0.06 Z: -0.06 CALIBRATION: Sys=3 Gyro=3 Accel=3 Mag=3

I only built up a second audio board to verify it was not the specific hardware, the error is the same on both, and also on both custom pcbs (where the second SGTL5000 of course has the address changed).
 
Hi again,

I just tested the setup with the BNO055 connected through a PCA9548A 8-Ch I²C multiplexer, but the issue persists. It seems that the BNO crashes when the MCLK is clocking, we hypothesize it may be a timing issue caused in the Teensy's I²C/I²S hardware.
 
Ok, the MCP23017 in DIP package arrived and I have a little time today to test. I've got the program from msg #1 running on a Teensy 3.2 with the audio shield, an Adafruit BNO0055 module, and the MCP23017 chip.

Here's what I see on my screen.

sc.png

I can't seem to get it to lock up. In this test, I picked the breadboard up and shook it a bit, just to make sure the numbers were still responding. If I leave it still, it prints an endless stream of "Qx: 0.01".

Here's the hardware I used for testing:

DSC_0059_web.jpg

DSC_0060_web.jpg
 
I looked at this again today.

This time I found a way to reproduce the problem. I plugged a 4 inch length wire into pin 11 (MCLK). If that wire comes too close to the IMU, it locks up.

DSC_0062_web.jpg

The BNO0055 IMU does appear to be sensitive to the 11.3 MHz square wave. If I test without that white wire, it always works. It also works if the wire is present but oriented towards the USB cable. When I move the wire in close proximity to the IMU, it locks up. The problem is very reproducible and absolutely related to having that wire too close to the IMU.

I believe it's safe to conclude the problem is not happening on Teensy. But the 11.3 MHz square wave for MCLK can radiate RF energy if connected to a lengthy wire that doesn't have a close GND return. The BNO0055 IMU appears to be particularly sensitive to this 11.3 MHz (plus harmonics) radio energy.

It definitely does work if you connect the audio shield directly above the Teensy and avoid any extra wire between the Teensy and audio shield.
 
Last edited:
Did a little more testing. The 2.8 MHz BCLK signal also can cause the BNO0055 to lock up, though it's much less sensitive to BCLK than MCLK. Placing the wire close to the crystal & chip seems to be the trouble spot.

One other thing I've noticed is the problem starts with the BNO0055 returning all zeros. Then after uploading again, it never responds until I cycle the power.
 
Thanks for checking again, that makes sense and is very helpful. I will try and connect the BNO with a longer cable and see if the problem persists. The first setup that reproduced the problem was with a Teensy stacked on the Audioshield, and the BNO in roughly the same distance as on your breadboard, the only difference was that the Audioshield was underneath the Teensy. The I2C/I2S lines do run close on the custom PCB, so that would explain that instance.

I also need to power-cycle the BNO after programming, always.. maybe there's something with the reset line to be done there.

Another variant I also tried recently was to communicate with the BNO through its UART interface, and it seemed to run stable; there is unfortunately little library support for this though.
 
Thanks for checking again, that makes sense and is very helpful. I will try and connect the BNO with a longer cable and see if the problem persists.

I now have it working reliably, it seems: I used a 4-strand shielded cable (grounded on one side) for the power/I2C connection.

I also need to power-cycle the BNO after programming, always.. maybe there's something with the reset line to be done there.

This does not seem to be an issue anymore somehow; the example sketch from Adafruit seems to handle the I2C command reset.
 
Status
Not open for further replies.
Back
Top