So, I have a 16x32 LED Panel and I have configured it with an Arduino UNO and using Processing i have been able to make it a spectrum Analyzer.
What i really want to do is hook up an electret microphone so it does not need to be hooked up to Processing/my computer the entire time.
Having trouble finding help on this online.
I want to do something very similar to the Piccolo project on here, but with a 16x32 LED panel instead of the the 8x8.
Help??
Thanks!
16x32 LED Panel as Spectrum Analyzer (need help!)
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- kctheelephant
- Posts: 4
- Joined: Thu Sep 04, 2014 11:44 am
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Are you looking to do something like this?
https://learn.adafruit.com/piccolo/overview
https://learn.adafruit.com/piccolo/overview
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
This might work. Requires the ffft library (same as used by Piccolo). In ffft.h, FFT_N *must* be set to 64 for this to work. Also, you might need to tweak the CLK/LAT/OE pin assignments to match your matrix wiring.
Code: Select all
#include <avr/pgmspace.h>
#include <ffft.h>
#include <math.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library
#define CLK 8 // MUST be on PORTB!
#define LAT 9
#define OE 9
#define A A0
#define B A1
#define C A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
#define ADC_CHANNEL 3 // Analog pin
int16_t capture[FFT_N]; // Audio capture buffer
complex_t bfly_buff[FFT_N]; // FFT "butterfly" buffer
uint16_t spectrum[FFT_N/2]; // Spectrum output buffer
volatile byte samplePos = 0; // Buffer position counter
// In library file ffft.h, FFT_N *must* be set to 64. Due to the RGB
// matrix overhead, there's only enough RAM for a 64 sample FFT buffer
// (32 spectrum outputs). Any higher WILL fail!
byte
peak[32], // Peak level of each column; used for falling dots
count = 0; // Frame counter for delaying dot-falling speed
int
minLvlAvg = 0, // For dynamic adjustment of low & high ends of the graph,
maxLvlAvg = 512; // pseudo rolling averages for the prior few frames.
// These two tables help the graph adjust dynamically to varying input:
PROGMEM uint8_t
// This is low-level noise that's subtracted from each FFT output column:
lower[32] = { 44,28,5,6,4,3,3,5,3,4,5,4,4,4,4,5,
3,4,4,3,4,4,4,4,4,3,4,3,4,3,4,5 },
// These are scaling quotients for each column. Partly for filtering out
// low-frequency (~150 Hz) noise from the FFT, and also because most music
// is simply heavy toward the low end (rhythm, bass).
upper[32] = { 200,160,90,48,23,11,5,3,1,1,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0 };
void setup() {
memset(peak, 0, sizeof(peak));
matrix.begin();
// Init ADC free-run mode; f = ( 16MHz/prescaler ) / 13 cycles/conversion
ADMUX = ADC_CHANNEL; // Channel sel, right-adj, use AREF pin
ADCSRA = _BV(ADEN) | // ADC enable
_BV(ADSC) | // ADC start
_BV(ADATE) | // Auto trigger
_BV(ADIE) | // Interrupt enable
_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1 / 13 = 9615 Hz
ADCSRB = 0; // Free run mode, no high MUX bit
DIDR0 = 1 << ADC_CHANNEL; // Turn off digital input for ADC pin
TIMSK0 = 0; // Timer0 off
sei(); // Enable interrupts
}
void loop() {
char c;
byte x, y, y2, r, g, b;
int hue, minLvl, maxLvl;
uint16_t n;
long level;
while(ADCSRA & _BV(ADIE)); // Wait for audio sampling to finish
fft_input(capture, bfly_buff); // Samples -> complex #s
samplePos = 0; // Reset sample counter
ADCSRA |= _BV(ADIE); // Resume sampling interrupt
fft_execute(bfly_buff); // Process complex data
fft_output(bfly_buff, spectrum); // Complex -> spectrum
// Get min & max levels in FFT output:
for(x=0; x<32; x++) {
level = (long)spectrum[x] - (long)pgm_read_byte(&lower[x]); // rm noise
if(level < 0L) level = 0L; // Clip...else fixed-point scale:
else level = (level * (256L - pgm_read_byte(&upper[x]))) >> 8;
if(x == 0) {
minLvl = maxLvl = level;
} else {
if(level < minLvl) minLvl = level;
else if(level > maxLvl) maxLvl = level;
}
}
// minLvl and maxLvl indicate the extents of the FFT output, used
// for vertically scaling the output graph (so it looks interesting
// regardless of volume level). If they're too close together though
// (e.g. at very low volume levels) the graph becomes super coarse
// and 'jumpy'...so keep some minimum distance between them (this
// also lets the graph go to zero when no sound is playing):
if((maxLvl - minLvl) < 8) maxLvl = minLvl + 8;
minLvlAvg = (minLvlAvg * 7 + minLvl) >> 3; // Dampen min/max levels
maxLvlAvg = (maxLvlAvg * 7 + maxLvl) >> 3; // (fake rolling average)
// Render display:
for(x=0, hue=0; x<32; x++, hue += 40) { // For each column...
level = (long)spectrum[x] - (long)pgm_read_byte(&lower[x]); // rm noise
if(level < 0L) level = 0L; // Clip...else fixed-point scale:
else level = (level * (256L - pgm_read_byte(&upper[x]))) >> 8;
// Second fixed-point scale based on dynamic min/max levels:
level = ((level - minLvlAvg) * 16L) / (long)(maxLvlAvg - minLvlAvg);
// Clip output and convert to byte (column height...0 to 16):
if(level < 0L) c = 0;
else if(level > 16L) c = 16;
else c = (char)level;
if(c > peak[x]) peak[x] = c; // Keep white dot on top
if(peak[x] <= 0) { // Empty column?
matrix.drawLine(x, 0, x, 15, 0);
continue;
}
y = 16 - peak[x]; // y = 0 to 15
if(y > 0) matrix.drawLine(x, 0, x, y-1, 0); // Fill black above peak
// WILL CRASH HERE if out of RAM!
matrix.drawPixel(x, y, 0xffff); // Draw white dot at peak
// Draw fading streak from below peak to just above current level
for(y++, y2 = 16 - c, n=150; y < y2; y++) {
matrix.drawPixel(x, y, matrix.ColorHSV(hue, 255, n, true));
if(n >= 50) n -= 50;
}
// Draw bar for current level, with slight glow at top
y = y2;
n = 100;
// If current level is peak, don't overwrite white dot
if(c == peak[x]) {
y++;
n = 150;
}
while(y < 16) {
matrix.drawPixel(x, y, matrix.ColorHSV(hue, n, 255, true));
n += 50;
if(n > 255) n = 255;
y++;
}
}
// Every alternate frame, make the peak pixels drop by 1:
if(++count == 1) {
count = 0;
for(x=0; x<32; x++) {
if(peak[x] > 0) peak[x]--;
}
}
}
ISR(ADC_vect) { // Audio-sampling interrupt
static const int16_t noiseThreshold = 4;
int16_t sample = ADC; // 0-1023
capture[samplePos] =
((sample > (512-noiseThreshold)) &&
(sample < (512+noiseThreshold))) ? 0 :
sample - 512; // Sign-convert for FFT; -512 to +511
if(++samplePos >= FFT_N) ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off
}
- kctheelephant
- Posts: 4
- Joined: Thu Sep 04, 2014 11:44 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
The code you gave me seems like it will work when i understand it better! i'm a little lost on all the #defines though. for my 16x32 panel i have plugged it into my Arduino just like the Adafruit wiring guide says.
Could you explain your code a little more? Or guide me to more tutorials on this type of code?
Thank you!
Could you explain your code a little more? Or guide me to more tutorials on this type of code?
Thank you!
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Hmmm...actually I'd suggest changing one wire vs. the standard tutorials: move the LAT wire from pin A3 to pin 9 (you'll probably need to use a breadboard or solder up a little Y-splitter jumper, since this pin is now going both to LAT and OE). 3.3V goes to mic amp + and the Arduino's AREF pin. Mic output goes to A3. Mic - to GND. Then use the code as-is.
As for explaining it...erf...this is actually some pretty hairy stuff and would fill a book. If there's anything specific that's not covered in the comments, I could try to offer some guidance, but otherwise it's extremely non-trivial. I just had it around from a project we never released, posted it since it pretty much matches your description.
As for explaining it...erf...this is actually some pretty hairy stuff and would fill a book. If there's anything specific that's not covered in the comments, I could try to offer some guidance, but otherwise it's extremely non-trivial. I just had it around from a project we never released, posted it since it pretty much matches your description.
- kctheelephant
- Posts: 4
- Joined: Thu Sep 04, 2014 11:44 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
I tried what you suggested in the previous comment and used your code as is, i got no results. Then i tried moving the LAT to a3, the mic to A4, and the OE at pin 9, and editted the code accordingly, still with no results.
Any ideas?
Any ideas?
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Use the wiring layout suggested; this was chosen for a reason, though it's been so long I can't remember exactly what that reason was. But I digress...
Did you change the ffft.h library as described?
If it still refuses to work, I would suggest first trying to get some of the other RGBmatrix library examples working with the alternate wiring as described (LAT on pin 9, should require just a one-line change to most of the demos). If it doesn't work, then either A) the wiring is wrong, or B) the code doesn't match the wiring. I can't help troubleshoot this further without A) clear photos of the wiring between Arduino and matrix, and B) the pin #defines and RGBmatrix constructor call from the beginning of the sketch.
Once you get that working, then try the full code I previously posted here.
Did you change the ffft.h library as described?
If it still refuses to work, I would suggest first trying to get some of the other RGBmatrix library examples working with the alternate wiring as described (LAT on pin 9, should require just a one-line change to most of the demos). If it doesn't work, then either A) the wiring is wrong, or B) the code doesn't match the wiring. I can't help troubleshoot this further without A) clear photos of the wiring between Arduino and matrix, and B) the pin #defines and RGBmatrix constructor call from the beginning of the sketch.
Once you get that working, then try the full code I previously posted here.
- kctheelephant
- Posts: 4
- Joined: Thu Sep 04, 2014 11:44 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Where/what exactly in the fft needs to be changed? I'm struggling to find it.
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Second line in ffft.h:
Should be changed to:
Code: Select all
#define FFT_N 128 /* Number of samples (64,128,256,512). */
Code: Select all
#define FFT_N 64 /* Number of samples (64,128,256,512). */
- rb3
- Posts: 1
- Joined: Sun Feb 24, 2013 6:46 pm
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Is the the correct modification do get around the update to Ardunio 1.6.6?
Code: Select all
PROGMEM const uint8_t
// This is low-level noise that's subtracted from each FFT output column:
lower[32] = { 44,28,5,6,4,3,3,5,3,4,5,4,4,4,4,5,
3,4,4,3,4,4,4,4,4,3,4,3,4,3,4,5 },
// These are scaling quotients for each column. Partly for filtering out
// low-frequency (~150 Hz) noise from the FFT, and also because most music
// is simply heavy toward the low end (rhythm, bass).
upper[32] = { 200,160,90,48,23,11,5,3,1,1,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0 };
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Yes, that will work
- gbalici
- Posts: 5
- Joined: Wed Aug 31, 2016 3:09 pm
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
Hello, what to use if instead of a mic I want to use a line in?
Could that be connected to A4?
Why LAT and OE are connected to pin 9? Shouldn't LAT be connected to A3?
Thanks!
Could that be connected to A4?
Why LAT and OE are connected to pin 9? Shouldn't LAT be connected to A3?
Thanks!
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
What is the voltage of the line-in signal? it should be biased so that the range is 0 to 5V (0 to 3.3V if you're using a 3.3V processor.
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
As Phil said in his earlier post:gbalici wrote:Why LAT and OE are connected to pin 9? Shouldn't LAT be connected to A3?
Use the wiring layout suggested; this was chosen for a reason, though it's been so long I can't remember exactly what that reason was. But I digress...
- gbalici
- Posts: 5
- Joined: Wed Aug 31, 2016 3:09 pm
Re: 16x32 LED Panel as Spectrum Analyzer (need help!)
I was hoping you'd remember it :)
Please be positive and constructive with your questions and comments.