查看: 1027|回复: 0

[中级] RGB LED Matrix点阵屏--蓝牙频谱播放器

[复制链接]
本帖最后由 Mingming.Zhang 于 2018-1-17 17:31 编辑



6W4A7958.jpg
准备好我们需要的材料:

1. 32x16 RGB LED matrix 点阵屏;
1516157527(1).jpg
拿到点阵屏后还配带3跟线:彩色杜邦线(方便点阵和微控制板的连接,杜邦线两端都是母头);
红黑电源线;还有同样是点阵屏信号输入接口的灰色排线(和彩色杜邦线功能一样)。
1516157868.jpg
现在看到我们的点阵屏的背面:有3个接插的端口分别是 input、 电源、 output(考虑我的蓝牙音频播放器只用到一块rgb
,我们不用考虑级联另外的rgb屏。所以output不用,我们只需用到intput、电源。
1516158207(1).jpg
16x32RGB LED Matrix点阵屏   天生嘻哈天生有范儿
演示效果:
1632.gif
硬件清单:
.  DFRduino UNO R3(含USB线)
.  IO 传感器扩展板 V7.1            
.  16x32RGB LED Matrix点阵屏
. 12V/1000mA开关电源适配器(Arduino兼容)
接线示意图:
1000px-FIT0509连线图[1].jpg
代码示例:
[C] 纯文本查看 复制代码
#include <Adafruit_GFX.h>
#include <RGBmatrixPanel.h>
#define F2(progmem_ptr) (const __FlashStringHelper *)progmem_ptr
#define CLK 8 
#define LAT A3
#define OE  9
#define A   A0
#define B   A1
#define C   A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, true);
const char str[] PROGMEM = "DFrobot ";
int    textX   = matrix.width(),
       textMin = sizeof(str) * -12,
       hue     = 0;
static const uint16_t PROGMEM ballcolor[3] = {
  0x0080, // Green=1
  0x0002, // Blue=1
  0x1000  // Red=1
};

void setup() {
  matrix.begin();
  matrix.setTextWrap(false); // Allow text to run off right edge
  matrix.setTextSize(2);
}

void loop() {
  byte i;
  matrix.fillScreen(0);
  // Draw big scrolly text on top
  matrix.setTextColor(matrix.ColorHSV(hue, 255, 255, true));
  matrix.setCursor(textX, 1);
  matrix.print(F2(str));

  // Move text left (w/wrap), increase hue
  if((--textX) < textMin) textX = matrix.width();
  hue += 7;
  if(hue >= 1536) hue -= 1536;
  delay(100);
  matrix.swapBuffers(false);
}

同理32x32RGB LED Matrix点阵屏
演示效果:

32x32.gif
可以想象金属网格、rgb频谱、蓝牙音乐会搭配出怎样的视听享受?
说到音乐频谱???
让你跟着动起来!
哟哟切克闹,看看我在跳!一起来!呜哇!
其实跳跃的频谱还是有美感的 ,尤其是当音乐频率分量规律变化的时候, 挺有趣的 。另外可以上网搜索“音乐可视化”,频谱算音乐可视化的一种。底下推荐windows media player插件,把音乐的实时频谱用一些复杂的算法进行处理,转为画面显示出来。把频谱的画面美感做到极致了,画面和音乐同步是很神奇。
比如soundspectrum.com/
1516158472(1).jpg
上面都是软件频谱 如何硬件实现了?
大体思路就是:ADC转换、FFT快速傅里叶变化、rgb点阵屏显示、蓝牙连接、音频播放;
1516158958.jpg
我这里 准备的一个可插接的蓝牙音频模块:音质、灵活行、电压支持范围广(4.5v-27v都行)、关键性价比才40元。
从上面的接线图来看,主要蓝色接线端子 接左右声道的喇叭。电源接口可蓝色接线端子也可以dc插座。很灵活
1516159351(1).jpg

DFRduino Mega2560 V3.0控制器
选用它  是因为2方面的考虑: 做FFT快速傅里叶转换要的动态内存要的比较大(一般的arduino uno可能带不动);
rgb点阵屏的接线比较多12根,而且考虑加入颜色传感器随时改变音频灯效。
下面开始: dfrduino mega2560与点阵屏的接线;
1516159897.png
我们要依此接好点阵屏与mega2560的连接:
1. 3个GND D都是下面mega的gnd位置;
1516159814.png
2. R1, G1 and B1  对接 pin 24、25、26;
1516160062.png
3. R2, G2 and B2 对接 pin  27, 28 and 29;
1516160219.png
4. Pins A, B, and C 对接 PIN a4、a1and a2(ao口用于采集左右声道的音频模拟量);
5. LAT 接a3;
6.clk 接pin 11,OE 接pin 9.
完成以上连接

我们需要用到Rgb matrix panel库函数:
RGBmatrixPannel::color333(uint8_t r, uint8_t  g, uint8_t b)
//promote 3/3/3 rgb to adafruit_gfx 5/6/5 3/3/3颜色比例转换为5/6/5
RRRGGGBBB->RRRrrGGGgggBBBbb
类似color444(uint8_t r, uint8_t  g, uint8_t b)
     color888(uint8_t r, uint8_t  g, uint8_t b)
选用color888 r/g/b828次方等于256,方便对照rgb颜色对照表;
1516160773(1).jpg
我选择的color888 的颜色模式: rgb分别对应0~255;
Drawpixelint16_t x, int16_t y, uint16_t c) 绘制像素点
由于需要在arduino上进行声音处理,就需要FFT变换(快速傅里叶变换)
.  傅里叶变化概念
.  复数的概念
.  欧拉公式
好像记忆里大学的信号的数据分析原理以及通讯原理讲过;
下面附上处理的代码:
[C] 纯文本查看 复制代码
#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // FFT采样数:16.32.64.128.256
//#define DEBUG
#include <FFT.h> //快速傅里叶转换头文件声明
#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library

