Electronic – Audio Noise: ATMEGA328P, MCP4921, and LM386

amplifieraudiodacnoise

I am trying to build a simple audio circuit. The goal is to store .wav files in the form of hex files in the ATMEGA328P's flash memory, and output the audio through a small speaker by using an MCP4921 DAC and an LM386N-1 Op Amp.

I uploaded a portion of my EAGLE schematic. The value of AMP_FIL_R is actually 0.05uF, instead of the 100uF indicated on the Eagle Schematic, and this is per the LM386 datasheet. Also, the code that I am running is attached. I started off with the code from here and added some code to play my hex file.

The Problem:
Although I am able to output a meow, it is coming out with a lot of noise. So, it sounds like the final sound I actually desire is fully there, but high frequency noise is added on top of it.

The Question:
What could be causing this noise? I have read a number of things could cause this. First, the LTC1514-5 power regulator I am using is in the 650kHz switching frequency range, so not sure if it is affecting the audio? Second, the LM386 op-amp itself, should it be farther away from the speaker? Unreliable connections in the breadboard? Proximity to bench equipment such as oscilloscope/meter/DC power supply?

Eagle Schematic

//"meow.h" file is stored as PROGMEM, char type variable

#include "avr/io.h"
#include "util/delay.h"
#include "HRL_SPI.h"
#include "HRL_MCP492x.h"
#include "meow.h"

void setup() {
  Serial.begin(9600);  
  // Initiate SPI in Mode 0 with MSB first, NO interrupts and a clock of F_CPU/4   
  setupSPI(SPI_MODE_0, SPI_MSB, SPI_NO_INTERRUPT, SPI_MASTER_CLK4);  
  SETUP_DAC;  
  _delay_us(100);    
}

int config = 0x30; //Mono, unbuffered, 1xGain, SHDN off  
word output = 0;  
word a=0; //index for meow array 

void loop() {

  if(a==sizeof(meow)) {Serial.print("again!"); delay(2000); a=0;}  
  output = pgm_read_byte(&(meow[a++]))*16; //Multiplied by 16 to go from 8 to 12 bits  

//  Serial.print("index:");  
//  Serial.print(a,DEC);  
//  Serial.print('\n');     
//  Serial.print("output:");  
//  Serial.print(output,DEC);  
//  Serial.print('\n');  
//  Serial.print('\n');    

  writeMCP492x(output,config);    
  _delay_us(125);    
}

Best Answer

Saturation.

You connected the reference voltage of MCP4921 to its \$V_{DD}\$, through a filter. This means that \$V_{REF}\$ is either 3.3V or 5V (I guess 5 V, because of your LTC1514-5).

This means that your analog signal has a maximum 5V peak to peak value. The LM386 in that configuration has a gain between 20 and 200. Assuming a gain of only 20 (which I doubt, as there is a \$10\ \mu F\$ cap), you get \$100\ V_{pp}\$, which of course can't be achieved, also because the LM386 maximum operating voltage is 12V.

You can try:

  • inserting a resistor in parallel to DEC_C6, to reduce the reference voltage (it can be as low as 0.04V). Still noise performance will drop I guess.
  • Attenuate Vout_A. But again, not only the noise performance will drop, but it would be a very inefficient solution: you attenuate the signal and the you amplify it back.
  • or use some non amplifying speaker driver configuration, so that it won't saturate.

Anyway keep the 386 away from the switching regulator. In fact the 386 is very non linear outside its bandwidth, and therefore the 650 kHz noise could be picked up and brought in band.