驴友花雕 发表于 2022-7-24 11:23:23

【花雕动手做】看见声音,基于Arduino系列音乐可视器(12)

本帖最后由 驴友花雕 于 2022-7-25 10:07 编辑

偶然心血来潮,想要做一个声音可视化的系列专题。这个专题的难度有点高,涉及面也比较广泛,相关的FFT和FHT等算法也相当复杂,不过还是打算从最简单的开始,实际动手做做试验,耐心尝试一下各种方案,逐步积累些有用的音乐频谱可视化的资料,也会争取成型一些实用好玩的音乐可视器项目。
【花雕动手做】有趣好玩的音乐可视化项目(12)---米管快速节奏灯
捡到的报废灯管,准备利用一下,做个一米二的快速节奏灯



驴友花雕 发表于 2022-7-25 15:36:39

【花雕动手做】有趣好玩音乐可视化(12)--米管快速节奏灯
相关程序之二:SoftwareSerial米管音乐频谱灯
模块接线:WS2812B接D6
MAX9814      UNO
VCC                5V
GND             GND
OUT               A0

/*
【花雕动手做】有趣好玩音乐可视化(12)--米管快速节奏灯
相关程序之二:SoftwareSerial米管音乐频谱灯
模块接线:WS2812B接D6
MAX9814      UNO
VCC          5V
GND         GND
OUT          A0
*/

#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
#include <math.h>
#include <SoftwareSerial.h>
#define N_PIXELS70
#define N_PIXELS_HALF (N_PIXELS/2)
#define MIC_PIN   A0
#define LED_PIN    6
#define SAMPLE_WINDOW   10
#define PEAK_HANG 24
#define PEAK_FALL 20
#define PEAK_FALL2 8
#define INPUT_FLOOR 10
#define INPUT_CEILING 300
#define DC_OFFSET0
#define NOISE   10
#define SAMPLES   60
#define TOP       (N_PIXELS + 2)
#define SPEED .20      
#define TOP2      (N_PIXELS + 1)
#define LAST_PIXEL_OFFSET N_PIXELS-1
#define PEAK_FALL_MILLIS 10
#define POT_PIN    4
#define BG 0
#define LAST_PIXEL_OFFSET N_PIXELS-1
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif
#define BRIGHTNESS255
#define LED_TYPE    WS2812B   
#define COLOR_ORDER GRB
#define COLOR_MIN         0
#define COLOR_MAX         255
#define DRAW_MAX          100
#define SEGMENTS            4
#define COLOR_WAIT_CYCLES10
#define qsubd(x, b)((x>b)?b:0)
#define qsuba(x, b)((x>b)?x-b:0)                                             
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)))

struct CRGB leds;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

static uint16_t dist;         
uint16_t scale = 30;         
uint8_t maxChanges = 48;      

CRGBPalette16 currentPalette(OceanColors_p);
CRGBPalette16 targetPalette(CloudColors_p);

uint8_t timeval = 20;                                                         
uint16_t loops = 0;                                                            
bool   samplepeak = 0;                                                      
uint16_t oldsample = 0;                                                         
bool thisdir = 0;

enum
{
} MODE;
bool reverse = true;
int BRIGHTNESS_MAX = 80;
int brightness = 20;


byte
//peak      = 0,      
//dotCount= 0,      
volCount= 0;      
int
reading,
vol,      
lvl       = 10,      
minLvlAvg = 0,      
maxLvlAvg = 512;
float
greenOffset = 30,
blueOffset = 150;

int CYCLE_MIN_MILLIS = 2;
int CYCLE_MAX_MILLIS = 1000;
int cycleMillis = 20;
bool paused = false;
long lastTime = 0;
bool boring = true;
bool gReverseDirection = false;
int          myhue =   0;

uint8_t colour;
uint8_t myfade = 255;                                       
#define maxsteps 16                                          
int peakspersec = 0;
int peakcount = 0;
uint8_t bgcol = 0;
int thisdelay = 20;
uint8_t max_bright = 255;

unsigned int sample;

#define NSAMPLES 64
unsigned int samplearray;
unsigned long samplesum = 0;
unsigned int sampleavg = 0;
int samplecount = 0;
//unsigned int sample = 0;
unsigned long oldtime = 0;
unsigned long newtime = 0;

int color;
int center = 0;
int step = -1;
int maxSteps = 16;
float fadeRate = 0.80;
int diff;

int
origin = 0,
color_wait_count = 0,
scroll_color = COLOR_MIN,
last_intensity = 0,
intensity_max = 0,
origin_at_flip = 0;
uint32_t
draw;
boolean
growing = false,
fall_from_left = true;

uint32_t currentBg = random(256);
uint32_t nextBg = currentBg;
TBlendType    currentBlending;

const int buttonPin = 0;   

int buttonPushCounter = 0;   
int buttonState = 0;         
int lastButtonState = 0;


byte peak = 16;      

byte dotCount = 0;
byte dotHangCount = 0;

void setup() {

analogReference(EXTERNAL);

pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);

// Serial.begin(9600);
strip.begin();
strip.show(); // all pixels to 'off'

Serial.begin(57600);
delay(3000);

LEDS.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, N_PIXELS).setCorrection(TypicalLEDStrip);
LEDS.setBrightness(BRIGHTNESS);
dist = random16(12345);         
}

