If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Hearing aid using T4 and audio shield

I've been working on a hearing aid project and initially used a T3.2 and two Adafruit MCP4725 DACs. The method was to use synchronized ADC stereo inputs, filter a sample of the input with a 3-pole Bessel HP IIR filter, pass it to the DAC boards, amplify the results, and mix it back into the output amp. The filter is using float type which is slow and the I2C bus is worse, and a no-go. The T4 solved some timing problems but the DAC board will not update fast enough even when setting the I2C clock to 3.4MHz. Adafruit has not answered my post on their forum on how to up the clock. However, the improvement would not be great enough to make this method work correctly.

I'm now considering the T4 and the audio shield. I need to increase the amplitude of the 4KHz - 12KHz range by about 10dB and the low range by about 2dB. What is the best approach to accomplish this task?

I read some of it earlier today and will go over it again. I looked at Paul's tutorial and the design tool and have a diagram of what I think I need. Will order the audio shield today to have some hardware for testing.

I found this board, the Adafruit I2S Stereo Decoder - UDA1334A Breakout which would also work except for one reason. The library is incompatible with the T3.2, T4.0, and probably others. Is there a simple way of fixing this problem or am I likely to find only the PJRC audio shield my only alternative?

I found this board, the Adafruit I2S Stereo Decoder - UDA1334A Breakout which would also work except for one reason. The library is incompatible with the T3.2, T4.0, and probably others. Is there a simple way of fixing this problem or am I likely to find only the PJRC audio shield my only alternative?

It is a standard I2S board. What you have to do is remove the lines that refer to the sgtl5000 in the audio shield:

It should work for a stereo board such as the Adafruit board you mention or the HiLetgo PCM5102 I2S (https://smile.amazon.com/gp/product/...?ie=UTF8&psc=1), adjusting for the stereo board not having the gain/shutdown pins, and that you need to attach an amplifier to the audio outputs.

Note it can be confusing understanding the input/output pins. Typically the Teensy documentation tends to mean the output going from the Teensy to the I2S device (i.e. pin 7 in the Teensy 4.0 or pin 22 in the Teensy 3.x), and input going from the I2S device to the Teensy (pin 8 in the Teensy 4.0, or pin 13 in the Teensy 3.x). The documentation for the I2S boards tends to reverse this, and they talk of input (i.e. DIN) as being the input to the device, and output (DOUT) as going from the device. The clock pins (BCLK, LRCLK and possibly MCLK) are all the same.

I was not going to use the audio board as I have most of the code already written. I just need an output DAC that is fast. The Adafruit I2C DAC breakout, MCP4725, runs at 400KHz but is way too slow. It has a fast mode, 3.4MHz, but nobody on the Adafruit forum knows how to get the board into this mode. My timing test shows the output to one DAC takes around 350 usec. I need to make it around the entire loop in 25 usec. At this point, I'm beginning to think it is wise to learn the PJRC audio shield as it opens all kinds of future prospects.

I was not going to use the audio board as I have most of the code already written. I just need an output DAC that is fast. The Adafruit I2C DAC breakout, MCP4725, runs at 400KHz but is way too slow. It has a fast mode, 3.4MHz, but nobody on the Adafruit forum knows how to get the board into this mode. My timing test shows the output to one DAC takes around 350 usec. I need to make it around the entire loop in 25 usec. At this point, I'm beginning to think it is wise to learn the PJRC audio shield as it opens all kinds of future prospects.

Not knowing much about the details, I suspect the Audio Shield would be too slow for you also. According to the SGTL5000 datasheet, maximum LRCLK can only go 96kHz (https://www.pjrc.com/teensy/SGTL5000.pdf).

just to understand: is it really sure, that the latency you are talking about is caused by the DAC?
I would suspect latency is caused by the filter delay and the block size of the audio processing and only a small portion really caused by the DAC. And I think the I2C bus frequency will not affect latency at all.
Maybe you want to investigate into techniques that noise cancelling headphones use instead of the usual block processing?

I've never heard of anyone who used a I2C DAC for audio...
Do yourself a favor and use a well known shield which is built for audio. It has a microphone- and headphone-connector, too (and it's very loud with the right headphones) So everything will be much easier.
As a plus, you can use the audio library which has the filters you need.

Points well taken. I will likely end up with the PJRC shield but want to finish my search for just a DAC breakout.

My 3-pole Bessel IIR filter takes only a few usec to run both channels with the T4. The long delay is entirely within the 4725 board, for whatever reason. My loop time is 6 usec with ADC capture and filter but jumps to 374 usec when the first DAC is added to the loop.

I found another board, the AK-MCP4922 – Dual 12-Bit DAC Breakout. Not sure if 12-bit audio will sound good enough for speech. It uses SPI for communications. Now looking for a US supplier.

The Adafruit library switches the bus to 400KHz(TWBR=12), writes the data, then switches back to the users default, usually 100KHz. I run mine at 400KHz and can bump it to 888KHz(TWBR=1) but the DAC won't work. I need to capture data from two synchronized ADCs at around 20KHz, filter both channels, and output to two DACs. I just ran another timing test using the T4 and the capture and filter takes 6 usec. When I add one DAC, it jumps to 385 usec and the second DAC pushes it to 763 usec. This destroys my ability to capture at the rate I need. The MCP4922 will work but I haven't found a US breakout board.

I've discovered that the I2C bus is running at 100KHz no matter what I do to change it. The value of TWBR is 72 and it should be 12. I set it as my 400KHz default and the MCP4725 library does the same thing. I found the Wire library that appears to be used by the compiler. I used the Wire.setClock function with a value of 400000 but printing out TWBR still shows 72. How do you set the bus speed for a T4?

I've discovered that the I2C bus is running at 100KHz no matter what I do to change it. The value of TWBR is 72 and it should be 12. I set it as my 400KHz default and the MCP4725 library does the same thing. I found the Wire library that appears to be used by the compiler. I used the Wire.setClock function with a value of 400000 but printing out TWBR still shows 72. How do you set the bus speed for a T4?

TWBR is a legacy emulation for ye ol 8-bit AVR processors. I don't think T4 supports the emulation. use Wire.setClock(400000) and verify with scope on SCL pin.

When using Wire, I had no control over the speed. When switching to Wire1, my loop time dropped from 384usec to 109usec for 20 passes. However, using Wire1.setClock() does not produce a change in loop time for freq values of 100KHz, 400KHz, 500KHz, 800KHz, and 1MHz. I'm still using pins A4 and A5. It appears to be stuck at 400KHz while Wire is stuck at 100KHz.

PS
It appears that Wire is stuck at 100KHz and Wire1 and Wire2 are stuck at 400KHz.

It's now responding to speed changes by moving the Wire1.setClock() to just under the Wire1.begin() in the DAC library CPP file. However, I don't get the right output voltage and by calculation, it's running about double speed. I'll have to put the scope on it tomorrow and see what is happening.

Problem Solved
My Owon SDS-7102V scope found it all. It turns out that Wire1 commands do not work or they use different pins than A4 and A5. None on the top of the T4 were active. I changed everything to Wire and set the clock immediately after Wire.begin(). Also, the Adafruit_MCP4725 library has so little in it that I copied the working part directly into my sketch to have more control when experimenting. I tested I2C clocks at 100KHz, 400KHz, and 1MHz and all rates are right on at 50% duty cycle according to the scope. Pullup resistors of 1K are enough to give fast rise times. The DACs are working correctly at all these rates even though the chip data sheet says 400KHz.

Unfortunately, at 1MHz it takes 86 usec to go around the loop so my sample rate will probably be limited to 10Ks/s. This should work with a filter corner freq of 4KHz but I want the rate to go to 40KHz. It appears then that the MCP4724 on I2C will not work. My next choice is an MCP4922 running on SPI but there are no US suppliers of a breakout board. OSHPark makes a board but shipping on a single chip is about three time the chip cost. I'll still investigate that route as I have other high freq apps in mind.

Thank you all for your help in solving this problem. The T4 is a marvelous board and thank you Paul for a great product.
Ed

I looked at that and found a nice board from Adafruit that would directly replace the function of a pair of MCP4725 boards. However, the library was written for the Due and other CPUs that show up as incompatible in the Arduino IDE. If I had a board and library that would run fast enough then I would consider I2S. I've never used any I2S hardware so have no experience in that part of Arduino programming.

With the audio sibrary, 44.1kHz 16Bit stereo is standard/default. Every codec can do that, the T3.2 can do that. It can do 96kHz stereo if you want. May be a little much for hearing aid...

I'm currently using 256Khz/2 channel, in+out, 16 Bit, over I2S on a Teensy 4 (same price as T3.2) , 2 channel, for a SDR receiver (Thanks to DD4WH) CPU-usage still low....
I2S is all DMA, so no CPU usage for the codec.