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

发布时间 2023-06-30 21:37:42作者: 面筋玄师

找到环境光与声音传感器对应的管教,使能,再在时钟树中设置频率为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)