float fscale( float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve) {

float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
boolean invFlag = 0;

if (curve > 10) curve = 10;
if (curve < -10) curve = -10;

curve = (curve * -.1) ;
curve = pow(10, curve);

if (inputValue < originalMin) {
    inputValue = originalMin;
}
if (inputValue > originalMax) {
    inputValue = originalMax;
}

OriginalRange = originalMax - originalMin;

if (newEnd > newBegin) {
    NewRange = newEnd - newBegin;
}
else
{
    NewRange = newBegin - newEnd;
    invFlag = 1;
}

zeroRefCurVal = inputValue - originalMin;
normalizedCurVal=zeroRefCurVal / OriginalRange;

if (originalMin > originalMax ) {
    return 0;
}

if (invFlag == 0) {
    rangedValue =(pow(normalizedCurVal, curve) * NewRange) + newBegin;

}
else   
{
    rangedValue =newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}

void loop() {
uint8_ti;
uint16_t minLvl, maxLvl;
int      n, height;
buttonState = digitalRead(buttonPin);
if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:");
      Serial.println(buttonPushCounter);
      if (buttonPushCounter == 16) {
      buttonPushCounter = 1;
      }
    }
    else {
      Serial.println("off");
    }
}
lastButtonState = buttonState;

switch (buttonPushCounter) {

    case 1:
      buttonPushCounter == 1; {
      All2();
      break;
      }

    case 2:
      buttonPushCounter == 2; {
      vu();
      break;
      }

    case 3:
      buttonPushCounter == 3; {
      vu1();
      break;
      }

    case 4:
      buttonPushCounter == 4; {
      vu2();
      break;
      }

    case 5:
      buttonPushCounter == 5; {
      Vu3();
      break;
      }

    case 6:
      buttonPushCounter == 6; {
      Vu4();
      break;
      }

    case 7:
      buttonPushCounter == 7; {
      Vu5();
      break;
      }

    case 8:
      buttonPushCounter == 8; {
      Vu6();
      break;
      }

    case 9:
      buttonPushCounter == 9; {
      vu7();
      break;
      }

    case 10:
      buttonPushCounter == 10; {
      vu8();
      break;
      }

    case 11:
      buttonPushCounter == 11; {
      vu9();
      break;
      }

    case 12:
      buttonPushCounter == 12; {
      vu10();
      break;
      }
    case 13:
      buttonPushCounter == 13; {
      vu11();
      break;
      }

    case 14:
      buttonPushCounter == 14; {
      vu12();
      break;
      }

    case 15:
      buttonPushCounter == 15; {
      vu13();
      break;
      }


    case 16:
      buttonPushCounter == 16; {
      colorWipe(strip.Color(0, 0, 0), 10);
      break;
      }
}
}

void colorWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    if (digitalRead(buttonPin) != lastButtonState)
      return;         
    delay(wait);
}
}

