1. 程式人生 > >不務正業之音樂節奏燈

不務正業之音樂節奏燈

前幾天在知乎上看到一個音樂節奏燈得帖子,覺得很有意思。就上淘寶買了材料,跟著淘主得視訊做了個LED音樂節奏燈。(我可能是吃飽撐著沒事做)。在此記錄一下製作過程。

本程式程式碼由Scott Lawson編寫,併發布在Github,這個程式碼最後一次更新在2年前。由於相容性問題,由知乎使用者:(英語老師摸我腿)修改,其還有製作教程。感謝各位大佬支援。

工具

1.Arduino

2.Anaconda(Python)

3.PVC管

4.ESP8266開發板

5.LED燈帶(60顆/1米)

6.5V的燈座

7.燈罩

8.杜邦線

9.MicroUSB資料線

實現步驟:

1.

下載並安裝Arduino和Anaconda

2.

在Anaconda中建立Python環境,並命名為MusicLed

3.

在Anaconda的MusicLed環境下Open Terminal安裝一些庫

conda install numpy scipy pyqtgraph
pip insatll pyaudio

4.

注:最好先連上VPN,不然安裝很容易失敗

安裝完Arduino,開啟安裝一些庫。

然後點選(工具)-(開發板)-(開發板管理器)-(等它載入完成在搜尋框輸入:ESP8266。只有一個結果直接點選安裝)。

接著點選(專案)-(載入庫)-(管理庫)-(搜尋框輸入websock,安裝的版本為2.1.1)。

5.

注:電腦小白最好安裝Notepad++

修改程式碼:注意以下注釋就好了。只要修改ws2812_controller.ion和config.py兩處的部分註釋程式碼。

6.

修改完兩個程式碼後,就要把arduino程式碼上傳到ESP8266上。

首先把板子插在電腦的USB埠上。

然後檢視裝置管理器中板子在哪個口,例如:CH340(COM3)。

接著點選ws2812_controller.ino進入Arduino,點選(工具)-(開發板)-(SparkFun ESP8266 Thing Eev)-修改埠為(COM3)-(上傳程式碼即可)。

最後點選Strat.bat,看到以下介面說明程式碼基本無誤:

7.

接下來就是組裝節奏燈就好啦。

注:這裡注意燈帶上的箭頭,不要接反了。

如果看不懂上圖可以看這個(靈魂畫手):

這裡將用將兩根杜邦線分別接上5v的紅線與GND,然後用PVC電氣膠布纏繞上即可。

記得用一根杜邦線將ESP8266的RX口和燈帶的DI口連線起來,否則燈帶不會亮。

然後將燈帶纏繞到PVC管上。

最後通電就可以啦。注:燈座的插頭電壓可能不夠導致燈帶亮的時候,ESP板子不通電(分壓)。這時候把充電頭換成手機的快充頭即可給兩個部件同時通電。

節奏燈,程式打開了,燈不亮。PING一下你給ESP8266設定的IP地址,如果通,那說明ESP8266執行正常,請檢查線是否接好,並保證兩個檔案設定正確。關閉PC程式,重新開啟試試

8.

大家電腦可能沒有混音功能。所以先下載Viocemeeter,點選A1選擇如下圖所示:

然後在(聲音)-(播放)將其設定為預設裝置即可,(錄製)也是如此。

9.

最後(給燈座通上點)-(點選Start.bat)-(開啟Voicemeeter)-(開啟音樂播放器播放音樂即可,當然你直接對著電腦講話也有同樣效果只要是有聲音輸入都行)。

完!

Arduino程式碼

ws2812_controller.ino

/*
 * 注意,一定要看到檔案隔壁還有很多字尾名為".h"的檔案,如果沒有的話,那說明當前資料夾下沒有這個檔案。編譯會出錯。
 * 參考資料:https://github.com/scottlawsonbc/audio-reactive-led-strip
 * 原始碼2年未更新,稍作修改。
 * 你只需要修改程式碼後面後中文註釋的地方!
 */

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WebSocketsServer.h>
#include <Hash.h>
#include <WiFiUdp.h>
#include "ws2812_i2s.h"


