I'm making an FFT spectrum analyzer and I've got it working, but when I tried implementing a gradient effect, the matrix would run for a second then freeze for two seconds. I'm pretty certain its due to poor software, but I just started with LEDs and FastLED, so bear with me. If someone could help me diagnose this lag or suggest a better way to write out to the LEDs, that would be appreciated.
The way I write out to the LEDs is weird due to the direction of data I wired up my LEDs in. The data direction zigzags: one column goes up, the next down, the next up and so on.
#define LIN_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft
#define DC_OFFSET 511
#define SAMPLING_FREQ (16000000/(13*32))
#include <FFT.h> //FFT library
#include <FastLED.h> //FastLED library
#define LED_DT 6 //LED data pin
#define COLOR_ORDER GRB //WS2812b specific
#define LED_TYPE WS2812B
#define NUM_LEDS 288 //Number of LEDs in project
#define COL_HEIGHT 9 //height of column
struct CRGB leds[NUM_LEDS];
int adc_val;
void setup() {
delay(1000); //soft startup to ease flow of electrons
LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(15);
TIMSK0 = 0; // turn off timer0 for lower jitter - delay() and millis() killed
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
}
void loop() {
while (1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
while (!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= DC_OFFSET;
adc_val = k<<6;
fft_input[i] = adc_val; // put real data into even bins
fft_input[i + 1] = 0; // set odd bins to 0
}
// window data, then reorder, then run, then take output
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(); // turn interrupts back on
fft_lin_out[1] -= 10; //adjust for values in bin when silent (unknown cause)
fftDisplay();
FastLED.show();
}
}
void fftDisplay() {
int i, j, k, colHeight, startIndex;
for(i = 1; i < 33; i++) //traverse columns from left to right, i represents col # as well as bin #
{
if (i % 2 == 0) //code for writing LEDs to even # columns (due to alternating data directions)
{
colHeight = map((unsigned char)fft_lin_out[i], 0, 235, 0, 9); //map FFT output from 0-255 (value of unsigned char) to 0-9
startIndex = 9 * i - 1; //figure out starting index of ith column (repeats every 2nd column since data direction alternates)
j = startIndex - colHeight + 1; //figure out ending index based on colHeight to be input to fill_gradient
fill_gradient(leds, startIndex, CHSV(0, 255, 255), j, CHSV(0, 125, 255), SHORTEST_HUES);
for(k = j - 1; k > startIndex - COL_HEIGHT; k--) //turn off all *other* LEDs in ith column
{
leds[k] = CRGB::Black; //turn off leds that are not in use
}
}
else //code for writing LEDs to odd # columns.
{
colHeight = map((unsigned char)fft_lin_out[i], 0, 235, 0, 9);
startIndex = 9 * (i-1); //starting LED index of ith column
j = startIndex + colHeight - 1;
fill_gradient(leds, startIndex, CHSV(0, 255, 255), j, CHSV(0, 125, 255), SHORTEST_HUES);
for(k = j + 1; k < startIndex + COL_HEIGHT; k++)
{
leds[k] = CRGB::Black; //turn off leds that are not in use
}
}
}
}