Analog Noise on A0, A2 but not on A9?

Status
Not open for further replies.

apleschu

Member
So, First, I know I have not posted a lot of code, but in this case ... hear me out

I am in the process of programming a relatively bigger project, and while working on one of the modules (FFT with LED display) from the audio library I found it weird that I always have a lot of noise on the default adc1 input (A2) Noise that was specifically according to the FFT above 5kHz and below 100Hz.

I ran many, many tests including isolating the power supply from the LED's driving them from the 3.3V or from the 5V or from external battery or from USB, nothing seemed to make any difference. finally I started to dig into the code and thought: Hmm,, I wonder if different audio inputs behave differently... I switched the analog adc to A( and lo and behold, the noise is gone. the only differences are the audio in in the software and then of course the wire on the breadboard.

And yes, before you ask, the noise was substantial.

Does that make any sense? And if so why?

And if somebody wants to dig through 200 lines of code, I'll be happy to post. since precisely the same code works as expected on A9, I don't believe this is in the code.
 
Since I have time, before somebody complains, here is the code for the problem above:

Main file:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <FastLED.h>
#include <RunningAverage.h>
#include <EEPROM.h>
#include <FastCRC.h>

#define NUM_LEDS 21
#define DATA_PIN  11
#define CLOCK_PIN 13
#define COLOR_ORDER BGR
#define CHIPSET     APA102

#include "definitions.h"

CRGB leds[NUM_LEDS];
float mgain1 = 1.0;
float mgain2 = 1.0;
static uint8_t Debug = 1;

#include "AudioDefinitions.h"

RunningAverage avg(255);

#include "misc.h"
#include "setup.h"


void loop() { 
  double val = 0;
  
  if (fft.available()) {
//    cLed(0,1,1);      // 43
    cLed(1,2,3);      // 86
    cLed(2,3,4);      // 172
    cLed(3,5,8);      // 344  
    cLed(4,9,16);     // 688
    cLed(5,17,32);    // 1376
    cLed(6,33,64);    // 2752
    cLed(7,65,128);   // 5504
    cLed(8,129,255);  // 11008
//    cLed(9,256,511);  // rest

    val = fft.read(2,128);
    avg.addValue(val);
    double ravg = avg.getAverage();

    if (Debug != 0) {
      Serial.print(mgain1);
      Serial.print("\t");
      Serial.println(ravg);
    }

 
    if (ravg > TargetAVG)
      mgain1 -= GainAdjust;
    else
      mgain1 += GainAdjust;

    if (mgain1 > MAXGAIN)
      mgain1 = MAXGAIN;         //lets not overdo it!
    if (mgain1 < MINGAIN)
      mgain1 = MINGAIN;         // same here
    mixer.gain(0, mgain1);
    
    FastLED.show();
  }
}

Audiodefinitions.h:
Code:
AudioInputAnalog          adc1(A9); 
AudioMixer4              mixer;         
AudioAnalyzeFFT1024      fft; 
AudioAnalyzePeak         peak;  
AudioConnection          patchCord1(adc1, 0, mixer, 0);
//AudioConnection          patchCord2(adc1, 0, mixer, 1);
AudioConnection          patchCord3(mixer, fft);
AudioConnection          patchCord4(mixer, peak);    
//AudioConnection          patchCord1(adc1, fft);

definitions.h
Code:
#define BRIGHTNESS  255
#define NoiseFloor  0.06
#define TargetAVG   0.9               // Target avg for AGC
#define GainAdjust  0.001            // AGC uses this value to increase or decrease gain each loop, bigger values make AGC react faster
#define MAXGAIN     3               // AGC will not set the mixer gain higher than this
#define MINGAIN     0.01              // AGC will not set mixer gain lower than this
#define LogCurve    3

misc.h
Code:
uint8_t cVal(int start, int end){
  double val = 0;                         // starting value
  double res = 0;

  val = fft.read(start,end);          // add 1 so that we get to the correct part of the log2 curve
  if ( val > NoiseFloor ) {
    res = (((log(val) / log(LogCurve)) + LogCurve) / LogCurve) *255;
    return((uint8_t) res);
  } else {
    return(0);
  }
}

void cLed(int i, int start, int end){
  uint8_t val = cVal(start,end);
  leds[i] = CHSV(val, 200, val>>1);
}

setup.h
Code:
void setup() {
  Serial.begin(9600);
  while (!Serial);                    // wait for serial to start
  
  AudioMemory(10);
  FastLED.addLeds<APA102,11,13,BGR,DATA_RATE_MHZ(10)>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
  FastLED.setBrightness( BRIGHTNESS );
  FastLED.setMaxPowerInVoltsAndMilliamps(5,200);
  for (int i = 0; i < NUM_LEDS; i++)
    leds[i] = 0x000000;
  FastLED.show();
  // Uncomment one these to try other window functions
  // fft1024_1.windowFunction(NULL);
  // fft.windowFunction(AudioWindowBartlett1024);
  //fft.windowFunction(AudioWindowFlattop1024);
  avg.clear();
  mixer.gain(0, mgain1);
//  mixer.gain(1, mgain2);
  delay(1000);
}
 
Last edited:
Well, I think I solved the problem myself. My code allowed to crank the gain on the mixer up to 5.0/3.0 depending on which version. Looks like those high frequency artefacts are coming from the mixer at gain values of more than 1.0.

And to some extent I can understand it (after the fact) that poor mixer was trying to crank something into usable value range that just was not there. and you can't amplify a signal thats just not there.

At the same time I changed the display instead of being a log3 display to be a log10 display, which is much crisper, and easier to understand. And thirdly I changed the way the color of the LED is calculated, so that at theoretical 100% (255) it would be red, starting at green.

So, here is the changed way the values of a LED is calculated for those interested and have a similar problem.

Code:
uint8_t cVal(int start, int end){
  double val = 0;                         // starting value
  double res = 0;

  val = fft.read(start,end);          // add 1 so that we get to the correct part of the log2 curve
  if ( val > NoiseFloor ) {
      res = ((log10(val) + 2) / 2) * 255;
//    res = (((log(val) / log(LogCurve)) + LogCurve) / LogCurve) *255;    /// log 3 to log 5
    return((uint8_t) res);
  } else {
    return(0);
  }
}

void cLed(int i, int start, int end){
  uint8_t val = cVal(start,end);
  leds[i] = CHSV(127 - (val>>1), 255, val);
}

The only problem with this calculation is the the noisefloor, in my case at 0.04 to 0.05 gives an output value of about 0.3. which mean that you have to map the values between 0.3 and 1.0 at your number of leds if what you are creating is a spectrum analyzer.
 
Status
Not open for further replies.
Back
Top