void vu() {
uint8_ti;
uint16_t minLvl, maxLvl;
int      n, height;
n   = analogRead(MIC_PIN);                        
n   = abs(n - 512 - DC_OFFSET);
n   = (n <= NOISE) ? 0 : (n - NOISE);            
lvl = ((lvl * 7) + n) >> 3;   

height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

if (height < 0L)       height = 0;   
else if (height > TOP) height = TOP;
if (height > peak)   peak   = height;

for (i = 0; i < N_PIXELS; i++) {
    if (i >= height)               strip.setPixelColor(i,   0,   0, 0);
    else strip.setPixelColor(i, Wheel(map(i, 0, strip.numPixels() - 1, 30, 150)));
}

if (peak > 0 && peak <= N_PIXELS - 1) strip.setPixelColor(peak, Wheel(map(peak, 0, strip.numPixels() - 1, 30, 150)));

strip.show();

if (++dotCount >= PEAK_FALL) {

    if (peak > 0) peak--;
    dotCount = 0;
}

vol = n;                     
if (++volCount >= SAMPLES) volCount = 0;

minLvl = maxLvl = vol;
for (i = 1; i < SAMPLES; i++) {
    if (vol < minLvl)      minLvl = vol;
    else if (vol > maxLvl) maxLvl = vol;
}

if ((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}

uint32_t Wheel(byte WheelPos) {
if (WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}

void vu1() {
uint8_ti;
uint16_t minLvl, maxLvl;
int      n, height;

n   = analogRead(MIC_PIN);                        
n   = abs(n - 512 - DC_OFFSET);
n   = (n <= NOISE) ? 0 : (n - NOISE);            
lvl = ((lvl * 7) + n) >> 3;   

height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

if (height < 0L)       height = 0;   
else if (height > TOP) height = TOP;
if (height > peak)   peak   = height;

for (i = 0; i < N_PIXELS_HALF; i++) {
    if (i >= height) {
      strip.setPixelColor(N_PIXELS_HALF - i - 1,   0,   0, 0);
      strip.setPixelColor(N_PIXELS_HALF + i,   0,   0, 0);
    }
    else {
      uint32_t color = Wheel(map(i, 0, N_PIXELS_HALF - 1, 30, 150));
      strip.setPixelColor(N_PIXELS_HALF - i - 1, color);
      strip.setPixelColor(N_PIXELS_HALF + i, color);
    }
}

if (peak > 0 && peak <= N_PIXELS_HALF - 1) {
    uint32_t color = Wheel(map(peak, 0, N_PIXELS_HALF - 1, 30, 150));
    strip.setPixelColor(N_PIXELS_HALF - peak - 1, color);
    strip.setPixelColor(N_PIXELS_HALF + peak, color);
}

strip.show();

if (++dotCount >= PEAK_FALL) { //fall rate

    if (peak > 0) peak--;
    dotCount = 0;
}

vol = n;                     
if (++volCount >= SAMPLES) volCount = 0;

minLvl = maxLvl = vol;
for (i = 1; i < SAMPLES; i++) {
    if (vol < minLvl)      minLvl = vol;
    else if (vol > maxLvl) maxLvl = vol;
}

if ((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}

void vu2()
{
unsigned long startMillis = millis();
float peakToPeak = 0;   

unsigned int signalMax = 0;
unsigned int signalMin = 1023;
unsigned int c, y;

while (millis() - startMillis < SAMPLE_WINDOW)
{
    sample = analogRead(MIC_PIN);
    if (sample < 1024)
    {
      if (sample > signalMax)
      {
      signalMax = sample;
      }
      else if (sample < signalMin)
      {
      signalMin = sample;
      }
    }
}
peakToPeak = signalMax - signalMin;

for (int i = 0; i <= N_PIXELS_HALF - 1; i++) {
    uint32_t color = Wheel(map(i, 0, N_PIXELS_HALF - 1, 30, 150));
    strip.setPixelColor(N_PIXELS - i, color);
    strip.setPixelColor(0 + i, color);
}

c = fscale(INPUT_FLOOR, INPUT_CEILING, N_PIXELS_HALF, 0, peakToPeak, 2);

if (c < peak) {
    peak = c;      
    dotHangCount = 0;   
}
if (c <= strip.numPixels()) {
    drawLine(N_PIXELS_HALF, N_PIXELS_HALF - c, strip.Color(0, 0, 0));
    drawLine(N_PIXELS_HALF, N_PIXELS_HALF + c, strip.Color(0, 0, 0));
}

y = N_PIXELS_HALF - peak;
uint32_t color1 = Wheel(map(y, 0, N_PIXELS_HALF - 1, 30, 150));
strip.setPixelColor(y - 1, color1);

y = N_PIXELS_HALF + peak;
strip.setPixelColor(y, color1);

strip.show();

if (dotHangCount > PEAK_HANG) {
    if (++dotCount >= PEAK_FALL2) {
      peak++;
      dotCount = 0;
    }
}
else {
    dotHangCount++;
}
}


void Vu3() {
uint8_t i;
uint16_t minLvl, maxLvl;
int n, height;

n = analogRead(MIC_PIN);            
n = abs(n - 512 - DC_OFFSET);      
n = (n <= NOISE) ? 0 : (n - NOISE);
lvl = ((lvl * 7) + n) >> 3;   

height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

if (height < 0L)       height = 0;      
else if (height > TOP) height = TOP;
if (height > peak)   peak   = height;

greenOffset += SPEED;
blueOffset += SPEED;
if (greenOffset >= 255) greenOffset = 0;
if (blueOffset >= 255) blueOffset = 0;

for (i = 0; i < N_PIXELS; i++) {
    if (i >= height) {
      strip.setPixelColor(i, 0, 0, 0);
    } else {
      strip.setPixelColor(i, Wheel(
                            map(i, 0, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)
                        ));
    }
}
if (peak > 0 && peak <= N_PIXELS - 1) strip.setPixelColor(peak, Wheel(map(peak, 0, strip.numPixels() - 1, 30, 150)));

strip.show();

if (++dotCount >= PEAK_FALL) {

    if (peak > 0) peak--;
    dotCount = 0;
}
strip.show();

vol = n;
if (++volCount >= SAMPLES) {
    volCount = 0;
}

minLvl = maxLvl = vol;
for (i = 1; i < SAMPLES; i++) {
    if (vol < minLvl) {
      minLvl = vol;
    } else if (vol > maxLvl) {
      maxLvl = vol;
    }
}

if ((maxLvl - minLvl) < TOP) {
    maxLvl = minLvl + TOP;
}
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}


void Vu4() {
uint8_ti;
uint16_t minLvl, maxLvl;
int      n, height;

n   = analogRead(MIC_PIN);                        
n   = abs(n - 512 - DC_OFFSET);
n   = (n <= NOISE) ? 0 : (n - NOISE);            
lvl = ((lvl * 7) + n) >> 3;   

height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

if (height < 0L)       height = 0;   
else if (height > TOP) height = TOP;
if (height > peak)   peak   = height;
greenOffset += SPEED;
blueOffset += SPEED;
if (greenOffset >= 255) greenOffset = 0;
if (blueOffset >= 255) blueOffset = 0;

for (i = 0; i < N_PIXELS_HALF; i++) {
    if (i >= height) {
      strip.setPixelColor(N_PIXELS_HALF - i - 1,   0,   0, 0);
      strip.setPixelColor(N_PIXELS_HALF + i,   0,   0, 0);
    }
    else {
      uint32_t color = Wheel(map(i, 0, N_PIXELS_HALF - 1, (int)greenOffset, (int)blueOffset));
      strip.setPixelColor(N_PIXELS_HALF - i - 1, color);
      strip.setPixelColor(N_PIXELS_HALF + i, color);
    }

}

// Draw peak dot
if (peak > 0 && peak <= N_PIXELS_HALF - 1) {
    uint32_t color = Wheel(map(peak, 0, N_PIXELS_HALF - 1, 30, 150));
    strip.setPixelColor(N_PIXELS_HALF - peak - 1, color);
    strip.setPixelColor(N_PIXELS_HALF + peak, color);
}

strip.show(); // Update strip

// Every few frames, make the peak pixel drop by 1:

if (++dotCount >= PEAK_FALL) { //fall rate

    if (peak > 0) peak--;
    dotCount = 0;
}


vol = n;                     
if (++volCount >= SAMPLES) volCount = 0;


minLvl = maxLvl = vol;
for (i = 1; i < SAMPLES; i++) {
    if (vol < minLvl)      minLvl = vol;
    else if (vol > maxLvl) maxLvl = vol;
}

if ((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}

void Vu5()
{
uint8_ti;
uint16_t minLvl, maxLvl;
int      n, height;

n   = analogRead(MIC_PIN);                        
n   = abs(n - 512 - DC_OFFSET);
n   = (n <= NOISE) ? 0 : (n - NOISE);            
lvl = ((lvl * 7) + n) >> 3;   

height = TOP2 * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

if (height < 0L)       height = 0;   
else if (height > TOP2) height = TOP2;
if (height > peak)   peak   = height;


#ifdef CENTERED
for (i = 0; i < (N_PIXELS / 2); i++) {
    if (((N_PIXELS / 2) + i) >= height)
    {
      strip.setPixelColor(((N_PIXELS / 2) + i),   0,   0, 0);
      strip.setPixelColor(((N_PIXELS / 2) - i),   0,   0, 0);
    }
    else
    {
      strip.setPixelColor(((N_PIXELS / 2) + i), Wheel(map(((N_PIXELS / 2) + i), 0, strip.numPixels() - 1, 30, 150)));
      strip.setPixelColor(((N_PIXELS / 2) - i), Wheel(map(((N_PIXELS / 2) - i), 0, strip.numPixels() - 1, 30, 150)));
    }
}

if (peak > 0 && peak <= LAST_PIXEL_OFFSET)
{
    strip.setPixelColor(((N_PIXELS / 2) + peak), 255, 255, 255);
    strip.setPixelColor(((N_PIXELS / 2) - peak), 255, 255, 255);
}
#else
for (i = 0; i < N_PIXELS; i++)
{
    if (i >= height)
    {
      strip.setPixelColor(i,   0,   0, 0);
    }
    else
    {
      strip.setPixelColor(i, Wheel(map(i, 0, strip.numPixels() - 1, 30, 150)));
    }
}

if (peak > 0 && peak <= LAST_PIXEL_OFFSET)
{
    strip.setPixelColor(peak, 255, 255, 255);
}

#endif

if (millis() - lastTime >= PEAK_FALL_MILLIS)
{
    lastTime = millis();

    strip.show();

    if (peak > 0) peak--;
}

vol = n;                     
if (++volCount >= SAMPLES) volCount = 0;


minLvl = maxLvl = vol;
for (i = 1; i < SAMPLES; i++)
{
    if (vol < minLvl)      minLvl = vol;
    else if (vol > maxLvl) maxLvl = vol;
}

if ((maxLvl - minLvl) < TOP2) maxLvl = minLvl + TOP2;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}

void Vu6()
{
uint8_ti;
uint16_t minLvl, maxLvl;
int      n, height;

n   = analogRead(MIC_PIN);                     
n   = abs(n - 512 - DC_OFFSET);
n   = (n <= NOISE) ? 0 : (n - NOISE);            
lvl = ((lvl * 7) + n) >> 3;   

height = TOP2 * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

if (height < 0L)       height = 0;   
else if (height > TOP2) height = TOP2;
if (height > peak)   peak   = height;


#ifdef CENTERED
if (peak > 0 && peak <= LAST_PIXEL_OFFSET)
{
    strip.setPixelColor(((N_PIXELS / 2) + peak), 255, 255, 255);
    strip.setPixelColor(((N_PIXELS / 2) - peak), 255, 255, 255);
}
#else
// Color pixels based on rainbow gradient
for (i = 0; i < N_PIXELS; i++)
{
    if (i >= height)
    {
      strip.setPixelColor(i,   0,   0, 0);
    }
    else
    {
    }
}

// Draw peak dot
if (peak > 0 && peak <= LAST_PIXEL_OFFSET)
{
    strip.setPixelColor(peak, 0, 0, 255);
}

#endif

// Every few frames, make the peak pixel drop by 1:

if (millis() - lastTime >= PEAK_FALL_MILLIS)
{
    lastTime = millis();

    strip.show(); // Update strip

    //fall rate
    if (peak > 0) peak--;
}

vol = n;                     
if (++volCount >= SAMPLES) volCount = 0;

minLvl = maxLvl = vol;
for (i = 1; i < SAMPLES; i++)
{
    if (vol < minLvl)      minLvl = vol;
    else if (vol > maxLvl) maxLvl = vol;
}

if ((maxLvl - minLvl) < TOP2) maxLvl = minLvl + TOP2;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}

void vu7() {

EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                       
    peakcount = 0;                                                
}

soundmems();

EVERY_N_MILLISECONDS(20) {
    ripple3();
}
show_at_max_brightness_for_power();
}

void soundmems() {                                                
newtime = millis();
int tmp = analogRead(MIC_PIN) - 512;
sample = abs(tmp);

int potin = map(analogRead(POT_PIN), 0, 1023, 0, 60);

samplesum = samplesum + sample - samplearray;      
sampleavg = samplesum / NSAMPLES;                                 
samplearray = sample;                              
samplecount = (samplecount + 1) % NSAMPLES;                     

if (newtime > (oldtime + 200)) digitalWrite(13, LOW);         

if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) {
    step = -1;
    peakcount++;
    digitalWrite(13, HIGH);
    oldtime = newtime;
}
}

void ripple3() {
for (int i = 0; i < N_PIXELS; i++) leds = CHSV(bgcol, 255, sampleavg * 2);

switch (step) {

    case -1:                                                      
      center = random(N_PIXELS);
      colour = (peakspersec * 10) % 255;                                          
      step = 0;
      bgcol = bgcol + 8;
      break;

    case 0:
      leds = CHSV(colour, 255, 255);                        
      step ++;
      break;

    case maxsteps:                                                   
      break;

    default:                                                            
      leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade / step * 2);
      leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade / step * 2);
      step ++;                                                         
      break;
}
}

void vu8() {
int intensity = calculateIntensity();
updateOrigin(intensity);
assignDrawValues(intensity);
writeSegmented();
updateGlobals();
}

int calculateIntensity() {
int      intensity;

reading   = analogRead(MIC_PIN);                     
reading   = abs(reading - 512 - DC_OFFSET);
reading   = (reading <= NOISE) ? 0 : (reading - NOISE);         
lvl = ((lvl * 7) + reading) >> 3;   

intensity = DRAW_MAX * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

return constrain(intensity, 0, DRAW_MAX - 1);
}

void updateOrigin(int intensity) {
if (growing && intensity < last_intensity) {
    growing = false;
    intensity_max = last_intensity;
    fall_from_left = !fall_from_left;
    origin_at_flip = origin;
} else if (intensity > last_intensity) {
    growing = true;
    origin_at_flip = origin;
}
last_intensity = intensity;

if (!growing) {
    if (fall_from_left) {
      origin = origin_at_flip + ((intensity_max - intensity) / 2);
    } else {
      origin = origin_at_flip - ((intensity_max - intensity) / 2);
    }
    if (origin < 0) {
      origin = DRAW_MAX - abs(origin);
    } else if (origin > DRAW_MAX - 1) {
      origin = origin - DRAW_MAX - 1;
    }
}
}

void assignDrawValues(int intensity) {
int min_lit = origin - (intensity / 2);
int max_lit = origin + (intensity / 2);
if (min_lit < 0) {
    min_lit = min_lit + DRAW_MAX;
}
if (max_lit >= DRAW_MAX) {
    max_lit = max_lit - DRAW_MAX;
}
for (int i = 0; i < DRAW_MAX; i++) {

    if (
      (min_lit < max_lit && min_lit < i && i < max_lit)
      || (min_lit > max_lit && (i > min_lit || i < max_lit))
    ) {
      draw = Wheel(scroll_color);
    } else {
      draw = 0;
    }
}
}

void writeSegmented() {
int seg_len = N_PIXELS / SEGMENTS;

for (int s = 0; s < SEGMENTS; s++) {
    for (int i = 0; i < seg_len; i++) {
      strip.setPixelColor(i + (s * seg_len), draw);
    }
}
strip.show();
}

uint32_t * segmentAndResize(uint32_t* draw) {
int seg_len = N_PIXELS / SEGMENTS;

uint32_t segmented;
for (int s = 0; s < SEGMENTS; s++) {
    for (int i = 0; i < seg_len; i++) {
      segmented = draw;
    }
}
return segmented;
}

void writeToStrip(uint32_t* draw) {
for (int i = 0; i < N_PIXELS; i++) {
    strip.setPixelColor(i, draw);
}
strip.show();
}

void updateGlobals() {
uint16_t minLvl, maxLvl;

color_wait_count++;
if (color_wait_count > COLOR_WAIT_CYCLES) {
    color_wait_count = 0;
    scroll_color++;
    if (scroll_color > COLOR_MAX) {
      scroll_color = COLOR_MIN;
    }
}

vol = reading;                     
if (++volCount >= SAMPLES) volCount = 0;

minLvl = maxLvl = vol;
for (uint8_t i = 1; i < SAMPLES; i++) {
    if (vol < minLvl)      minLvl = vol;
    else if (vol > maxLvl) maxLvl = vol;
}

if ((maxLvl - minLvl) < N_PIXELS) maxLvl = minLvl + N_PIXELS;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6;
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6;
}

void vu9() {
currentPalette = OceanColors_p;                           
currentBlending = LINEARBLEND;
EVERY_N_SECONDS(5) {                                       
    for (int i = 0; i < 16; i++) {
      targetPalette = CHSV(random8(), 255, 255);
    }
}

EVERY_N_MILLISECONDS(100) {                                 
    uint8_t maxChanges = 24;
    nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);
}

EVERY_N_MILLIS_I(thistimer, 20) {                           
    uint8_t timeval = beatsin8(10, 20, 50);                  
    thistimer.setPeriod(timeval);                           
    fadeToBlackBy(leds, N_PIXELS, 16);                     
    sndwave();
    soundble();
}
FastLED.setBrightness(max_bright);
FastLED.show();
}

void soundble() {                                          
int tmp = analogRead(MIC_PIN) - 512 - DC_OFFSET;
sample = abs(tmp);
}

void sndwave() {
leds = ColorFromPalette(currentPalette, sample, sample * 2, currentBlending);
for (int i = N_PIXELS - 1; i > N_PIXELS / 2; i--) {   
    leds = leds;
}

for (int i = 0; i < N_PIXELS / 2; i++) {               
    leds = leds;
}
addGlitter(sampleavg);
}

void vu10() {
EVERY_N_SECONDS(5) {                                       
    static uint8_t baseC = random8();                        

    for (int i = 0; i < 16; i++) {
      targetPalette = CHSV(random8(), 255, 255);
    }
}

EVERY_N_MILLISECONDS(100) {
    uint8_t maxChanges = 24;
    nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);   
}

EVERY_N_MILLISECONDS(thisdelay) {                           
    soundtun();
    FastLED.setBrightness(max_bright);
    FastLED.show();
}
}

void soundtun() {
int n;
n = analogRead(MIC_PIN);                                    
n = qsuba(abs(n - 512), 10);                              
CRGB newcolour = ColorFromPalette(currentPalette, constrain(n, 0, 255), constrain(n, 0, 255), currentBlending);
nblend(leds, newcolour, 128);

for (int i = N_PIXELS - 1; i > 0; i--) {
    leds = leds;
}

}

void vu11() {
EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                 
    peakcount = 0;                                          
}

soundrip();

EVERY_N_MILLISECONDS(20) {
    rippled();
}
FastLED.show();
}

