Merge pull request #7 from s-marley/Neomatrix

Added Neomatrix support
pull/16/head
s-marley 2021-02-17 19:33:10 +00:00 zatwierdzone przez GitHub
commit 9645716276
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
2 zmienionych plików z 33 dodań i 46 usunięć

72
ESP32_FFT_VU/ESP32_FFT_VU.ino 100644 → 100755
Wyświetl plik

@ -1,7 +1,8 @@
// (Heavily) adapted from https://github.com/G6EJD/ESP32-8266-Audio-Spectrum-Display/blob/master/ESP32_Spectrum_Display_02.ino
// Adjusted to allow brightness changes on press+hold, Auto-cycle for 3 button presses within 2 seconds
// Edited to add Neomatrix support for easier compatibility with different layouts.
#include <FastLED.h>
#include <FastLED_NeoMatrix.h>
#include <arduinoFFT.h>
#include <EasyButton.h>
@ -68,27 +69,11 @@ CRGBPalette16 greenbluePal = greenblue_gp;
CRGBPalette16 heatPal = redyellow_gp;
uint8_t colorTimer = 0;
// XY code for serpentine matrix with input in top left
uint16_t XY( uint8_t x, uint8_t y) {
uint16_t i;
y = kMatrixHeight - 1 - y; // Adjust y coordinate so (0,0) is bottom left
if(SERPENTINE) {
if( y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (kMatrixWidth - 1) - x;
i = (y * kMatrixWidth) + reverseX;
} else {
// Even rows run forwards
i = (y * kMatrixWidth) + x;
}
}
else {
i = (y * kMatrixWidth) + x;
}
return i;
}
// FastLED_NeoMaxtrix - see https://github.com/marcmerlin/FastLED_NeoMatrix for Tiled Matrixes, Zig-Zag and so forth
FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, kMatrixWidth, kMatrixHeight,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG +
NEO_TILE_TOP + NEO_TILE_LEFT + NEO_TILE_ROWS);
void setup() {
Serial.begin(115200);
@ -138,7 +123,7 @@ void loop() {
for (int i = 0; i<NUM_BANDS; i++){
bandValues[i] = 0;
}
// Sample the audio pin
for (int i = 0; i < SAMPLES; i++) {
newTime = micros();
@ -156,7 +141,7 @@ void loop() {
// Analyse FFT results
for (int i = 2; i < (SAMPLES/2); i++){ // Don't use sample 0 and only first SAMPLES/2 are usable. Each array element represents a frequency bin and its value the amplitude.
if (vReal[i] > NOISE) { // Add a crude noise filter
/*8 bands, 12kHz top band
if (i<=3 ) bandValues[0] += (int)vReal[i];
if (i>3 && i<=6 ) bandValues[1] += (int)vReal[i];
@ -189,7 +174,7 @@ void loop() {
// Process the FFT data into bar heights
for (byte band = 0; band < NUM_BANDS; band++) {
// Scale the bars for the display
int barHeight = bandValues[band] / AMPLITUDE;
if (barHeight > TOP) barHeight = TOP;
@ -201,7 +186,7 @@ void loop() {
if (barHeight > peak[band]) {
peak[band] = min(TOP, barHeight);
}
// Draw bars
switch (buttonPushCounter) {
case 0:
@ -249,10 +234,10 @@ void loop() {
// Save oldBarHeights for averaging later
oldBarHeights[band] = barHeight;
}
// Decay peak
EVERY_N_MILLISECONDS(60) {
for (byte band = 0; band < NUM_BANDS; band++)
for (byte band = 0; band < NUM_BANDS; band++)
if (peak[band] > 0) peak[band] -= 1;
colorTimer++;
}
@ -265,7 +250,7 @@ void loop() {
EVERY_N_SECONDS(10) {
if (autoChangePatterns) buttonPushCounter = (buttonPushCounter + 1) % 6;
}
FastLED.show();
}
@ -274,8 +259,8 @@ void loop() {
void rainbowBars(int band, int barHeight) {
int xStart = BAR_WIDTH * band;
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
for (int y = 0; y < barHeight; y++) {
leds[XY(x,y)] = CHSV((x / BAR_WIDTH) * (255 / NUM_BANDS), 255, 255);
for (int y = TOP; y >= TOP - barHeight; y--) {
matrix->drawPixel(x, y, CHSV((x / BAR_WIDTH) * (255 / NUM_BANDS), 255, 255));
}
}
}
@ -283,8 +268,8 @@ void rainbowBars(int band, int barHeight) {
void purpleBars(int band, int barHeight) {
int xStart = BAR_WIDTH * band;
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
for (int y = 0; y < barHeight; y++) {
leds[XY(x,y)] = ColorFromPalette(purplePal, y * (255 / barHeight));
for (int y = TOP; y >= TOP - barHeight; y--) {
matrix->drawPixel(x, y, ColorFromPalette(purplePal, y * (255 / (barHeight + 1))));
}
}
}
@ -292,8 +277,8 @@ void purpleBars(int band, int barHeight) {
void changingBars(int band, int barHeight) {
int xStart = BAR_WIDTH * band;
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
for (int y = 0; y < barHeight; y++) {
leds[XY(x,y)] = CHSV(y * (255 / kMatrixHeight) + colorTimer, 255, 255);
for (int y = TOP; y >= TOP - barHeight; y--) {
matrix->drawPixel(x, y, CHSV(y * (255 / kMatrixHeight) + colorTimer, 255, 255));
}
}
}
@ -305,25 +290,24 @@ void centerBars(int band, int barHeight) {
int yStart = ((kMatrixHeight - barHeight) / 2 );
for (int y = yStart; y <= (yStart + barHeight); y++) {
int colorIndex = constrain((y - yStart) * (255 / barHeight), 0, 255);
leds[XY(x,y)] = ColorFromPalette(heatPal, colorIndex);
matrix->drawPixel(x, y, ColorFromPalette(heatPal, colorIndex));
}
}
}
void whitePeak(int band) {
int xStart = BAR_WIDTH * band;
int peakHeight = peak[band];
int peakHeight = TOP - peak[band] - 1;
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
leds[XY(x,peakHeight)] = CRGB::White;
matrix->drawPixel(x, peakHeight, CHSV(0,0,255));
}
}
void outrunPeak(int band) {
int xStart = BAR_WIDTH * band;
int peakHeight = peak[band];
int peakHeight = TOP - peak[band] - 1;
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
//leds[XY(x,peakHeight)] = CHSV(peakHeight * (255 / kMatrixHeight), 255, 255);
leds[XY(x,peakHeight)] = ColorFromPalette(outrunPal, peakHeight * (255 / kMatrixHeight));
matrix->drawPixel(x, peakHeight, ColorFromPalette(outrunPal, peakHeight * (255 / kMatrixHeight)));
}
}
@ -333,14 +317,16 @@ void waterfall(int band) {
// Draw bottom line
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
leds[XY(x,0)] = CHSV(constrain(map(bandValues[band],0,highestBandValue,160,0),0,160), 255, 255);
matrix->drawPixel(x, 0, CHSV(constrain(map(bandValues[band],0,highestBandValue,160,0),0,160), 255, 255));
}
// Move screen up starting at 2nd row from top
if (band == NUM_BANDS - 1){
for (int y = kMatrixHeight - 2; y >= 0; y--) {
for (int x = 0; x < kMatrixWidth; x++) {
leds[XY(x,y+1)] = leds[XY(x,y)];
int pixelIndexY = matrix->XY(x, y + 1);
int pixelIndex = matrix->XY(x, y);
leds[pixelIndexY] = leds[pixelIndex];
}
}
}

Wyświetl plik

@ -5,7 +5,7 @@ A spectrum analyzer VU meter running a 40kHz FFT on an ESP32 and outputting to a
If you're inerested in running this using Neomatrix for easier adjustment to different matrix setups, [VonHirsch](https://github.com/VonHirsch/ESP32_FFT_VU/tree/FastLED_NeoMatrix) has a fork that you might be interested in.
## Demo
If you are planning on using this code, it is advisable to watch the YouTube video below explaining how it works.
If you are planning on using this code, it is advisable to watch the YouTube video below explaining how it works. Please note, the code has changed to use FastLED Neomatrix since the video was produced thanks to [VonHirsch](https://github.com/VonHirsch/). See 'Installation and code usage' below.
[![Youtube video of VU meter in action](http://img.youtube.com/vi/Mgh2WblO5_c/0.jpg)](https://www.youtube.com/watch?v=Mgh2WblO5_c)
@ -24,8 +24,9 @@ This is much simpler than the line in method, but you will be limited to the fre
## Installation and code usage
1. Download this repository and open ESP32_FFT_VU.ino.
2. You will need the FastLED and EasyButton libraries from the Arduino library manager. Youw will also need the arduinoFFT library. At the time of writing, the library manager version arduinoFFT has a bug which prevents `DCRemoval()` from working, so download it from the [GitHub repository](https://github.com/kosme/arduinoFFT) and install it from a zip file.
3. Watch the video to see how to use it, you will need to customise it to your matrix and your needs.
2. You will need the FastLED Neomatrix and EasyButton libraries from the Arduino library manager. Youw will also need the arduinoFFT library. At the time of writing, the library manager version arduinoFFT has a bug which prevents `DCRemoval()` from working, so download it from the [GitHub repository](https://github.com/kosme/arduinoFFT) and install it from a zip file.
3. Watch the video to see how to use it.
4. To customsise it to your own matrix layout, read about Neomatrix layouts at [Adafruit](https://learn.adafruit.com/adafruit-neopixel-uberguide/neomatrix-library#layouts-2894555-5).
## Controls
The matrix is controlled from a single button. The functions are: