4.STM32传感器ADC采样+继电器控制实现声光控灯
找到环境光与声音传感器对应的管教,使能,再在时钟树中设置频率为12Mhz,一般不要太高
在adc.c 中可以添加如下代码:
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灯,根据环境光和声音情况模拟继电器开关控制灯的代码:
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头文件中。)
#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)

浙公网安备 33010602011771号