欢迎光临haoDIY - DIY制作从这里开始!

diy音响功放音箱胆机电子单片机电脑科技小发明机器人制作_haoDIY

haodiy微信
当前位置: 主页 > 最新DIY >

LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)

时间:2017-07-09 10:53来源:数码之家 作者:2545889167 点击:
之前参加某宝商家的免单活动(其实就是shua dan了,活动早就没了,别问了)免费得了个LED点阵胸牌。到手后发现他配套的上位机非常非常难用,10次连接,1次不到的概率能连接到胸牌下载程序,而且内容编辑功能也巨难用。然而,转念也想,貌似作为一个胸牌我也用
之前参加某宝商家的免单活动(其实就是shua dan了,活动早就没了,别问了)免费得了个LED点阵胸牌。到手后发现他配套的上位机非常非常难用,10次连接,1次不到的概率能连接到胸牌下载程序,而且内容编辑功能也巨难用。然而,转念也想,貌似作为一个胸牌我也用不到,还不如跟风改造个音乐频谱,于是就有了今天的帖子。
胸牌原装的芯片是GD32f150c6t6,这个芯片时国内MCU企业兆易创新推出的超值型单片机。然而这个东西不像pos机上的gd32f103,和stm32f03基本上是完全兼容的。这货的引脚和stm32f103c8不兼容,但是和stm32f030c8引脚兼容(如图),然而GD32f150c6t6的内核是cortex m3,stm32f030c8内核是cortex m0,也就是说,这两个在内核上也是不兼容的。

LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft) 所以说了半天,是不是有点绕。但是综上所述就是,GD32f150这个芯片不是我熟悉使用的,而且貌似无论使用stlink还是jlink都不能选到合适的型号直接调试(即不支持),要使用gd link ,但是我没有。
可以使用串口做isp下载,但是这样不能做调试还要每次下载拉boot0很不爽的。在观察电路的时候,我甚至发现,这个板子上的BOOT0引脚是直接接地的。也就是说,这真心断了我在原装芯片上折腾的兴趣。
正好GD32f150c6t6和stm32f030c8的引脚是兼容的,我手上也有几片stm32f030c8,于是就开始了本帖的魔改心路例程
首先先放上魔改总体设计图
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
第一步当然是拆原装芯片
拆下来的gd32妥善保管,以防以后研究没有进展不想玩了的时候,还有后悔的机会,吧原来芯片换回去就满血复活了
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
因为这个pcb是黑色的,所以在跑走线的时候,真心是一边骂娘一边在放大镜下看
顺便拍下了空焊盘下的走线,方便以后备查
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
还有一张
同时经过测量,我也吧boot0接地的走线直接隔断了,也是为了方便以后操作
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
换上stm32f030(这个芯片不带USB,这是和gd32的一个区别)
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
因为是黑油,很难完整的排查出走线,所以使用了观察走线(查出哪些走线和led有关)+程序点亮排查+万用表点亮(确定行列逻辑)的综合手段来排查
最后大概花了两天的时间吧走线跑通并实现点亮。

首先,这个led是44(列)*11(行)的点阵,使用了23个io来驱动
其次,每两列是共阳的
接着,每一行是有2-3个io来共阴驱动的,驱动的时候,一组负责奇数,一组负责偶数(大致是这样的,实际更复杂,但是也有规律)
最后,吧行列线直接直连。
第23根线的作用类似于用来解决对角线引脚重复问题(大致是这样的,实际更复杂,但是也有规律)

