Using the SPH0645LM4H-B with an MKR 1010 brd.
I get data streams from the device but the data is biased up about 25500 (dec).
When I use the serial plotter I do see waves but the waves are biased up about 255000 (dec)
So I ran the serial out (binary) with out >>14.
See the binary out below.
Then I ran the serial out (binary) with the >>14.
The 8 LSB seem to vary.
I'm probably not reading the I2S coming out of the chip correctly.
Any pointers what I'm doing wrong?
// start I2S at 40 kHz with 32-bits per sample
if (!I2S.begin(I2S_PHILIPS_MODE, 40000, 32)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
unsigned int sample=0;
sample=I2S.read();
// sample>>14:
Then I shift right 14 bits
Now this is a quiet room, but I’m get values of 255000 and higher.
There seems to be a bias built in.
// start I2S at 40 kHz with 32-bits per sample
if (!I2S.begin(I2S_PHILIPS_MODE, 40000, 32)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
unsigned int sample=0;
sample=I2S.read();
sample>>14:
I would suggest spending some time understanding how they work. USB can carry digital audio is defined in 3 different classes named Class 1, 2 and 3.
Class 1 can send up to a maximum of 24-bit 96 kHz while Class 2 can support up to 24-bit 192 kHz. Class 3 simply uses less power and is less susceptible to jitter and data loss.
USB audio data transmits information as packets rather than a continuous stream of PCM audio (like much other digital audio transferring). USB requires a clock signal to keep everything in time and the choice of clock system is actually very important for USB audio.
USB audio utilized isochronous transfer mode for its real-time characteristics at the expense of error recovery.
Isochronous mode trades a fully guaranteed bandwidth and cyclic redundancy checking (CRC) of data transmission errors for the downside of there being no packet acknowledgement or retransmission in the event of an error.
Note: there are 3 sub-modes within isochronous mode:
Adaptive: the peripheral sink or source adapts to a potentially varying sample rate of the host.
Asynchronous: the sink or source determines the sample rate, and the host accommodates.
Synchronous: a fixed number of bytes is transferred to each SOF period. The audio sample rate is effectively derived from the USB clock.
USB Microphones As Audio Interfaces effectively connect to computers (or other digital devices) and act as their very own audio interfaces.
From what I can see this microphone is using standard I2S mode and should be reading correctly
with I2S_PHILIPS_MODE.
The result value is not what I'd expect though.
You keep saying "sample>>14;" rather than "sample >>= 14;" - best to copy and paste code
verbatim, rather than produce typos to further confuse the issue.
You right shift by 14 of
0b01111001001111010100000000000000
claims to generate
0b00000000000000111110010101000001
Which both is a shift of 13 or is creating an extra 1 at the start.
I suspect your method of printing the values is flawed and your values are fine.
This may well be because you are using unsigned for sample values - I2S samples
are signed integers.
If so then the
0b00000000000000111110010101000001
would be from
0b11111001010100000100000000000000
Which is what you'd expect, a value "close" to 0. Of course when doing this
correctly with signed quantities your shift would give
0b11111111111111111110010101000001
Using binary is hard on the brain, hexadecimal is worth learning ASAP.
BTW you mention both 25500 and 255000. Slips like this in programming will give nothing
but grief...
I'm not a fan of that device as its timing violates the I2S specification. I've confirmed that with both the datasheet and oscilloscope measurements. You can read my screed about it here:
Well that explains a lot. I'm finding it very difficult to get decent tech support on the SPH0645LM4H.
It seems to take forever to settle down, but I'm wondering if the non-compliance to the I2L spec that maybe the issue.
Sucks I just ordered 10 circuit boards laid out for this and I'm on a 10/9/2020 deadline (it's 10/3).
Thanks for the post, I really appreciate it.
gfvalvo:
I'm not a fan of that device as its timing violates the I2S specification. I've confirmed that with both the datasheet and oscilloscope measurements. You can read my screed about it here: I2S Microphone (SPH0645LM4H-B) | Teensy Forum
FWIW, when I tested this microphone, it did indeed have a strong DC offset. I had to use a software high-pass filter to get rid of the DC part. Code and a little FFT demo video here:
I presume the high-pass filter isn't on-board the microphone die itself due to lack of room - ADC chips
often include one but they don't need to spend silicon real-estate on a MEMS diaphragm structure, or
high gain analog amplifiers. An RC filter down to 20Hz isn't practical on silicon due to the very limited capacitance available.
signed int for reading samples
shift sample >> 14
Digital Low Pass Filter to get rid of the DC bias. THIS WAS KEY.
So we can use the boards that just came in.
I'm thinking Rev B will be the ICS-43434
Thanks everyone for their help.
Bytheway, the documentation for the ICS-43434 is light years better than the SPH0645LM4H and the manufacturer has a lot of tech notes on general usage.
Digital Low Pass Filter to get rid of the DC bias. THIS WAS KEY.
I assume the bias is intentional and a fixed-known digital value? In that case you can simply SUBTRACT it out.
When you have an unknown or uncontrolled/unexpected DC bias/offset caused by a cheap soundcard, HIGH-pass filtering (or a similar algorithm) is a common solution. (DC is zero-Hz so a high-pass filter removes it.)