Audio Adapter ADC Square wave with no input

Status
Not open for further replies.

Bob Larkin

Well-known member
I am observing the ADC output through the DAC, with no analog input (inputs grounded). I see the following:
AudioADCx200.jpg
I have added a gain of 200 to not see too much DAC noise. The noise on the square wave is probably normal ADC noise. The p-p square wave is 200 mV for a DAC full scale of about 2 V p-p. So when the x 200 is removed, it is a lot smaller, about 1/2000 of full scale. But that is still about 8 times bigger than the ADC noise. The frequency is about 1836 Hz for a period of about 545 microseconds. It does this even with 5V applied and the PC not running (but still supplying the 5V).
The test setup is
Code:
/* RSL_ADCTest2.ino
*/
#include <Audio.h>

//Audio objects
// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=173,313
AudioMixer4              mixer1;         //xy=404,164
AudioMixer4              mixer2;         //xy=404,355
AudioOutputI2S           i2s3;           //xy=668,313
AudioConnection          patchCord2(i2s1, 0, mixer1, 0);
AudioConnection          patchCord4(i2s1, 1, mixer2, 0);
AudioConnection          patchCord5(mixer1, 0, i2s3, 0);
AudioConnection          patchCord6(mixer2, 0, i2s3, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=177,525
// GUItool: end automatically generated code

void setup() {
   AudioMemory(20);
  sgtl5000_1.enable();
  // 2 & 19 sets 2.2 v p-p range for in and out
  sgtl5000_1.lineInLevel(2);
  sgtl5000_1.lineOutLevel(19);
  mixer1.gain(0,200.0);             // To see ADC noise on scope
  mixer2.gain(0,200.0);
  }

void loop(){
  }

What is this? Does anybody else see this? Am I doing something I shouldn't?
 
If it makes any difference, the hardware I was using was the stock audio adaptor plugged together with a Teensy 3.6. Bob
 
Has anybody been able to 1-not see the square wave, 2-confirm it, or 3-say where it comes from?

It is messing up the noise floor on the Audio Network Analyzer, for me, and I would like to deal with it by filtering, or something. But, I'm not sure it is a reproducible issue. Any observations?
 
An update. This undesired square wave is at 1/24 th of the 44.1... kHz sample rate. This was determined by syncing the analog scope to the square wave and using a second trace to look at the 44.1... clock. Well, it is 1/24 a lot of the time.

Using the idea that if it would stay put relative to the 44.1 clock, I could subtract it out, I constructed an object with a square wave changing every 12 samples. Looking at the output of this and the original square wave, they stay synced for a while---sometimes many seconds, more often a fraction of a second. Then, the two jump a period of the 44.1, just like a PLL does when it is not quite able to lock. But, this means that the idea of subtracting the square wave out is more complicated, and generally flawed with transients when the cycle jumps occur. I can post code for this latter measurement, if somebody would like to observe the frequency jumping.

I'm still looking for input from others that observe this. Maybe I have the only one??? I have searched for possible non-CODEC sources, with no success. The 5-V line from the USB has some noise on it, but nothing at 1.8 kHz. Also, the internet does not seem to discuss it. Has anyone seen this?

Also, I need to emphasize that this is not a big signal. It is about +/- 12 in amplitude out of +/- 32768 or about 69 dB down from full input range. In many, many applications, this would be a very minor issue. The x200 in the above sketch makes it easily seen, though.

Thoughts? Bob
 
I started experimenting with Frank B.'s variable sampling rate for the SGTL5000 Teensy Audio Adaptor. Thank you, Frank, for the great feature. The discussion is here. The update is in this thread, because it allowed me to observe that the frequency of the square wave described above tracks the sample rate. I only took a sampling, but for 8, 44.117, 48, 96 and 192 kHz, it looked to be about 1/24 on the scope.

This means that moving sampling rates towards the low end keep moving the frequency into the peak human-audible range. For instance, a 16 kHz sampling rate moves the square wave to about 667 Hz. In addition , it appears, as others have observed, that low sampling rates like 8 kHz have more random noise. This makes decimation and interpolation very attractive, as was discussed on the other thread.

I am working on making a measurement tool, so this allows me to move the frequency around to avoid the frequency of measurement. I will be exploring this further.

Bob
 
OK, I'm about done exploring this question of the SGTL5000 ADC spectrum. I have run the 1024 point FFT on the ADC output. This was done by putting a gain of 100 on the ADC output so that it covers up the FFT noise (the FFT uses integer arithmetic that typically leaves 1 or 2 LSB of data "noise".) In addition, I introduced an external signal from an HP33120A generator, normally at 10 kHz, to show that A/D conversion was occurring. This signal is weak enough to not contribute any noise of its own. The output for all 512 bins was taken through Serial.print by only taking 1 out of 150 FFT's. This was put into LibreOffice spread sheet, producing the plots here. The spread sheet converted the voltage to power, averaged 40-powers for each frequency, converted this to dB and scaled the result to a full 16-bit input.

I ran a bunch of different sampling rates, using Frank B.'s divide/multiply constants. First, here is the plot for 44117.65 rate
FFTScreen44117Hz10KHz.gif
It shows the square wave at 1838 Hz as three components, the fundamental, third and fifth harmonics. Apparently the higher odd harmonics are hidden in the noise, as the 7th bump suggests. In any event, this is the expected spectrum. Comparing these spectral spikes with the 10 KHz shows that they are somewhat broader in spectrum than a good sine wave. The spike at 1838 is more than 70 dB down from full scale, and as pointed out before really a small disturbance. I did not try to add up the powers, but it appears that the ADC is meeting its specs with some margin.

What is notable is that there are spectral regions that are really quiet. This is really shown by running the sampling at 96 kHz:
FFTScreen96KHz_10KHz.gif
The region below 4 kHz is very quiet. For communications applications, the region from 12 to 20 KHz is very quiet, as are higher regions. This rate should be useful up to 40 kHz. Also note that as the sample rate goes up, the FFT noise bandwidth is also. So the base noise at the 96 kHz rate is around -110 dB, which is lower than at 44 kHz by perhaps 5 dB. But, it is really better on a dB/Hz basis, that is often the best measure. Adjusting for the sample rates, this makes an additional 3.4 advantage of 96KHz in dB/Hz.

I looked at other sample rates. I could not get output for 192 or 176.4 kHz. Low rates like 16 KHz are noisy and put the square wave at a bad spot.

Here is the sketch that was run for this.
Code:
// AudioVariRate.ino  Bob Larkin 22 Jan 2017
// Collect FFT spectrum of ADC with changing sample rate
// Variable sample rate from Frank B., see
// https://forum.pjrc.com/threads/38753-Discussion-about-a-simple-way-to-change-the-sample-rate
// As pointed out by Frank, the various routines, like waveform generator, are calibrated
// for 44.11765 and need to be corrected when other sample rates are used, e.g.,
//      waveform1.frequency(AUDIO_SAMPLE_RATE_EXACT/samplefreq*freq); 

#include <Audio.h>

//Note Teensy 3.6:  F_CPU == 180000000, F_PLL == 180000000
void setI2SFreq(int freq) {
  typedef struct {
    uint8_t mult;
    uint16_t div;
  } __attribute__((__packed__)) tmclk;
  const int numfreqs = 14;
  const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000};

#if (F_PLL==16000000)
  const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
#elif (F_PLL==72000000)
  const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
#elif (F_PLL==96000000)
  const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
#elif (F_PLL==120000000)
  const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
#elif (F_PLL==144000000)
  const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
#elif (F_PLL==168000000)
  const tmclk clkArr[numfreqs] = {{32, 2625}, {21, 1250}, {64, 2625}, {21, 625}, {128, 2625}, {42, 625}, {8, 119}, {64, 875}, {84, 625}, {16, 119}, {128, 875}, {168, 625}, {32, 119}, {189, 646} };
#elif (F_PLL==180000000)
  const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
#elif (F_PLL==192000000)
  const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
#elif (F_PLL==216000000)
  const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
#elif (F_PLL==240000000)
  const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
#endif

  for (int f = 0; f < numfreqs; f++) {
    if ( freq == samplefreqs[f] ) {
      while (I2S0_MCR & I2S_MCR_DUF) ;
      I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
      return;
    }
  }
}