上面这段貌似说了一大堆也没说明白,其实这东西,语言不好讲明白,画电路图很复杂,只能意会不好言传,哈哈。暂且认为你们听懂了,实在不懂的,可能去看下程序怎么实现的,就懂了。
如图是吧所以列的共阳拉高,拉低点亮其中一行的情况,看到了吧,这规律还是有点风骚的
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
行驱动在对角线位置会出行跳到下一行的动作,并且奇偶会发生变化。这样就是为毛我熬了两天才吧所有线序弄明白的原因。
设计者的这个设计真的太精妙也太复杂了
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
最后的测序结果如图,很佩服用23个io点亮了484个led的人
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
其实这个工程到这里就算是吧最难的坎过去了,后面要做啥都很简单了,只要扫描驱动就好
如图是我做的驱动和原装没改造过的显示亮度效果对比
为了追求亮度,貌似我设置的扫描速度要稍微慢了点,但是也只是局限于相机的效果,反正眼睛看,都一样,没区别
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
后面点亮了整个led就是开始改造频谱了。
主要是加了在PA3输入音频信号,剪了一个报废的耳机线接上,又焊接了一个座子供声音输出监听用的。
板子左边吧供电和调试用的swd都引出来了。
至于外观,请勿吐槽,处于实验阶段都是随便乱接线的,图的是方便,要美观的话肯定是要等到设计定性以后才考虑的
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
特写
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
然后开始编程。主要就是吧快速傅里叶变换(FFT)的东西弄好了,就可以玩了
快速傅里叶变换(FFT)的这个东西,不接触的时候,看着就感觉都难,实际上,如果吧他当作一个黑箱来用的时候,其实就不怎么难了。
具体详细原理可以看这两个帖子:
http://www.51hei.com/bbs/dpj-49593-1.html
http://www.amobbs.com/forum.php?mod=viewthread&tid=5574941
(我大致说下怎么用,说的不好大神勿喷)
也就是说,这个东西的作用就是吧一段采集到的的信号进行分析,从而得到这段信号里面频率的分布和对应的强度,也就是说吧时域信号转为频域信号。
而如果我们吧他看作一个黑箱,给他输入的信号是adc采样得到的信号,中间进行了一些换算,换算的结果是以复数的形式表现的,最后进行取模运算,就是这个频率点对于的模长(可以理解成强度)。

我用到的是进行128点的转换。首先使用定时器进行定时(我设置了24khz采样,也就是说,最高能捕捉12khz的信号),设置每次定时器溢出的时候自动触发一次ADC转换。转换完成后的数据由DMA自动搬运到内存指定位置,这个采样过程无需cpu干预,完全自动,处理器该干嘛干嘛去。在完成128次定频率的转换后,会触发一个完成中断,在中断里面将处理完成标志置为1。
然后我们定义一个数组,里面使用结构体,实部加虚部,
复制代码
  1. struct compx {float real,imag;};  
这个数组长度为128。
当满足上一次换算完成和adc采样完成的两个条件时,将所有采样adc得到的数据搬运到上面定义的数组里面的实部里面,然后将所以虚部赋值为0.
这个数组完成赋值后,就可以吧他丢给FFT函数进行换算了,具体的换算过程,我们不用管他,当做黑箱来用,感兴趣的可以看看书。
完成换算以后,换算的结果是以复数的形式表现的,比如某个频率的信息以a+bi的形式表示,这里a是实部,b是虚部,最后进行取模运算,也就是取a和b的平方根,就是这个频率点对于的模长(可以理解成强度)。
将这个模长进行长度拉申或压缩(为了适应屏幕的显示高度),然后就可以吧这些内容显示到屏幕上了。
核心代码展示
其实真的很简单,不难
复制代码
  1. #define FFT_N 128  
  2. extern uint16_t scan_frame_buffer[44];//led显示缓存
  3. extern uint8_t ADC_Sample_Complete;//ADC取样完成标志
  4. extern uint16_t RegularConvData_Tab[ADC_sam_dat_size];
  5.  
  6. const uint16_t dat2display[12]={0x0000,0x0400,0x0600,0x0700,0x0780,0x07c0,0x07e0,0x07f0,0x07f8,0x07fc,0x07fe,0x07ff};//吧数据转换成显示的灯条长度
  7. struct compx {float real,imag;};  
  8.  
  9. struct compx s[FFT_N]; //FFT输入和输出:从S[1]开始存放,根据大小自己定义
  10.  
  11. void Show_Spectrum(void)
  12. {
  13.     uint16_t i;
  14.     uint8_t cache;
  15.     while(ADC_Sample_Complete==0);//等待adc转换完成
  16.     for(i=0;i<FFT_N;i++)
  17.     {
  18.         s[i].real=(float)RegularConvData_Tab[i];//实部为正弦波FFT_N点采样,赋值为ADC取样值
  19.         s[i].imag=0;   //虚部为0          
  20.     }
  21.     ADC_Sample_Complete=0;//删除标志位
  22.     Restart_DMA();//开始采样
  23.     FFT(s);//做傅里叶变换
  24.     for(i=0;i<FFT_N;i++)
  25.     {
  26.         s[i].real=sqrt(s[i].real*s[i].real+s[i].imag*s[i].imag);    //求变换后结果的模值,存入复数的实部部分
  27.     }
  28.     
  29.     for(i=0;i<44;i++)//吧计算结果写入显示缓存
  30.     {
  31.         cache=(uint8_t)(s[i+1].real/200);
  32.         if(cache>11)cache=11;
  33.         scan_frame_buffer[i]=dat2display[cache];
  34.     }        
  35. }

我现在做的转换所需耗时的参数和专业人士做的还是有很大的差距,不过也是在可视范围内完全完全够用了。
做128点FFT运算。处理器M0内核,速度48mhz。每次转换耗时约20ms的样子。也就是说每秒刷新50次已经完全超出视觉了,也是够用了。

而这次做下来,最花时间的首先是跑LED的走线和想办法驱动,第二花时间的是如何实现TIM+ADC+DMA的自动运行。因为我是第一次用STM32F030,之前用103的时候很多想法都有先人实践过,大部分抄过来改改就行了,然而030真心资料好少,调试这三样东西花了我好多的精力才调通。其中有两个坑要说的,默认的TIMER-TRGO事件是定时器复位而不是定时器updata溢出,也就是说,要配置成updata,才能在每次定时器溢出的时候触发adc 。第二出就是这个芯片的定时器15个人感觉有很大的问题。它定出来的时间是常规的128分频,然而我找了参考手册,没找到关于怎么调整这个分频为1分频的地方。参考时钟树,发觉同样是挂在APB2上的定时器16,确是一切正常,毫无半点问题,这也是百思不得其解。。。。之前我是用定时器15触发adc的,结果发觉频率老是不对,后来改到了定时器3触发,就一切正常了。  

最后说一点,对于USB和电池电压检测,因为换了030,都是不支持的,所以这方面我就没研究了。

使用软件单一频率的扫频部分图
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)
LED点阵胸牌魔改为音乐频谱(附视频、源代码、原理讲解fft)

最后是音乐播放的视频
其实如果这个点阵能宽度变成2倍的话,也就是44*22的话,那么显示效果真的能大大提升,现在这个矮矮的,频率条子太容易冲出去了。
里面有四首歌,(按顺序)分别是,这些歌里面除了第三首是看了坛友的视频跟风测试的以外,其他几首貌似都比较小众,个人感觉也很悦耳,算是安利一发吧,喜欢的可以下载听听
King of My Heart  
歌手:Love & the Outcome
Bonnie & Clyde
歌手:Sarah Connor/Henning Wehland
My Soul(忧伤还是快乐)  
歌手:昼夜
The Riot's Gone
歌手:Santigold



源代码在这里:链接:http://pan.baidu.com/s/1sk9jV1V 密码:tce9
或者可以下载附件



回帖都有m币哦


[ 此帖被2545889167在2016-11-12 12:16重新编辑 ]
赞一下
(0)
0%
一般般
(0)
0%
相关文章
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
用户名: 验证码: 点击我更换图片
栏目列表
推荐DIY