PDA

View Full Version : Analog Noise on A0, A2 but not on A9?



apleschu
02-20-2016, 11:57 PM
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.

apleschu
02-21-2016, 12:29 AM
Since I have time, before somebody complains, here is the code for the problem above:

Main file:


#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:


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


#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


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


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);
}

apleschu
02-21-2016, 01:53 AM
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.



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.