uint16_t k;
const int samplefreq = 96000;  //   44117.64706;   //  int??

AudioInputI2S            i2s1; 
AudioMixer4              gain0;         // Just used as a gain block
AudioAnalyzeFFT1024      bFFT;
AudioConnection          patchCord1(i2s1,  0, gain0, 0);
AudioConnection          patchCord3(gain0, 0, bFFT,  0);
AudioControlSGTL5000     sgtl5000_1;
  
void setup()
  {
  Serial.begin(115200);
  delay(1000);
  AudioMemory(25);
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN);
  // 2 & 19 sets 2.2 v p-p range for Line in and out
  sgtl5000_1.lineInLevel(2);
  sgtl5000_1.lineOutLevel(19);
  // To override FFT noise, and see ADC noise, raise level by 40 dB
  // Allow for this extra 40 dB in post-processing
  gain0.gain(0,100);
  // Configure the window algorithm to use Hanning
  bFFT.windowFunction(AudioWindowHanning1024);
  setI2SFreq(samplefreq);           // Set the rate to samplefreq
  Serial.println(I2S0_MDR);         // Specific command value
  k=0;
  }

void loop()
  {
  int i;
  float d[512];

  if (bFFT.available())
    {
    // Transmit all 512 points, but only for one in every 150 FFT's
    // Simple way to slow down the data output
    if(k++ >= 150)
       {
       k=0;
       for (i=0; i<512; i++)          // Get a full data set quickly
           d[i] = bFFT.read(i);       // Get rms voltage
       for (i=0; i<512; i++)
          {
          Serial.print(3276.8*d[i]);  // Scale up to allow for 2 digits in .print
          Serial.print(" ");          // This leaves a LSB as 0.1 in the output
          }
       Serial.println();              // One row per data set
       }
    }
  }
My conclusion is that for my measurement and communications applications, a little playing with sample rates allows it to do a lot!

Bob
 
Status
Not open for further replies.
Back
Top