找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4931|回复: 13
打印 上一主题 下一主题
收起左侧

DIY单片机声控小夜灯+PWM四档亮度调节 原理图PCB和程序全套资料

  [复制链接]
跳转到指定楼层
楼主
本帖最后由 zsw3721 于 2022-2-18 23:28 编辑

2022年2月18日本次更新:

截至目前使用了半个多月,可以说是非常好用和方便的。电池很耐用,睡前使用一会再设置为声控触发模式,晚上带娃要经常点亮灯,充一次电基本上可以使用一个星期。这段时间进行了多处优化,程序升级为V1.6版。
1. 调整为5档PWM亮度调节,分别为20%、40%、60%、80%、100%亮度
2. 增加声控触发过滤,在1秒内需要3次及以上的外部中断才能触发亮灯(不会影响正常声控触发,因为一个声音比如一声咳嗽实际会有非常多个中断产生),消除了单个偶发的杂波干扰导致可能的意外亮灯或反复触发无法熄灯

3. 声控触发亮灯后60秒后才允许声控再触发,即每次声控亮灯3分钟的后两分钟完全平静即可自动熄灯
4. 声控触发亮灯后,距自动熄灯剩余10秒时亮度自动降低(至10%亮度)
5. 长按亮度调节按键2秒以上,亮度调整为10%亮度
6. 定时器T0(定时1mS)初值纠正为12MHz 1T的配置(之前程序为11.0592MHz下的配置)。程序下载时应选择12MHz时钟频率。
7. 增加MCU进掉电模式以降低功耗:声控亮灯3分钟自动熄灯后即控制MCU进入掉电模式,当有外部中断(即声音信号)时MCU唤醒并正常触发亮灯。


程序 V1.6 增加声控待触发状态下进掉电模式以降低功耗.rar (45.88 KB, 下载次数: 65)



2022年1月28日更新一次:
试用了几天后,优化了两处地方,程序升级为V1.4版。
1. 声控触发亮灯后延时3分钟自动熄灯,修改为自动熄灯前如果又检测到声音,重新计时3分钟
2. 按键从常亮模式切换到声控待触发模式,默认熄灯,但是按键的声音会导致切到声控待触发模式后直接触发亮灯,现修改为按键切到声控待触发模式后等待1秒钟才允许被触发亮灯

以下为2022年1月27日原始帖:
最近,老婆大人提了一个需求,要一个声控的小夜灯。在某宝搜索一番无果,于是自己动手设计。
老规矩,先上最终完工的实物图。使用三天的效果:非常好,谁用谁知道。



下面简单介绍一下制作过程。

首先是理清需求。

1. 需要有内置电池供电,使用时可随意摆放位置
2. 有常亮模式和声控亮灯模式
3. 声控亮灯模式使用时,小声音不能触发,要一定强度的声音才能触发亮灯
4. 声控亮灯触发后,延时3分钟自动熄灭,熄灭前最后10秒亮度自动调至最低

5. 支持多档亮度调节,灯光无闪烁感

然后是硬件设计。
1. 电池好解决,以前网上购买的5V升压锂电池就很好用
2. 声音检测模块可以购买现成的,灵敏度可调节
3. 使用MCU外部中断处理声音检测模块的信号
4. 使用软件PWM方式进行亮度调节,PWM频率100Hz就足够了

5. 两个按键,分别控制亮灯模式和亮度调节
6. 一共只需要4个IO口,用我熟悉的STC15F104W绰绰有余
7. LED灯可以购买现成的USB LED灯,设计一个PMOS电路用于控制LED的供电

下面是设计好的原理图。


设计好的PCB。



嘉立创免费打样,焊好并准备好材料。


下面这个是购买的声控模块,有声音时输出低电平。直接焊在我的控制板上。以后如果有机会做升级版,会把这个声控模块画到我的电路中。



然后开始写程序。功能比较简单,两百多行代码就搞定。用了一个定时器,定时1mS,然后中断里每10mS扫一次按键;PWM功能也在定时器中实现。
下面是代码。附件有整套资料,如果你想做一个,按我的资料放心去做保证成功。如果你做出来了,欢迎贴个图分享。

后注:以下为原始程序,比V1.4版更早。

  1. /*********************************************************************
  2. 《声控小夜灯》
  3. 设计:zsw3721 @51黑
  4. 日期:2022/1/26
  5. MCU型号:STC15F104W
  6. 系统时钟:12MHz

  7. 功能简介:
  8. 1.支持常亮与声控点亮;
  9. 2.声控点亮后延时3分钟自动熄灭,熄灭前最后10秒钟亮度自动调至最低;
  10. 3.支持四档PWM亮度调节:10%、40%、70%、100%亮度;PWM频率100Hz无闪烁感;
  11. **********************************************************************/

  12. #include "STC15.H"
  13. #include "intrins.h"

  14. #define LED_ON   P32=1;     //LED点亮,P3.2口高电平输出驱动三极管和PMOS导通点亮LED
  15. #define LED_OFF  P32=0;     //LED熄灭

  16. sbit Key1 = P3^4;                    //按键1,短按常亮与声控模式切换,长按功能未定义
  17. sbit Key2 = P3^5;                    //按键2,短按PWM四档亮度调节,长按功能未定义

  18. bit ShortTouchFlag1=0;      //按键1短按按键有效标志
  19. bit LongTouchFlag1=0;       //按键1长按按键有效标志
  20. bit LongTouchRelease1=1;    //按键1长按释放过的标志
  21. bit ShortTouchFlag2=0;      //按键2短按按键有效标志
  22. bit LongTouchFlag2=0;       //按键2长按按键有效标志
  23. bit LongTouchRelease2=1;    //按键2长按释放过的标志
  24. bit Flag_1s=1;              //秒任务标志位

  25. unsigned int uiKeyTimeCnt1; //按键1计数
  26. unsigned int uiKeyTimeCnt2; //按键2计数

  27. unsigned char MODE=0;                //工作模式0,1,2分别表示LED常亮模式、声控待触发模式、声控已触发模式
  28. unsigned int Count_1S=0;    //1000mS计数器
  29. unsigned char Count_10mS=0; //10ms计数器
  30. unsigned char Count_180S;   //时间计数器,声控触发后延时180S关灯
  31. unsigned char PWM_COUNT;    //PWM计数器
  32. unsigned char LED_Brightness=10;   //LED亮度设定值,0~10表示0~100%亮度,开机默认最大亮度
  33. unsigned char PWM_SET;      //PWM占空比设置,可取值0~10,对应占空比0~100%;



  34. /********************************************
  35. 函数说明:初始化IO口、定时器、外部中断等
  36. ********************************************/
  37. void Init(void)
  38. {   
  39.     P3M1 &= ~(1<<2);        //将LED驱动脚P3.2设置为推挽输出
  40.         P3M0 |= (1<<2);

  41.         LED_ON;                        //开机后默认开灯
  42.     PWM_SET = LED_Brightness;   //配置PWM初始占空比   

  43.         AUXR |= 0x80;                //定时器T0 时钟1T模式
  44.         TMOD &= 0xF0;                //设置定时器模式为16位自动重装
  45.         TL0 = 0xCD;                    //设置定时初值
  46.         TH0 = 0xD4;                    //设置定时初值
  47.         TF0 = 0;                    //清除TF0标志
  48.         TR0 = 1;                    //定时器0开始计时
  49.         ET0 = 1;                        //允许T0中断
  50.    
  51.     P33 = 1;            //设置外部中断IO口高电平
  52.     IT1 = 1;            //设置INT1的中断类型为下降沿触发 (1:仅下降沿 0:上升沿和下降沿)
  53.     EX1 = 1;            //使能INT1中断

  54.     EA = 1;             //使能全局中断
  55. }


  56. /******************************
  57. 函数说明:按键短按长按检测
  58. ******************************/
  59. void Key_scan(void)                 //在定时器T0中断里每10mS调用一次检查按键状态
  60. {
  61.         if(Key1==0)                     //如果按键1按下
  62.         {
  63.             uiKeyTimeCnt1++;            //累加按键计时
  64.         }
  65.         if(uiKeyTimeCnt1>200 && LongTouchRelease1==1)   //当按键超过2秒且此前释放过一次时
  66.         {
  67.                 LongTouchFlag1 = 1;         //长按标志位置1,用于长按2秒后立即处理长按动作
  68.                 LongTouchRelease1 = 0;      //长按释放标志置0,表示长按未释放
  69.         }
  70.         if(Key1==1)                     //当按键松开(也可能是抖动弹开)
  71.         {
  72.                 if(uiKeyTimeCnt1>2 && uiKeyTimeCnt1<=200)   //只有大于20mS,且小于2秒,才判为短按
  73.                 {
  74.                         uiKeyTimeCnt1 = 0;      //清零按键计时
  75.                         ShortTouchFlag1 = 1;        //短按标志位置1
  76.                         LongTouchFlag1 = 0;     //长按标志位置0        
  77.                 }
  78.                 if(uiKeyTimeCnt1>200)       //如果松开按键时按键超过2秒,则为长按释放
  79.                 {
  80.                         uiKeyTimeCnt1 = 0;      //清零按键计时
  81.                         LongTouchRelease1 = 1;  //长按释放标志位置1,表示长按已释放
  82.                 }        
  83.         }

  84.         if(Key2==0)                     //如果按键2按下
  85.         {
  86.             uiKeyTimeCnt2++;            //累加按键计时
  87.         }
  88.         if(uiKeyTimeCnt2>200 && LongTouchRelease2==1)   //当按键超过2秒且此前释放过一次时                          
  89.         {
  90.                 LongTouchFlag2 = 1;         //长按标志位置1,用于长按2秒后立即处理长按动作
  91.                 LongTouchRelease2 = 0;      //长按释放标志置0,表示长按未释放
  92.         }
  93.         if(Key2==1)                     //当按键松开(也可能是抖动弹开)
  94.         {
  95.                 if(uiKeyTimeCnt2>=2 && uiKeyTimeCnt2<=200)  //只有大于等于20mS,且小于2秒,才判为短按
  96.                 {
  97.                         uiKeyTimeCnt2 = 0;      //清零按键计时
  98.                         ShortTouchFlag2 = 1;    //短按标志位置1
  99.                         LongTouchFlag2 = 0;     //长按标志位置0        
  100.                 }
  101.                 if(uiKeyTimeCnt2>200)       //如果松开按键时按键超过2秒,则为长按释放
  102.                 {
  103.                         uiKeyTimeCnt2 = 0;      //清零按键计时
  104.                         LongTouchRelease2 = 1;  //长按释放标志位置1,表示长按已释放
  105.                 }        
  106.         }
  107. }


  108. /******************************
  109. 函数说明:按键处理
  110. ******************************/
  111. void Key_process(void)
  112. {
  113.         if(ShortTouchFlag1==1)          //当按键1短按标志位为1时进行按键1短按处理
  114.         {
  115.                 ShortTouchFlag1 = 0;        //清除短按标志位
  116.         if(MODE==0)                 //常亮模式下按Key1进入声控模式
  117.         {
  118.             MODE = 1;               //声控模式
  119.             LED_OFF;                //进入声控模式后默认先不亮灯
  120.             PWM_SET = 0;
  121.             PWM_COUNT = 0;
  122.             Count_180S = 0;
  123.         }
  124.         else if(MODE==1 || MODE==2) //MODE=1为声控待触发模式,MODE2为声控已触发模式
  125.         {
  126.             MODE = 0;               //进入常亮模式并亮灯
  127.             PWM_SET = LED_Brightness;   //PWM占空比因子调整为亮度设置值
  128.             Count_180S = 0;
  129.         }
  130.         }
  131.         if(LongTouchFlag1==1)           //按键1长按处理
  132.         {
  133.                 LongTouchFlag1 = 0;         //清除长按标志位
  134.         //此处可执行Key1长按动作
  135.         }        
  136.         if(ShortTouchFlag2==1)          //按键2短按处理,功能为亮度设置
  137.         {
  138.                 ShortTouchFlag2 = 0;        //清除短按标志位
  139.         LongTouchFlag2 = 0;         
  140.         LED_Brightness += 3;        //四档PWM亮度调节,LED_Brightness可取值1、4、7、10分别对10%、40%、70%、100%亮度
  141.         if(LED_Brightness>10)       //亮度达到最大后再按Key2,亮度从1重新开始调整
  142.         {
  143.             LED_Brightness = 1;
  144.         }
  145.         PWM_SET = LED_Brightness;   //PWM占空比因子调整为亮度设置值
  146.         }
  147.         if(LongTouchFlag2==1)           //按键2长按处理
  148.         {
  149.                 LongTouchFlag2 = 0;                //清除长按标志位
  150.         //此处可执行Key2长按动作
  151.         }
  152. }

  153. /******************************
  154. 函数说明:主函数
  155. ******************************/
  156. void main(void)
  157. {
  158.         Init();                         //系统初始化   
  159.         while(1)
  160.         {
  161.                 Key_process();              //调用按键处理函数
  162.         
  163.         if(Flag_1s==1 && MODE==2)   //声控已触发模式触发后进行计时并延时3分钟关灯
  164.         {
  165.             Flag_1s = 0;            //清秒标志位
  166.             Count_180S++;           //秒计数器加1
  167.             if(Count_180S==170 && PWM_SET>1)
  168.             {
  169.                 PWM_SET = 1;        //离关灯剩余10秒时亮度调至最低即10%
  170.             }
  171.             if(Count_180S>=180)     //声控点亮3分钟后自动熄灯
  172.             {
  173.                 Count_180S = 0;
  174.                 PWM_SET = 0;        //亮度调至0%即熄灯
  175.                 MODE = 1;           //重新进入声控待触发模式
  176.             }            
  177.         }      
  178.         }
  179. }


  180. void time0(void) interrupt 1        //T0中断服务函数,每1ms进入一次
  181. {
  182.     PWM_COUNT++;                    //PWM每1mS为调节步长,一个周期10mS共10步
  183.    
  184.         if(++Count_10mS>=10)            //每10ms扫描一次按键状态
  185.     {
  186.         Count_10mS = 0;
  187.         Key_scan();
  188.     }

  189.         if(++Count_1S>=1000)            //每1秒设置一次秒标志位
  190.         {
  191.                 Count_1S = 0;
  192.                 Flag_1s = 1;
  193.         }
  194.    
  195.     if(PWM_COUNT<=PWM_SET)          //控制PWM输出占空比
  196.     {
  197.         LED_ON;
  198.     }
  199.     else
  200.     {
  201.         LED_OFF;
  202.     }

  203.     if(PWM_COUNT>=10)               //控制PWM周期为10mS,即频率100Hz
  204.     {
  205.         PWM_COUNT = 0;
  206.     }
  207. }


  208. void exint1() interrupt 2           //INT1外部中断入口
  209. {
  210.     if(MODE==1)                     //声控待触发模式才执行以下动作
  211.     {
  212.         MODE = 2;                   //进入声控已触发模式
  213.         PWM_SET = LED_Brightness;   //亮灯
  214.         PWM_COUNT = 0;
  215.         Count_1S = 0;
  216.         Flag_1s = 0;
  217.     }
  218. }