#define Cycle 3 //因为单次采样会有极大的噪音干扰,故用多次采样取平均值的方法
#define SIZE_WIDTH 32    //rgb显示宽度
//#define MAX_SPECTRUM 32 
#define GAIN 2.3
//#define FREQUENCY_INDEX(I) ((I)*3 + 10)
int Spectrum[SIZE_WIDTH];//数组记录多次采样值并在最后取平均数
// Similar to F(), but for PROGMEM string pointers rather than literals
//#define F2(progmem_ptr) (const __FlashStringHelper *)progmem_ptr
#define CLK 11 // MUST be on PORTB! (Use pin 11 on Mega)
#define LAT A3
#define OE  9
#define A   A4
#define B   A1
#define C   A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);

void setup() {
   Serial.begin(115200); // use the serial port
   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

   matrix.begin();
//           matrix.fillScreen(matrix.Color888(0, 150, 255));
//while(true);
 }
 
void loop() {
  int ave;
//  matrix.fillScreen(0);
  for (int m=0;m<SIZE_WIDTH;m++){
    Spectrum[m]=0;
  }
  for (int n=0;n<Cycle;n++){   //n记录采样次数
  //while(1) { // reduces jitter
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
         // cli();  // UDRE interrupt slows this way down on arduino1.0
      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 -= 0x0200; // form into a signed int
         k <<= 6; // form into a 16b signed int
         fft_input[i] = k; // put real data into even bins
         fft_input[i+1] = 0; // set odd bins to 0
       }
            // sei(); // turn interrupts back on
       // 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_log(); // take the output of the fft
      /* for (byte i = 0 ; i < FFT_N/2 ; i++) 
       { 
          Serial.println(fft_log_out[i]); // <--输出到串口  
       }*/
       //Serial.write(255); // send a start byte
       //Serial.write(fft_log_out, 128); // send out the data
      }


      
      static int times = 0;

        if(times++ == 0){
          times=0;
                for(int m=0;m<SIZE_WIDTH;m++){
        ave=0;
        for (byte i=m*4;i<(m+1)*4;i++){
          ave+=fft_log_out[i];
        }
        ave/=4;
        ave/=2;
        Spectrum[m]=ave;
        Spectrum[m]/=Cycle;
        Serial.print(Spectrum[m]);
        Serial.print("-");
        if (m ==15)
        {
          Serial.println("||");
        }
        
          Spectrum[0] = Spectrum[1]-22;
          //Spectrum[1] = Spectrum[1]-7;
          //Spectrum[2] = Spectrum[2]-6;
          //Spectrum[3] = Spectrum[3]-6;
         
          
        int y = Spectrum[m]-8;
        if(y>26)
        y = 15;
        
        /*if(y<=7){
          
           //y = 0;
           matrix.fillScreen(0);
        }*/
        
       matrix.drawLine(m, 0, m, y, matrix.Color888(0, 150, 255));
     
        matrix.drawLine(m, y+1, m, 15, matrix.Color888(0, 0, 0));
        

//        else{
//          //matrix.drawLine(m, 0, m, y, matrix.Color888(0, 0, 0));
//          //delay(100);
//        }
      }
        }


      
//      matrix.fillScreen(matrix.Color333(0, 0, 0));
      //delay(500);     
}

开始编制我的播放器的壳体: 用的比较金属和操作的金属网格;
6W4A7965.jpg
买好的金属网格是是一张很大的,需要根据实际需要  剪裁适合自己的大小;
6W4A7966.jpg
安装好螺丝固定,直角处  电烙铁焊接即可;
6W4A7967.jpg
然后是我选用的喇叭 4w 8欧姆的喇叭都是可以的 ,我用的方行喇叭;
1311_G_1470916873848[1].jpg
安装好所有电路和接口即可:
6W4A7978.jpg
安装我们的扬声器位置;
6W4A7980.jpg
我们的电源充电和数据更新口;
最后完工:
6W4A7982.jpg

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
wifi气象站

硬件清单

btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2016 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail