16浏览
查看: 16|回复: 2

[项目] 【Arduino 动手做】在 VFD 显示屏上 DIY 音频频谱分析仪

[复制链接]
频谱分析仪是一种测量工具,可显示传入音频信号的实时频率分析。

它通常是均衡器和音频信号处理设备的组成部分。纵轴表示以分贝为单位测量的特定频率的振幅。

这次我将向您展示如何在 20x2 VFD 显示屏上制作这样的设备。在我之前的某个视频中,您可以看到如何在这样的显示屏上制作音量表。这些显示屏的优点在于它们发出非常明亮的光线,对比度高,并且具有漂亮的复古外观。在我之前提到的视频 ( https://www.youtube.com/watch?v=gotUokTuP9U ) 中,您可以看到如何修改这样的显示屏,然后您可以使用适用于 16x2 字符 LCD 和 HD44780 驱动芯片的库。具体来说,在本例中,我们使用“LiquidCrystal”库来控制这个 VFD 显示屏。

所展示的设备构建非常简单,由几个组件组成:

- Arduino 纳米微控制器

- VFM202MDA1-1型VFD显示器略有修改

- 立体声电位器控制输入信号的强度

- 和两个电容器

用于分析和处理音频信号的库是“fix_fft”库。代码基础取自Ray Burnette,并进行了一些细微调整。新代码适用于20x2字符,提高了噪声敏感度阈值,并进行了一些细微的视觉校正。该设备内置于一个合适的盒子中,盒子由厚度为3毫米和5毫米的PVC材料制成,并贴有自粘墙纸。显示屏正面放置了一层薄而透明的滤光箔。


【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图1

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图2

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图3

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图4

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图5

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图6

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图7

驴友花雕  中级技神
 楼主|

发表于 4 小时前

【Arduino 动手做】在 VFD 显示屏上 DIY Arduino 音频频谱分...

项目代码

  1. /* FFT_TEST4
  2.   Ray Burnette 20130810 function clean-up & 1284 port (328 verified)
  3.   Uses 2x16 Parallel LCD in 4-bit mode, see LiquidCrystal lib call for details
  4.   http://forum.arduino.cc/index.php?PHPSESSID=4karr49jlndufvtlqs9pdd4g96&topic=38153.15
  5.   Modified by varind in 2013: this code is public domain, enjoy!
  6.   http://www.variableindustries.com/audio-spectrum-analyzer/
  7.   328P = Binary sketch size: 5,708 bytes (of a 32,256 byte maximum)
  8.   1284P= Binary sketch size: 5,792 bytes (of a 130,048 byte maximum) Free RAM = 15456
  9.   Binary sketch size: 8,088 bytes (of a 130,048 byte maximum) (Debug)
  10. */
  11. #include <Wire.h>
  12. #include <LiquidCrystal.h>
  13. #include <fix_fft.h>
  14. #define DEBUG 0
  15. #define L_IN 3 // Audio input A0 Arduino
  16. #define R_IN 2 // Audio input A1 Arduino
  17. const int Yres = 8;
  18. const int gain = 3;
  19. float peaks[64];
  20. char im[64], data[64];
  21. char Rim[64], Rdata[64];
  22. char data_avgs[64];
  23. int debugLoop;
  24. int i;
  25. int load;
  26. LiquidCrystal lcd(12, 11, 5, 4, 3, 2);// RS,E,D4,D5,D6,D7
  27. // Custom CHARACTERS
  28. byte v1[8] = {
  29.   B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111
  30. };
  31. byte v2[8] = {
  32.   B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111
  33. };
  34. byte v3[8] = {
  35.   B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111
  36. };
  37. byte v4[8] = {
  38.   B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111
  39. };
  40. byte v5[8] = {
  41.   B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111
  42. };
  43. byte v6[8] = {
  44.   B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111
  45. };
  46. byte v7[8] = {
  47.   B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111
  48. };
  49. byte v8[8] = {
  50.   B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111
  51. };
  52. void setup() {
  53.   if (DEBUG) {
  54.     Serial.begin(9600); // hardware serial
  55.     Serial.print("Debug ON");
  56.     Serial.println("");
  57.   }
  58.   lcd.begin(16,2);
  59.   lcd.clear();
  60.   lcd.createChar(1, v1);
  61.   lcd.createChar(2, v2);
  62.   lcd.createChar(3, v3);
  63.   lcd.createChar(4, v4);
  64.   lcd.createChar(5, v5);
  65.   lcd.createChar(6, v6);
  66.   lcd.createChar(7, v7);
  67.   lcd.createChar(8, v8);
  68.   for (i=0;i<100;i++)
  69.   {
  70.     for (load = 0; load < i / 5; load++)
  71.     {
  72.       lcd.setCursor(load, 1);
  73.       lcd.write(5);
  74.     }
  75.     if (load < 1)
  76.     {
  77.       lcd.setCursor(0, 1);
  78.       lcd.write(5);
  79.     }
  80.     lcd.setCursor(load + 1, 1);
  81.     lcd.write((i - i / 5 * 5) + 1);
  82.     for (load = load + 2; load < 20; load++)
  83.     {
  84.       lcd.setCursor(load, 1);
  85.       lcd.write(9);
  86.     }
  87.     lcd.setCursor(0, 0);
  88.     lcd.print("LOADING.............");
  89.     delay(10);
  90.   }
  91.   lcd.clear();
  92.   delay(10);
  93. }
  94. void loop() {
  95.   for (int i = 0; i < 64; i++) {    // 64 bins = 32 bins of usable spectrum data
  96.     data[i]  = ((analogRead(L_IN) / 8 ) - 256);  // chose how to interpret the data from analog in
  97.     im[i]  = 0;   // imaginary component
  98.     Rdata[i] = ((analogRead(R_IN) / 8 ) - 256);  // chose how to interpret the data from analog in
  99.     Rim[i] = 0;   // imaginary component
  100.   }
  101.   fix_fft(data, im, 6, 0);   // Send Left channel normalized analog values through fft
  102.   fix_fft(Rdata, Rim, 6, 0); // Send Right channel normalized analog values through fft
  103.   // At this stage, we have two arrays of [0-31] frequency bins deep [32-63] duplicate
  104.   // calculate the absolute values of bins in the array - only want positive values
  105.   for (int i = 0; i < 40; i++) {
  106.     data[i] = sqrt(data[i]  *  data[i] +  im[i] *  im[i]);
  107.     Rdata[i] = sqrt(Rdata[i] * Rdata[i] + Rim[i] * Rim[i]);
  108.     // COPY the Right low-band (0-15) into the Left high-band (16-31) for display ease
  109.     if (i < 20) {
  110.       data_avgs[i] = data[i];
  111.     }
  112.     else {
  113.       data_avgs[i] = Rdata[i - 20];
  114.     }
  115.     // Remap values to physical display constraints... that is, 8 display custom character indexes + "_"
  116.     data_avgs[i] = constrain(data_avgs[i], 0, 9 - gain);     //data samples * range (0-9) = 9
  117.     data_avgs[i] = map(data_avgs[i], 0, 9 - gain, 0, Yres);  // remap averaged values
  118.   }
  119.   Two16_LCD();
  120.   decay(1);
  121. }
  122. void Two16_LCD() {
  123.   lcd.setCursor(0, 0);
  124.   lcd.print("L"); // Channel ID replaces bin #0 due to hum & noise
  125.   lcd.setCursor(0, 1);
  126.   lcd.print("R"); // ditto
  127.   for (int x = 1; x < 20; x++) {  // init 0 to show lowest band overloaded with hum
  128.     int y = x + 20; // second display line
  129.     if (data_avgs[x] > peaks[x]) peaks[x] = data_avgs[x];
  130.     if (data_avgs[y] > peaks[y]) peaks[y] = data_avgs[y];
  131.     lcd.setCursor(x, 0); // draw first (top) row Left
  132.     if (peaks[x] == 0) {
  133.       lcd.print("_");  // less LCD artifacts than " "
  134.     }
  135.     else {
  136.       lcd.write(peaks[x]);
  137.     }
  138.     lcd.setCursor(x, 1); // draw second (bottom) row Right
  139.     if (peaks[y] == 0) {
  140.       lcd.print("_");
  141.     }
  142.     else {
  143.       lcd.write(peaks[y]);
  144.     }
  145.   }
  146.   debugLoop++;
  147.   if (DEBUG && (debugLoop > 99)) {
  148.     Serial.print( "Free RAM = " );
  149.     Serial.println( freeRam(), DEC);
  150.     Serial.println( millis(), DEC);
  151.     debugLoop = 0;
  152.   }
  153. }
  154. int freeRam () {
  155.   extern int __heap_start, *__brkval;
  156.   int v;
  157.   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
  158. }
  159. void decay(int decayrate) {
  160.   int DecayTest = 1;
  161.   // reduce the values of the last peaks by 1
  162.   if (DecayTest == decayrate) {
  163.     for (int x = 0; x < 40; x++) {
  164.       peaks[x] = peaks[x] - 1;  // subtract 1 from each column peaks
  165.       DecayTest = 0;
  166.     }
  167.   }
  168.   DecayTest++;
  169. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 4 小时前

【Arduino 动手做】在 VFD 显示屏上 DIY Arduino 音频频谱分...

【Arduino 动手做】在 VFD 显示屏上 DIY Arduino 音频频谱分析仪
项目链接:https://www.hackster.io/mircemk/ ... -vfd-display-655c10
项目作者:北马其顿 米尔塞姆克(Mirko Pavleski)
项目参考:https://www.youtube.com/watch?v=gotUokTuP9U
项目视频 :https://www.youtube.com/watch?v=MmLOjRUFaSg
项目代码:https://www.hackster.io/code_files/594048/download

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图1

【Arduino 动手做】在 VFD 显示屏上 DIY  音频频谱分析仪图2

回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

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

mail