复制代码

全部资料51hei下载地址:
声控小夜灯原理图PCB和程序全套资料.rar (11.34 MB, 下载次数: 120)



评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏13 分享淘帖 顶1 踩
回复

使用道具 举报

来自 2#
ID:702386 发表于 2022-1-28 20:20 | 只看该作者
试用了几天后,优化了两处地方,程序升级为V1.4版。
1. 声控触发亮灯后延时3分钟自动熄灯,修改为自动熄灯前如果又检测到声音,重新计时3分钟
2. 按键从常亮模式切换到声控待触发模式,默认熄灯,但是按键的声音会导致切到声控待触发模式后直接触发亮灯,现修改为按键切到声控待触发模式后等待1秒钟才允许被触发亮灯

程序 V1.4.rar

43.53 KB, 下载次数: 48, 下载积分: 黑币 -5

升级程序

回复

使用道具 举报

板凳
ID:577622 发表于 2022-1-28 11:37 | 只看该作者
自己动手丰衣足食,DIY精神永垂不朽!
回复

使用道具 举报

地板
ID:267707 发表于 2022-1-28 13:02 | 只看该作者

自己动手丰衣足食,DIY精神永垂不朽!
回复

使用道具 举报

5#
ID:59830 发表于 2022-1-30 10:22 | 只看该作者
看了一下,资料不错.值得参考一下.
回复

