4.STM32传感器ADC采样+继电器控制实现声光控灯

找到环境光与声音传感器对应的管教,使能,再在时钟树中设置频率为12Mhz,一般不要太高

 

在adc.c 中可以添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enum
{
    ADCCHN_NOISY,
    ADCCHN_LUX,
    ADCCHN_MAX,
};
 
int adc_sample_lux_noisy(uint32_t *lux,uint32_t *noisy)
{
    uint8_t i;
    uint32_t timeout = 0xffffff;
 
    for(i = 0;i<ADCCHN_MAX;i++)
    {
        HAL_ADC_Start(&hadc1);
        HAL_ADC_PollForConversion(&hadc1,timeout);
 
        if(ADCCHN_NOISY == i)
        {
            *noisy = HAL_ADC_GetValue(&hadc1);
        }
        else if(ADCCHN_LUX == i)
        {
            *lux = HAL_ADC_GetValue(&hadc1);
        }
 
        HAL_Delay(10);
    }
 
    HAL_ADC_Stop(&hadc1);
 
    return 0;
}

在adc.h中声明函数后,可以在main函数中调用,用串口调试助手测试结果:

 

基于此,我们可以实现简单的声光控灯了。

 ----------------------------------------------------------------------------------------------------------------

继电器介绍:

  

 

 

 以下是用开发板上的rgb灯,根据环境光和声音情况模拟继电器开关控制灯的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if( OFF == light_status)
      {
          adc_sample_lux_noisy(&lux,&noisy);
          printf("lux: %ld,noisy: %ld\n",lux,noisy);
 
          if(lux <30 && noisy >800)
          {
              printf("turn light on\r\n");
              turn_relay(ON);
              turn_led(RedLed,ON);
              light_status = ON;
 
              start = HAL_GetTick();
          }
      }
      else
      {
          if(time_after(HAL_GetTick(),start+15000))
          {
              printf("Turn Light off\r\n");
              turn_relay(OFF);
              turn_led(RedLed,OFF);
 
              HAL_Delay(200);
              light_status = OFF;
          }
 
      }
 
      HAL_Delay(300);

 

    代码中,我们通过ADC采样当前的光强和噪音值,如果光线较弱并且声音比较大的话就控制继电器开灯。为了符合实际情况,做了一个时间的控制,15s后将自动关灯。

    延时15s 的控制逻辑实现里,我们并没有直接用HAL_Delay(1500),而是在点灯的时候记录当前时间,然后循环获取当前时间看有没有超时,如果超时则”控制继电器关灯”。(这样可以在每次循环间隙做一些其他的操作)


    在判断时间是否到没有,我们不能直接if((HAL_GetTick() - start) - 15000)这个条件判断,因为变量的最大记值是有限制的(uint32_t最大计数到2^32-1),而时间是无限的,这样会存在时间回绕的问题。
    

    (参考Linux内核里的jiffies回绕解决方案,使用了time_after()这个宏来判断是否超时。这个宏需要添加到main.h头文件中。)

 

1
2
3
4
5
#define time_after(a,b) ((int32_t)(b) - (int32_t)(a) <0)
#define time_before(a,b) time_after(b,a)
 
#define time_after_eq(a,b) ((int32_t(a) - (int32_t)(b) >=0))
#define time_before_eq(a,b) time_after_eq(b,a)

  

 

 

posted @   面筋玄师  阅读(234)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示