void soundrip() {                                          
newtime = millis();
int tmp = analogRead(MIC_PIN) - 512;
sample = abs(tmp);

int potin = map(analogRead(POT_PIN), 0, 1023, 0, 60);

samplesum = samplesum + sample - samplearray;
sampleavg = samplesum / NSAMPLES;                        

Serial.println(sampleavg);

samplearray = sample;                        
samplecount = (samplecount + 1) % NSAMPLES;               

if (newtime > (oldtime + 200)) digitalWrite(13, LOW);      

if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) {
    step = -1;
    peakcount++;
    oldtime = newtime;
}
}

void rippled() {

fadeToBlackBy(leds, N_PIXELS, 64);                        

switch (step) {

    case -1:                                                
      center = random(N_PIXELS);
      colour = (peakspersec * 10) % 255;                     
      step = 0;
      break;

    case 0:
      leds = CHSV(colour, 255, 255);                  
      step ++;
      break;

    case maxsteps:                                          
      break;

    default:                                                
      leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade / step * 2);   
      leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade / step * 2);
      step ++;                                                
      break;
}

}

void drawLine(uint8_t from, uint8_t to, uint32_t c) {
uint8_t fromTemp;
if (from > to) {
    fromTemp = from;
    from = to;
    to = fromTemp;
}
for (int i = from; i <= to; i++) {
    strip.setPixelColor(i, c);
}
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
}

