Arduino 打造一个音量计

根据上一次的LM386的设计【参考1】,以及网上的设计【参考2】,用Arduino做一个音量计。首先,音频从MIC进入,经过LM386的放大后接入到Arduino的模拟输入上,经过 DAC 量化之后显示在 1602上。

电路方面,和【参考1】差别在于我们不再使用喇叭而是直接将放大后的OUT信号接入到 Arduino的A5上。

显示方面,我们使用【参考3】提到的方法来自定义字符充当强度指示。

下面的图片与其说是原理图不如说是连接图更合适

vu1

//www.lab-z.com 
//在 1602 上显示音量的小程序

#include <Wire.h> 
#include "LiquidCrystal_I2C.h"

int value=100;

// custom charaters

LiquidCrystal_I2C lcd(0x27,16,2);

//定义进度块
byte p1[8] = {
                0x10,
                0x10,
                0x10,
                0x10,
                0x10,
                0x10,
                0x10,
                0x10};

byte p2[8] = {
                0x18,
                0x18,
                0x18,
                0x18,
                0x18,
                0x18,
                0x18,
                0x18};

byte p3[8] = {
                0x1C,
                0x1C,
                0x1C,
                0x1C,
                0x1C,
                0x1C,
                0x1C,
                0x1C};

byte p4[8] = {
                0x1E,
                0x1E,
                0x1E,
                0x1E,
                0x1E,
                0x1E,
                0x1E,
                0x1E};

byte p5[8] = {
                0x1F,
                0x1F,
                0x1F,
                0x1F,
                0x1F,
                0x1F,
                0x1F,
                0x1F};

void setup() {
               lcd.init();           //初始化LCD
               lcd.backlight();		 //打开背光
				
			//将自定义的字符块发送给LCD
			//P1 是第一个,P2 是第二个,以此类推
                lcd.createChar(0, p1);			 
                lcd.createChar(1, p2);
                lcd.createChar(2, p3);
                lcd.createChar(3, p4);
                lcd.createChar(4, p5);
            //MIC输入放大之后在 A0 输入Arduino    
                pinMode(A0, INPUT);
}

//显示音量强度
//从左到右一共有 5 * 16 =80 点,一共是 80+1=81 个状态
void showprg(int value)
{
        //第一行显示当前VU值
                lcd.setCursor(0,0);
                lcd.print("     VU=");
                lcd.print(value);

                
		//移动光标到第二行
                lcd.setCursor(0,1);

        //显示全黑的块
                for (int i=1;i<value / 5;i++) {
                                lcd.write(4);
                        } //for (int i=1;i<a;i++) 


                // drawing charater's colums
		// 显示除去全黑块之后的零头
                switch (value % 5) {
                  case 0:
                        break;
                  case 1:
                        lcd.write(0);
                        break;
                  case 2:
                        lcd.write(1);
                        break;
                  case 3:
                        lcd.write(2);
                        break;
                  case 4:
                        lcd.write(3);
                        break;
                  } //switch (peace)

	       // 用空格填充剩下的位置
              for (int i =0;i<(16-value / 5);i++) {
                lcd.print(" ");   }
}

void loop()
{
     //输入的是0-1023,用函数将这个值对应到[0,80]上 
        showprg(map(analogRead(A0),0,1023,0,80));
		delay(100);
              
}

 

测试方法,在右边用一个手机播放声音,MIC将音频信号转化为电平信号,经过LM386放大后,通过Arduino A5进行量化,最终显示在LCD1602上。

vu2

工作视频:

这个还只是一个模型,很粗糙,对于VU的动态显示范围不大,如果想让人类更容易理解需要考虑将现在的线性显示改为非线性的。

另外,工作时我发现比较奇怪的事情,就是如果静音的时候,会显示UV 大约 35左右,但是如果有动态声音播放的时候反而会出现 16 这样值,不清楚原因。

==============================================================================
另外的另外,研究了一下前面那个口哨开关的模拟输出。下面是电路图,右下角红色框起来的是模拟输出电路部分

vu3

查了一下,发现这种用法是电压跟随器,下图来自【参考4】。

vu4

电压跟随器,顾名思义,是实现输出电压跟随输入电压的变化的一类电子元件。也就是说,电压跟随器的电压放大倍数恒小于且接近1【参考5】。
多少输入就是多少输出…….这也就是为什么这个模块驱动能力很差带不动喇叭的原因。
参考:

1. http://www.lab-z.com/lm386-with-mic/ LM386 with MIC
2.http://www.arduino-hacks.com/arduino-vu-meter-lm386electret-microphone-condenser/ Arduino VU meter – LM386+electret microphone condenser
3. http://www.lab-z.com/1602progressbar/ 用 1602实现进度条
4. http://www.geek-workshop.com/thread-551-1-1.html LM358双运算放大器
5. http://baike.baidu.com/link?url=85VzUTT6n3IrCaAATZSg5jsg_A-zQYFrizj6jqGP7PzRg1aJe2yTddMihqJ7_UgRMa_GxnAYakSmmjM-9nhsz_ 电压跟随器

发表评论

电子邮件地址不会被公开。 必填项已用*标注