使用道具 举报

6#
ID:687881 发表于 2022-2-16 11:07 | 只看该作者
电池供电的话,STC一直工作着,电流也有5-10MA,一天下来耗电也不少,用上掉电中断模式就能省不少电了。
回复

使用道具 举报

7#
ID:702386 发表于 2022-2-17 08:46 | 只看该作者
kindzhon 发表于 2022-2-16 11:07
电池供电的话,STC一直工作着,电流也有5-10MA,一天下来耗电也不少,用上掉电中断模式就能省不少电了。

谢谢你的建议,我后面想想怎么在低功耗方面再优化一下。
目前这个灯已经试用了一段时间,发现偶尔出现整夜不能自动关灯的情况,怀疑是有杂波干扰到声音检测模块,现已升级了一版程序,增加了声控触发的过滤机制,要求在1秒内有3个以上的中断脉冲才允许触发亮灯,测试几天后未再发现不能自动关灯的情况。后面我完善后会分享新版程序。
回复

使用道具 举报

8#
ID:229641 发表于 2022-2-23 21:44 来自手机 | 只看该作者
这玩意儿能搞个缓启动亮度吗?也就是慢慢的亮起来…
回复

使用道具 举报

9#
ID:230500 发表于 2022-3-5 20:35 | 只看该作者
谢谢你的无私分享, 很有学习的意义,
回复

使用道具 举报

10#
ID:1008454 发表于 2022-3-6 09:30 | 只看该作者
pcb是关键,程序很重要。
回复

使用道具 举报

11#
ID:702386 发表于 2022-3-7 08:59 | 只看该作者
auxccc 发表于 2022-3-6 09:30
pcb是关键,程序很重要。

确实PCB很关键,我后面再升级的话,会多考虑PCB布局走线的问题,可能还要给声音检测部分设计隔离电源或加强滤波,使系统自身尤其是PWM调光部分带来的干扰影响减小,这样能进一步提高可靠性和灵敏度。
回复

使用道具 举报

12#
ID:91721 发表于 2022-3-9 14:07 | 只看该作者
谢谢你的无私分享,很有爱的一次应用。
回复

使用道具 举报

13#
ID:430492 发表于 2022-3-9 14:12 | 只看该作者
pcb可以自己布线,主要是想法很重要。
回复

使用道具 举报

14#
ID:364201 发表于 2022-8-25 17:46 | 只看该作者
楼主,这个设计可以改成红外人体传感器的方式吗?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表