Attached is a copy of my Christmas hat .ino. Things went well until I combined the code clips from my stand alone FFT Neopixels.ino and my xmas hat Neopixels .ino. It produces a very specific program error, as if the "pix5" is being overwritten outside the audio while loop.
The program first time through the loop works as intended, subsequent iterations through the loop the audio code works as intended except for the neopixel related to "pix5". There are 16 pixels spread out over the hat. After the first time through the main loop, pix5 according to the serial terminal has values much higher than the 255 the setColor(); in the Neopixel library supports. Due to the Mic preamp setup, and the way i had to hack the pro mini for Aref access, setting the FFT library to LINOUT8 (8 bit scaled output) will barely light the neopixels. LINOUT gives the best results for displaying what our ears pickup. Aref was using a 4.096V precision Vref module from Adafruit for Aref, mic Vcc, and input biasing. It all worked well UNTIL I combined that code with the neopixel demo codes.
Something broke something inside my program and I cant seem to isolate the problem. I tried the pix# variables as word and byte, and as local and global variables. They all produce the same results. Neopixel library disables interrupts while its constructing its output stream, but I believe re-enables them once the output stream is finished because of the use of delay() in the neopixel demo code..
The mic doesn't have a low-pass filter on it, but the FFT code is the same for the stand alone version. So how is it that only one variable in the whole program seems to be getting overwritten after the neopixel demos run and returns to the audio code?
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#include <avr/wdt.h>
#define LIN_OUT 1
#define FFT_N 128 // set to 64 point fft
#include <FFT.h> // include the library
#define NUMPIXELS 16
#define PIN 10
#define debug 9
#define DEBUG 4
#define debug_active true
boolean debugFFT, debugfft = false;
byte p,m,j;
int k;
word bins = 0;
word Time = 0;
#define decay 1
#define noise_floor 32
#define looptime 20
unsigned long prevTime,currTime = 0;
const word spekTime = 2660;
const byte chaseTime = 80;
volatile byte scale = 6;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
//#if defined (__AVR_ATmega328__)
ADCSRA = 0xf6; // set the adc to free running mode (f6 = 9.6kHz bandwidth)
ADMUX = 0; // use Aref & ADC0(Pc0) ATMEGA328
DIDR0 = 0x1F; // disable digital inputs for A0:A5 on ATMEGA328(pg 251 datasheet)
pinMode(PIN, OUTPUT);
pinMode(debug, INPUT);
pinMode(DEBUG, INPUT);
pinMode(5,OUTPUT);
digitalWrite(5,HIGH);
pixels.begin();
pixels.show();
Serial.begin(115200);
interrupts();
}
void loop() {
Time = spekTime;
TIMSK0 = 0x0; // turn off timer0 for lower jitter
spectrum_vis();
TIMSK0 = 0x1;
// Some example procedures showing how to display to the pixels:
colorWipe(pixels.Color(255, 0, 0), chaseTime); // Red
colorWipe(pixels.Color(0, 255, 0), chaseTime); // Green
colorWipe(pixels.Color(0, 0, 255), chaseTime); // Blue
colorWipe(pixels.Color(192,192,192),chaseTime); //white
pixels.clear();
pixels.show();
Time = spekTime;
TIMSK0 = 0x0; // turn off timer0 for lower jitter
spectrum_vis();
TIMSK0 = 0x1;
// Send a theater pixel chase in...
theaterChase(pixels.Color(127, 127, 127), chaseTime); // White
theaterChase(pixels.Color(127, 0, 0), chaseTime); // Red
theaterChase(pixels.Color(0, 0, 127), chaseTime); // Blue
theaterChase(pixels.Color(255,64,8), chaseTime); // gold
theaterChase(pixels.Color(255,64,8), chaseTime); // gold
pixels.clear();
pixels.show();
Time = spekTime;
TIMSK0 = 0x0; // turn off timer0 for lower jitter
spectrum_vis();
TIMSK0 = 0x1;
rainbow(25);
rainbowCycle(10);
theaterChaseRainbow(75);
pixels.clear();
pixels.show();
}
void spectrum_vis(){
DIDR0 = 0x1F; // disable digital inputs for A0:A5 on ATMEGA328(pg 251 datasheet)
byte pix1, pix2, pix3, pix4, pix5, pix6 = 0;
while (1) { // reduces jitter
Time --;
//PORTD ^= (1<<PD5); //XOR toggle for loop time measure
if(Time == 0) break;
if (debug_active == true) {
debugFFT = PINB & B10; //just read the damned pin already!
debugfft = PINB & B1;
}
cli();
for (int i = 0 ; i < FFT_N * 2 ; i += 2) { // save 256 samples
while (!(ADCSRA & 0x10)) {}; // wait for adc to be ready
ADCSRA = 0xf6; // start adc sample @0xf5 38.4kHz || 0xf6 = 19.2kHz (9.6kHz Nyquist)
m = ADCL ; // fetch adc data
j = ADCH;
k = (j << 8) | m; // form into an int (ignore 2LSB)
k -= 0x200; // form into a signed int DC offset 619 count(0x26b)
k <<= scale; // form into a 16b signed int
fft_input[i] = k ; // put real data into even bins
fft_input[i + 1] = 0; // set odd bins to 0
}
if (debug_active == true) {
if (debugFFT == false && debugfft == false) {
for (int r = 0; r < FFT_N >> 1; r += 2) {
Serial.println(fft_input[r]);
}
}
}
fft_window(); // window the data for better frequency response
fft_reorder(); // reorder the data before doing the fft
fft_run(); // process the data in the fft
fft_mag_lin(); // take the output of the fft
sei();
bins = 0;
for (p = FFT_N >> 1; p > (FFT_N >> 2) + 1; p--) {
bins = fft_lin_out[p];
if (bins > pix5) {
pix5 = bins << 1;
if(pix5>255) pix5 = 255;
}
}
for (p = FFT_N >> 2; p > (FFT_N >> 3) + 1; p--) {
bins = fft_lin_out[p];
if (bins > pix4) {
pix4 = bins << 1;
}
}
for (p = FFT_N >> 3; p > (FFT_N >> 5) + 1; p--) {
bins = fft_lin_out[p];
if (bins > pix3) {
pix3 = bins;
}
}
//for (p = FFT_N >> 4; p > (FFT_N >> 5) + 1; p--) {
bins = fft_lin_out[1];
if (bins > pix2) {
pix2 = bins;
}
bins = fft_lin_out[0];
if (bins > pix1) {
pix1 = bins >> 1;
}
bins = 0;
if (pix5 > 128) pix5 -= decay << 2;
if (pix5 > 64) pix5 -= decay << 1;
if (pix5 > decay) pix5 -= decay;
if (pix5 < noise_floor) pix5 = 0;
if (pix4 > 128) pix4 -= decay << 3;
if (pix4 > 64) pix4 -= decay << 1;
if (pix4 > decay) pix4 -= decay;
if (pix4 < noise_floor) pix4 = 0;
if (pix3 > 192) pix3 -= decay << 4;
if (pix3 > 64) pix3 -= decay << 2;
if (pix3 > decay) pix3 -= decay;
if (pix3 < noise_floor) pix3 = 0;
if (pix2 > 128) pix2 -= decay << 4;
if (pix2 > 64) pix2 -= decay << 2;
if (pix2 > decay) pix2 -= decay;
if (pix2 < noise_floor) pix2 = 0;
if (pix1 > 128) pix1 -= decay << 4;
if (pix1 > 64) pix1 -= decay << 2;
if (pix1 > decay) pix1 -= decay;
if (pix1 < noise_floor) pix1 = 0;
pixels.setPixelColor(4, pixels.Color((pix5 >> 1), 0, pix5));
pixels.setPixelColor(3, pixels.Color(0, pix4, pix4));
pixels.setPixelColor(2, pixels.Color( 0, pix3, 0));
pixels.setPixelColor(1, pixels.Color(pix2, (pix2 >> 1), 0));
pixels.setPixelColor(0, pixels.Color(pix1, 0, 0));
delay(looptime);
pixels.show(); // very important!
FFTneoPixels.ino (13.6 KB)