#define NUM_LEDS 120 //LED燈數量

#define BUFFER_LEN 1024

#define PRINT_FPS 1


const char* ssid     = "zzzzzzzccccccc"; //你家WIFI名字
const char* password = "zcp5313.."; //你家WIFI密碼
unsigned int localPort = 7777;
char packetBuffer[BUFFER_LEN];


static WS2812 ledstrip;
static Pixel_t pixels[NUM_LEDS];
WiFiUDP port;

//你可以使用Windows+R鍵輸入cmd,然後輸入命令ipconfig 檢視自己網路情況。

IPAddress ip(192, 168, 1, 150); //你給ESP8266設定的IP地址,注意,這個IP不可以跟其他裝置(手機電腦燈)重複。

IPAddress gateway(192, 168, 1, 1); //你家網路的閘道器,這個跟你電腦的閘道器一樣

IPAddress subnet(255, 255, 255, 0); //子網掩碼,跟你電腦的一樣,一般不需要修改。

void setup() {
    Serial.begin(115200);
    WiFi.config(ip, gateway, subnet);
    WiFi.begin(ssid, password);
    Serial.println("");
    // Connect to wifi and print the IP address over serial
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    port.begin(localPort);
    ledstrip.init(NUM_LEDS);
}

uint8_t N = 0;
#if PRINT_FPS
    uint16_t fpsCounter = 0;
    uint32_t secondTimer = 0;
#endif

void loop() {
    // Read data over socket
    int packetSize = port.parsePacket();
    // If packets have been received, interpret the command
    if (packetSize) {
        int len = port.read(packetBuffer, BUFFER_LEN);
        for(int i = 0; i < len; i+=4) {
            packetBuffer[len] = 0;
            N = packetBuffer[i];
            pixels[N].R = (uint8_t)packetBuffer[i+1];
            pixels[N].G = (uint8_t)packetBuffer[i+2];
            pixels[N].B = (uint8_t)packetBuffer[i+3];
        } 
        ledstrip.show(pixels);
        #if PRINT_FPS
            fpsCounter++;
        #endif
    }
    #if PRINT_FPS
        if (millis() - secondTimer >= 1000U) {
            secondTimer = millis();
            Serial.printf("FPS: %d\n", fpsCounter);
            fpsCounter = 0;
        }   
    #endif
}

Python程式碼

config.py

# 你只需要修改有註釋的地方
# 其他未備註的地方,看得懂程式碼的人,請自行修改,需要需要了解numpy,pyaudio

#conding = utf8
from __future__ import print_function
from __future__ import division
import os

DEVICE = 'esp8266'


if DEVICE == 'esp8266':
# 下面是你剛才在Arduino中為ESP8266設定的IP地址,不要填錯了。
    UDP_IP = '192.168.1.150'
   
    UDP_PORT = 7777
  
    SOFTWARE_GAMMA_CORRECTION = False
 

if DEVICE == 'pi':
    LED_PIN = 18
   
    LED_FREQ_HZ = 800000
   
    LED_DMA = 5
   
    BRIGHTNESS = 255

    LED_INVERT = True
   
    SOFTWARE_GAMMA_CORRECTION = True
  

if DEVICE == 'blinkstick':
    SOFTWARE_GAMMA_CORRECTION = True
    

USE_GUI = True


DISPLAY_FPS = True

# 下面是你LED燈的數量,這個也不能搞錯,錯了,程式就執行出錯!
N_PIXELS = 120


GAMMA_TABLE_PATH = os.path.join(os.path.dirname(__file__), 'gamma_table.npy')


MIC_RATE = 44100


FPS = 60

_max_led_FPS = int(((N_PIXELS * 30e-6) + 50e-6)**-1.0)
assert FPS <= _max_led_FPS, 'FPS must be <= {}'.format(_max_led_FPS)

MIN_FREQUENCY = 200


MAX_FREQUENCY = 12000


N_FFT_BINS = 24


N_ROLLING_HISTORY = 2


MIN_VOLUME_THRESHOLD = 1e-7