Rank beginner question: Test tone for ADC test

clinker8

Well-known member
I haven't spent that much time with this yet, but I am considering using the audio library to create a test sine wave to check an external ADC.

From what I understand, I can control amplitude, frequency, and phase.

I need the tone centered about Vref/2 of the ADC. I suppose I can simply use an op amp for that. The ADC I am trying to check my Teensy driver code on is the AD7667. Is the code as easy as the following? Or is there more to it than this? I have never used these tools. I will use a Teensy4 and an audio shield as the stimulus for my ADC running data collection on a Teensy4.1.
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine1;          //xy=185.1666717529297,260.1666717529297
AudioMixer4              mixer1;         //xy=414.1666717529297,272.1666717529297
AudioOutputI2S           i2s1;           //xy=711.1666717529297,276.1666717529297
AudioConnection          patchCord1(sine1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, 0, i2s1, 0);
AudioConnection          patchCord3(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=316.1666717529297,424.1666717529297
// GUItool: end automatically generated code

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(10);

  // 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.8); // caution: very loud - use oscilloscope only!
  sine1.amplitude(0.1);
  sine1.frequency(1e4);
  sine1.phase(0.0);
}

void loop() {
  // put your main code here, to run repeatedly:

}
As a completely new person to this, does the signal come out at the line level? I need to drive a 10k load (which is buffered and drives the ADC with an amplifier).

On the second Teensy with the ADC I want to capture about 16K samples and do a floating point FFT. I haven't even thought about how to start that. But first, I simply need to generate a clean sine wave. How many bits is the audio generator? The sampling rate is currently 1 MHz, although I can adjust it.

Be gentle, but kindly point me in the right direction :) Much appreciated.
 
Seem to have gotten something to work. Final code is:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine1;          //xy=185.1666717529297,260.1666717529297
AudioMixer4              mixer1;         //xy=414.1666717529297,272.1666717529297
AudioOutputI2S           i2s1;           //xy=711.1666717529297,276.1666717529297
AudioConnection          patchCord1(sine1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, 0, i2s1, 0);
AudioConnection          patchCord3(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=316.1666717529297,424.1666717529297
// GUItool: end automatically generated code

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(10);

  // 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.75); // caution: very loud - use oscilloscope only!
  sine1.amplitude(0.95);
  sine1.frequency(10e3);
  sine1.phase(0.0);
  mixer1.gain(0, 1.0);
}

void loop() {
  // put your main code here, to run repeatedly:

}
At low levels there seems to be a bit of noise. I presume this is power supply noise and whatever coupling in via the USB? A USB isolator might reduce this noise? Will I be able to use a 12Mbps isolator? The 480Mbps ones seem to be quite a step up in price.

FFT shows not bad performance. Harmonic at 30KHz is making the SFDR less than 16 bits, but darn good for my makeshift tone generator.
 

Attachments

  • PXL_20230225_214056728_1080.jpg
    PXL_20230225_214056728_1080.jpg
    235.7 KB · Views: 18
Looks like you got it working!

To answer this question...

Will I be able to use a 12Mbps isolator?

This 12 Mbit USB isolator is known to work with Teensy 4.x.

https://hifimediy.com/product/usb-isolator/

A few "no name" ones with ADUM3160 chips have also worked when tested. These products look visually similar to the ones I personally tested, but impossible to know if they're exactly the same model.

https://www.amazon.com/Isolator-Protection-Isolation-ADUM3160-Module/dp/B08HHW4DXY

https://www.amazon.com/OCESTORE-Isolator-ADUM3160-Isolation-Protection/dp/B09W951K13
 
Seem to have gotten something to work. Final code is:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine1;          //xy=185.1666717529297,260.1666717529297
AudioMixer4              mixer1;         //xy=414.1666717529297,272.1666717529297
AudioOutputI2S           i2s1;           //xy=711.1666717529297,276.1666717529297
AudioConnection          patchCord1(sine1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, 0, i2s1, 0);
AudioConnection          patchCord3(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=316.1666717529297,424.1666717529297
// GUItool: end automatically generated code

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(10);

  // 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.75); // caution: very loud - use oscilloscope only!
  sine1.amplitude(0.95);
  sine1.frequency(10e3);
  sine1.phase(0.0);
  mixer1.gain(0, 1.0);
}

void loop() {
  // put your main code here, to run repeatedly:

}
At low levels there seems to be a bit of noise. I presume this is power supply noise and whatever coupling in via the USB? A USB isolator might reduce this noise? Will I be able to use a 12Mbps isolator? The 480Mbps ones seem to be quite a step up in price.

FFT shows not bad performance. Harmonic at 30KHz is making the SFDR less than 16 bits, but darn good for my makeshift tone generator.

You are measuring the performance of the oscilloscope's front end I suspect - scopes like that one are 8 bit - some can be configured for ~11 bits effective, but the front end analog stage is not very linear anyway (it doesn't have to be). A good soundcard is the simplest way to measure audio distortion these days, as many of them have good distortion figures.
 
@MarkT, Probably so. Sound cards aren't bad - if you have one. They are also limited to audio rates. Eventually hope to measure impulses coming from a PIN diode, due to scattered low energy X-rays. Unfortunately the X-ray events are randomly distributed (in time) and don't occur at audio rates all the time.

My ultimate test is to use an external 16 bit 1MSPS ADC. Did a sanity check on the ADC itself by measuring its own 2.5V DC reference. I get a spurious tone at -115 dBC at approximately 198.5 KHz. The noise is not quite flat, there is a little bit of structure to it. At lower sample rates, the noise seems to flatten more. Used the Teensy to compute a 4K FFT in single precision floating point using the CMSIS-DSP library. Used a flextimer PWM to control the sampling. Things will be a lot worse for tones, especially ones near fs/2.

Was hoping the PRJC audio board was sufficient to help characterize my ADC, an AD7667. It's probably not quite good enough, but that is what I have at the moment.

For some reason my python script isn't allowing me to save files - and I can't cut and paste an image on this message board. When I get my file saving fixed, I can post a graph.
 
matplotlib was acting up. Here are the two pictures, first the time domain. The time domain figure is partially cut off. The signal is 2.499000V plus what you see on the Y-axis. Midpoint is roughly 2.4990 + 0.00025V. 4096 samples from my 16 bit ADC. For the FFT, the Teensy performed a 4K 32 bit floating point FFT on the time domain samples. The tone at DC is due to the mean value of the ADC samples.
 

Attachments

  • teensyadcdat.png
    teensyadcdat.png
    38.1 KB · Views: 13
  • teensyfft4k.png
    teensyfft4k.png
    36.2 KB · Views: 12
Back
Top