void setAll(byte red, byte green, byte blue) {

for (int i = 0; i < N_PIXELS; i++ ) {

    setPixel(i, red, green, blue);
}
strip.show();
}
void vu12() {

EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                 
    peakcount = 0;                                          
}

soundripped();

EVERY_N_MILLISECONDS(20) {
    rippvu();
}
FastLED.show();
}

void soundripped() {                                          
newtime = millis();
int tmp = analogRead(MIC_PIN) - 512;
sample = abs(tmp);

int potin = map(analogRead(POT_PIN), 0, 1023, 0, 60);

samplesum = samplesum + sample - samplearray;
sampleavg = samplesum / NSAMPLES;                           

Serial.println(sampleavg);

samplearray = sample;                        
samplecount = (samplecount + 1) % NSAMPLES;               

if (newtime > (oldtime + 200)) digitalWrite(13, LOW);      

if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) {
    step = -1;
    peakcount++;
    oldtime = newtime;
}

}
void rippvu() {                                                               

fadeToBlackBy(leds, N_PIXELS, 64);                        

switch (step) {

    case -1:                                                
      center = random(N_PIXELS);
      colour = (peakspersec * 10) % 255;                     
      step = 0;
      break;

    case 0:
      leds = CHSV(colour, 255, 255);                  
      step ++;
      break;

    case maxsteps:                                          
      break;

    default:                                                
      leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade / step * 2);   
      leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade / step * 2);
      step ++;                                                
      break;
}
addGlitter(sampleavg);
}

void vu13() {                                                                  
EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                 
    peakcount = 0;                                          
}

soundripper();

EVERY_N_MILLISECONDS(20) {
    jugglep();
}
FastLED.show();
}

void soundripper() {                                          

newtime = millis();
int tmp = analogRead(MIC_PIN) - 512;
sample = abs(tmp);

int potin = map(analogRead(POT_PIN), 0, 1023, 0, 60);

samplesum = samplesum + sample - samplearray;
sampleavg = samplesum / NSAMPLES;                           

Serial.println(sampleavg);

samplearray = sample;                        
samplecount = (samplecount + 1) % NSAMPLES;               

if (newtime > (oldtime + 200)) digitalWrite(13, LOW);      

if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) {
    step = -1;
    peakcount++;
    oldtime = newtime;
    jugglep();
}
}

void jugglep() {                                                               

static uint8_t thishue = 0;
timeval = 40;                                                               
leds = ColorFromPalette(currentPalette, thishue++, sampleavg, LINEARBLEND);
for (int i = N_PIXELS - 1; i > 0 ; i-- ) leds = leds;
addGlitter(sampleavg / 2);                                                   
}

uint32_t Wheel(byte WheelPos, float opacity) {

if (WheelPos < 85) {
    return strip.Color((WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity, 0);
}
else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color((255 - WheelPos * 3) * opacity, 0, (WheelPos * 3) * opacity);
}
else {
    WheelPos -= 170;
    return strip.Color(0, (WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity);
}
}

void addGlitter( fract8 chanceOfGlitter) {                                    

if ( random8() < chanceOfGlitter) {
    leds += CRGB::White;
}
}

typedef void (*SimplePatternList[])();
SimplePatternList qPatterns = {vu, vu1, vu2, Vu3, Vu4, Vu5, Vu6, vu7, vu8, vu9, vu10, vu11, vu12, vu13};
uint8_t qCurrentPatternNumber = 0;

void nextPattern2()
{
qCurrentPatternNumber = (qCurrentPatternNumber + 1) % ARRAY_SIZE( qPatterns);
}

void All2()
{
qPatterns();
EVERY_N_SECONDS( 30 ) {
    nextPattern2();
}
}

驴友花雕 发表于 2022-10-5 09:59:42

【花雕动手做】看见声音,基于Arduino系列音乐可视器(1)---LED节奏灯
https://mc.dfrobot.com.cn/thread-311167-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(2)---OLED频谱灯
https://mc.dfrobot.com.cn/thread-311174-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(3)---RGB律动灯
https://mc.dfrobot.com.cn/thread-311183-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(4)---WS2812条灯
https://mc.dfrobot.com.cn/thread-311190-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(5)---WS2812柱跳灯
https://mc.dfrobot.com.cn/thread-311192-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(6)---点阵频谱灯
https://mc.dfrobot.com.cn/thread-311201-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(7)---大方格频谱灯
https://mc.dfrobot.com.cn/thread-311364-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(8)---四位32段点阵屏
https://mc.dfrobot.com.cn/thread-311490-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(9)---X Music Spectrum
https://mc.dfrobot.com.cn/thread-311627-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(10)---WS2812硬板屏
https://mc.dfrobot.com.cn/thread-311641-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(11)---WS2812幻彩灯带
https://mc.dfrobot.com.cn/thread-313648-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(12)---米管快速节奏灯
https://mc.dfrobot.com.cn/thread-313708-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(13)---有机棒立柱灯
https://mc.dfrobot.com.cn/thread-313723-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(14)---水杯水瓶灯
https://mc.dfrobot.com.cn/thread-313803-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(15)--横排LED方管灯
https://mc.dfrobot.com.cn/thread-313811-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(16)--热干胶棒棒灯
https://mc.dfrobot.com.cn/thread-313844-1-1.html
【花雕动手做】有趣好玩音乐可视化系列(17)--光导纤维灯
https://mc.dfrobot.com.cn/thread-313867-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(18)--LED平面板灯
https://mc.dfrobot.com.cn/thread-313951-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(19)--通体光纤灯
https://mc.dfrobot.com.cn/thread-313962-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(20)--首饰盒镜子灯
https://mc.dfrobot.com.cn/thread-313969-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(21)--CD 光盘灯
https://mc.dfrobot.com.cn/thread-313984-1-1.html
【花雕动手做】看见声音,基于Arduino系列音乐可视器(22)--LED无限魔方
https://mc.dfrobot.com.cn/thread-313994-1-1.html
【花雕动手做】有趣好玩的音乐可视化(23)--3合1闪点光纤
https://mc.dfrobot.com.cn/thread-314168-1-1.html
【花雕动手做】有趣好玩的音乐可视化(24)--无限LED镜子灯
https://mc.dfrobot.com.cn/thread-314180-1-1.html
【花雕动手做】有趣好玩音乐可视化(25)--水龙卷旋涡灯
https://mc.dfrobot.com.cn/thread-314231-1-1.html
【花雕动手做】有趣好玩音乐可视化系列(26)--LED 超立方体
https://mc.dfrobot.com.cn/thread-314244-1-1.html
【花雕动手做】有趣好玩的音乐可视化(27)--磁搅LED水旋灯
https://mc.dfrobot.com.cn/thread-314273-1-1.html


驴友花雕 发表于 2022-7-24 15:39:08

【花雕动手做】有趣好玩音乐可视化(12)--米管快速节奏灯
相关程序:MegunoLink音乐反应式LED灯带
模块接线:WS2812B接D9
MAX9814   ESP32_C3
VCC          5V
GND         GND
OUT       D4(ADC4)

/*
【花雕动手做】有趣好玩音乐可视化(12)--米管快速节奏灯
相关程序:MegunoLink音乐反应式LED灯带
模块接线:WS2812B接D9
MAX9814   ESP32_C3
VCC          5V
GND         GND
OUT       D4(ADC4)
*/

#include<FastLED.h>
#include<MegunoLink.h>
#include<Filter.h>

#define N_PIXELS70
#define MIC_PIN   4
#define LED_PIN   9

#define NOISE 150
#define TOP   (N_PIXELS+2)
#define LED_TYPEWS2811
#define BRIGHTNESS18   
#define COLOR_ORDER GRB

CRGB leds;

int lvl = 0, minLvl = 0, maxLvl = 100;

ExponentialFilter<long> ADCFilter(5,0);

void setup() {
Serial.begin(115200);
FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
}

void loop() {
int n, height;
n = analogRead(MIC_PIN);
n = abs(1023 - n);
n = (n <= NOISE) ? 0 : abs(n - NOISE);
ADCFilter.Filter(n);
lvl = ADCFilter.Current();

height = TOP * (lvl - minLvl) / (long)(maxLvl - minLvl);
if(height < 0L) height = 0;
else if(height > TOP) height = TOP;

for(uint8_t i = 0; i < N_PIXELS; i++) {

    if(i >= height) leds = CRGB(0,0,0);
    // otherwise, turn them on!
    else leds = Wheel( map( i, 0, N_PIXELS-1, 30, 150 ) );
}
FastLED.show();
}

CRGB Wheel(byte WheelPos) {
if(WheelPos < 85)
    return CRGB(WheelPos * 3, 255 - WheelPos * 3, 0);
else if(WheelPos < 170) {
    WheelPos -= 85;
    return CRGB(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
    WheelPos -= 170;
    return CRGB(0, WheelPos * 3, 255 - WheelPos * 3);
}
}

驴友花雕 发表于 2022-7-24 11:37:21

两个头都锯掉,抽出里面的LED灯片



驴友花雕 发表于 2022-7-24 11:40:46

花盆底盘找了二个,当灯管座



驴友花雕 发表于 2022-7-24 11:44:07

使用多级扩孔钻头



驴友花雕 发表于 2022-7-24 11:49:21

灯管地座三秒扩孔28mm





驴友花雕 发表于 2022-7-24 11:55:19

开发板使用合宙CORE ESP32-C3




主要特色
(1)功能强,应用广
合宙ESP32-C3开发板高集成化设计,板载 Wi-Fi/BLE天线、4MB Flash,支持UART、GPIO、SPI、I2C、ADC、PWM等接口,满足大多数应用;板载CH343P芯片实现更高速率的USB转串口,固件下载更快更稳。
(2)用料足,信号好
合宙ESP32-C3开发板采用4层PCB,板载2.4G天线,经过调试达到了比较好的使用效果。实测2.38到2.48GHz范围内的驻波比(VSWR)值比较好,能够有效的将发射功率辐射到无线空间。
(3)多样化开发更便捷
合宙ESP32-C3开发板目前支持:LuatOS/乐鑫IDF/Arduino/MicroPython等多样化开发方式,使用更便捷。LuatOS固件在社区大神梦程的努力下现已支持以下功能,其他内容正在不断更新。


驴友花雕 发表于 2022-7-24 11:59:04

ESP32-C3核心板 IO引脚图

1路SPI FLASH,板载4MB,支持最高 16MB
2路UART接口,UART0~UART1,其中下载口为UART0
6 路 12 比特 ADC,最高采样率 100KSPS
1路低速SPI接口,支持主模式
1路IIC控制器
4路PWM接口
GPIO外部管脚15路,可复用
2路贴片LED指示灯
1路复位按键+1路BOOT按键
1路USB转TTL下载调试口
2.4G PCB板载天线



驴友花雕 发表于 2022-7-24 12:03:48

声音模块使用MAX9814




MAX9814是一款低成本高性能麦克风放大器,具有自动增益控制(AGC)和低噪声麦克风偏置。器件具有低噪声前端放大器、可变增益放大(VGA)、输出放大器、麦克风偏置电压发生器和AGC控制电路。
●自动增益控制(AGC)
●3种增益设置(40dB、50dB、60dB)
●可编程动作时间
●可编程动作和释放时间比
●电源电压范围2.7V~5.5V
●低THD:0.04% (典型值)
●低功耗关断模式
●内置2V低噪声麦克风偏置


驴友花雕 发表于 2022-7-24 12:08:19

彩灯使用WS2812B

其主要特点
智能反接保护,电源反接不会损坏IC。
IC控制电路与LED点光源公用一个电源。
控制电路与RGB芯片集成在一个5050封装的元器件中,构成一个完整的外控像素点。
内置信号整形电路,任何一个像素点收到信号后经过波形整形再输出,保证线路波形畸变不会累加。
内置上电复位和掉电复位电路。
每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示,扫描频率不低于400Hz/s。
串行级联接口,能通过一根信号线完成数据的接收与解码。
任意两点传传输距离在不超过5米时无需增加任何电路。
当刷新速率30帧/秒时,级联数不小于1024点。
数据发送速度可达800Kbps。
光的颜色高度一致,性价比高。

主要应用领域
LED全彩发光字灯串,LED全彩模组, LED全彩软灯条硬灯条,LED护栏管。
LED点光源,LED像素屏,LED异形屏,各种电子产品,电器设备跑马灯。



驴友花雕 发表于 2022-7-24 12:20:39

WS2812B灯带选用的是每米60灯黑底裸板



驴友花雕 发表于 2022-7-24 12:24:41

WS2812模块电原理图



驴友花雕 发表于 2022-7-24 12:32:41

WS2812B是集控制电路和发光电路于一体的LED光源元件,其控制IC为WS2812B,发光元件是5050RGBLED,电压为5V,每个单位的峰值电流为60ma,灯带为三线制,VCC GND DIN分别为电源+、电源-、信号,当使用外部电源时,外部电源-需要与单片机的GND相连。



驴友花雕 发表于 2022-7-24 12:34:03




驴友花雕 发表于 2022-7-24 12:42:52

把灯带放入灯管之中(这里我剪了70颗灯珠)



驴友花雕 发表于 2022-7-24 12:47:56

灯管底座配重,后来采取了大理石方案,零费用高性价比



驴友花雕 发表于 2022-7-24 13:25:52

项目使用Arduino IDE烧录程序



驴友花雕 发表于 2022-7-24 13:29:00

开发板详细配置如图



驴友花雕 发表于 2022-7-24 13:47:57

安装相关驱动库

驴友花雕 发表于 2022-7-24 13:50:53




驴友花雕 发表于 2022-7-24 15:44:15

实验场景图


页: [1] 2
查看完整版本: 【花雕动手做】看见声音,基于Arduino系列音乐可视器(12)