STM32项目分享:智能语音台灯(机智云)

目录

一、前言

二、项目简介

1.功能详解

2.主要器件

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

六、实验效果 

七、资料内容

项目分享


一、前言

项目成品图片:

哔哩哔哩视频链接:

STM32智能语音台灯(机智云)

(资料分享见文末) 

二、项目简介

1.功能详解

基于STM32的智能语音台灯(机智云)

功能如下:

  1. STM32F103C8T6单片机作为主控单元
  2. 按键切换模式,支持自动/手动两种模式
  3. 光敏电阻采集光照强度,超声波传感器采集坐姿距离,所有参数显示在OLED上
  4. 智能模式:自动识别有人开灯,并根据环境光强度控制灯的亮度
  5. 按键模式:按键手动调节灯亮度
  6. 语音模式:通过语音识别控制台灯调光与模式切换
  7. 坐姿报警:超声波距离报警
  8. 机智云APP:通过APP可查看数据,以及控制下发

2.主要器件

  • STM32F103C8T6单片机
  • OLED 屏幕
  • DHT11温湿度传感器
  • 光电红外传感器
  • 光敏传感器
  • SNR8016语音模块
  • HC-SR04超声波传感器
  • ESP8266模块(WIFI)
  • 有源蜂鸣器
  • 大功率LED灯模块

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

#include "stm32f10x.h"                  // Device header
#include "adcx.h"
#include "ldr.h"
#include "oled.h"
#include "dht11.h"
#include "pwm.h"
#include "led.h"
#include "key.h"
#include "tim2.h"   
#include "tim3.h"   
#include "hc_sr501.h"
#include "hc_sr04.h"
#include "sensormodules.h"
#include "usart.h"
#include "gizwits_product.h"
#include "myrtc.h"
#include "flash.h"
#include "iwdg.h"
#include "usart3.h"

#define KEY_Long1	11

#define KEY_1	1
#define KEY_2	2
#define KEY_3	3
#define KEY_4	4

#define FLASH_START_ADDR	0x0801f000	//写入的起始地址

uint8_t hc501;						//存储人体信号
uint8_t systemModel = 0;				//存储系统当前模式

uint8_t hour,minute,second;			//时 分 秒
uint8_t menu = 1;					//显示菜单变量



SensorModules sensorData;	//声明传感器数据结构体变量
SensorThresholdValue Sensorthreshold;	//声明传感器阈值结构体变量

enum 
{
	display_page = 1,
	settingsPage,
	timeSettingsPage
	
}MenuPages;

/**
  * @brief  显示主页面固定内容
  * @param  无
  * @retval 无
  */
void OLED_Menu(void)
{
	//显示“Time:”
	OLED_ShowString(1, 1, "Time");
	OLED_ShowChar(1, 5, ':');
	
	//显示“温度:”
	OLED_ShowChinese(2,1, 0);
	OLED_ShowChinese(2,2, 1);
	OLED_ShowChar(2, 5, ':');
	//显示“湿度:”
	OLED_ShowChinese(2,5, 2);
	OLED_ShowChinese(2,6, 1);
	OLED_ShowChar(2, 13, ':');	
	
	//显示“光强:”
	OLED_ShowChinese(3,1, 4);
	OLED_ShowChinese(3,2, 5);
	OLED_ShowChar(3, 5, ':');
	//显示“距离:”
	OLED_ShowChinese(3,5, 17);
	OLED_ShowChinese(3,6, 18);
	OLED_ShowChar(3, 13, ':');
		
	//显示“亮度:”
	OLED_ShowChinese(4,1, 6);
	OLED_ShowChinese(4,2, 1);
	OLED_ShowChar(4, 5, ':');
}

/**
  * @brief  显示主页面的传感器数据等信息
  * @param  无
  * @retval 无
  */
void OLED_Menu_SensorData(void)
{
		//显示时间数据
		OLED_ShowNum(1,6,MyRTC_Time[3],2);
		OLED_ShowChar(1,8,':');
		OLED_ShowNum(1,9,MyRTC_Time[4],2);
		OLED_ShowChar(1,11,':');
		OLED_ShowNum(1,12,MyRTC_Time[5],2);
	
		//显示温度数据
		OLED_ShowNum(2, 6, sensorData.temp, 2);
		OLED_ShowChar(2, 8, 'C');	

		//显示湿度数据
		OLED_ShowNum(2, 14, sensorData.humi, 2);	
		OLED_ShowChar(2, 16, '%');	

		//显示光强数据
		OLED_ShowNum(3, 6, sensorData.lux, 3);	

		//显示距离数据
		OLED_ShowNum(3, 14, sensorData.distance, 3);

		//显示亮度等级
		OLED_ShowNum(4, 6, ledDutyRatio, 3);
		OLED_ShowChar(4, 9, '%');	
	
		//显示是否有人
		if (sensorData.people)
		{
			OLED_ShowChinese(1, 8, 19);
		}
		else
		{
			OLED_ShowString(1, 15, "  ");	
		}	
		
		//显示系统当前模式 手动模式 or 自动模式
		if (systemModel)
		{
			//显示“自动”
			OLED_ShowChinese(4, 7, 9);
			OLED_ShowChinese(4, 8, 10);					
		}
		else
		{
			//显示“手动”
			OLED_ShowChinese(4, 7, 11);
			OLED_ShowChinese(4, 8, 12);			
		}
}

/**
  * @brief  显示系统设置界面
  * @param  无
  * @retval 无
  */
void OLED_SetInterfacevoid(void)
{
	//显示“系统设置界面”
	OLED_ShowChinese(1, 2, 20);
	OLED_ShowChinese(1, 3, 21);
	OLED_ShowChinese(1, 4, 22);
	OLED_ShowChinese(1, 5, 23);
	OLED_ShowChinese(1, 6, 24);
	OLED_ShowChinese(1, 7, 25);	
	
	//显示“系统时间”
	OLED_ShowChinese(2, 2, 20);
	OLED_ShowChinese(2, 3, 21);	
	OLED_ShowChinese(2, 4, 28);
	OLED_ShowChinese(2, 5, 29);	
	OLED_ShowChar(2, 11, ':');	
	OLED_ShowString(2, 13, "xxx");
	
	//显示“光照阈值”
	OLED_ShowChinese(3, 2, 4);
	OLED_ShowChinese(3, 3, 5);	
	OLED_ShowChinese(3, 4, 26);
	OLED_ShowChinese(3, 5, 27);	
	OLED_ShowChar(3, 11, ':');

	//显示”距离阈值“
	OLED_ShowChinese(4, 2, 17);
	OLED_ShowChinese(4, 3, 18);	
	OLED_ShowChinese(4, 4, 26);
	OLED_ShowChinese(4, 5, 27);	
	OLED_ShowChar(4, 11, ':');
	
	//显示光照阈值数值
	OLED_ShowNum(3, 13, Sensorthreshold.Illumination_threshold, 3);

	//显示距离阈值数值
	OLED_ShowNum(4, 14, Sensorthreshold.Distance_threshold, 2);
}

/**
  * @brief  记录阈值界面下按KEY1的次数
  * @param  无
  * @retval 返回次数
  */
uint8_t SetSelection(void)
{
	static uint8_t count = 1;
	if(KeyNum == KEY_1)
	{
		KeyNum = 0;
		count++;
		if (count >= 4)
		{
			count = 1;
		}
	}
	return count;
}

/**
  * @brief  显示阈值界面的选择符号
  * @param  num 为显示的位置
  * @retval 无
  */
void OLED_Option(uint8_t num)
{
	switch(num)
	{
		case 1:	
			OLED_ShowChar(1,1,' ');
			OLED_ShowChar(2,1,'>');
			OLED_ShowChar(3,1,' ');
			OLED_ShowChar(4,1,' ');
			break;
		case 2:	
			OLED_ShowChar(1,1,' ');
			OLED_ShowChar(2,1,' ');
			OLED_ShowChar(3,1,'>');
			OLED_ShowChar(4,1,' ');
			break;
		case 3:	
			OLED_ShowChar(1,1,' ');
			OLED_ShowChar(2,1,' ');
			OLED_ShowChar(3,1,' ');
			OLED_ShowChar(4,1,'>');
			break;
		default: break;
	}
}

/**
  * @brief  显示时间调节界面的选择符号
  * @param  num 为显示的位置
  * @retval 无
  */
void OLED_Time_Option(u8 num)
{
	switch(num)
	{
		case 1:	

			OLED_ShowChar(2,6,'v');
			OLED_ShowChar(2,9,' ');
			OLED_ShowChar(2,12,' ');
			break;
		case 2:	
			OLED_ShowChar(2,6,' ');
			OLED_ShowChar(2,9,'v');
			OLED_ShowChar(2,12,' ');
			break;
		case 3:	
			OLED_ShowChar(2,6,' ');
			OLED_ShowChar(2,9,' ');
			OLED_ShowChar(2,12,'v');
			break;
		default: break;
	}
}

/**
  * @brief  显示时间调节界面的内容
  * @param  无
  * @retval 无
  */
void OLED_ThresholdTime(void)
{
	//系统时间:
	OLED_ShowChinese(1, 3, 20); 
	OLED_ShowChinese(1, 4, 21); 
	OLED_ShowChinese(1, 5, 28); 
	OLED_ShowChinese(1, 6, 29); 
	OLED_ShowChar(1, 13, ':');

	OLED_ShowNum(3,5,hour,2);
	OLED_ShowChar(3,7,':');
	OLED_ShowNum(3,8,minute,2);
	OLED_ShowChar(3,10,':');
	OLED_ShowNum(3,11,second,2);
}

/**
  * @brief  对阈值界面的传感器阈值进行修改
  * @param  num 为当前用户需要更改的传感器阈值位置
  * @retval 无
  */
void ThresholdModification(uint8_t num)
{
	switch (num)
	{
		case 1:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				OLED_Clear();
				menu = timeSettingsPage;
				
				hour = MyRTC_Time[3];
				minute = MyRTC_Time[4];
				second = MyRTC_Time[5];	
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				OLED_Clear();
				menu = timeSettingsPage;
				
				hour = MyRTC_Time[3];
				minute = MyRTC_Time[4];
				second = MyRTC_Time[5];
			}			
			break;		

		case 2:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				Sensorthreshold.Illumination_threshold += 10;
				if (Sensorthreshold.Illumination_threshold > 999)
				{
					Sensorthreshold.Illumination_threshold = 1;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				Sensorthreshold.Illumination_threshold -= 10;
				if (Sensorthreshold.Illumination_threshold < 1)
				{
					Sensorthreshold.Illumination_threshold = 999;
				}				
			}			
			break;
		case 3:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				Sensorthreshold.Distance_threshold++;
				if (Sensorthreshold.Distance_threshold > 99)
				{
					Sensorthreshold.Distance_threshold = 1;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				Sensorthreshold.Distance_threshold--;
				if (Sensorthreshold.Distance_threshold < 1)
				{
					Sensorthreshold.Distance_threshold = 99;
				}				
			}
			break;
		default: break;		
	}
}

/**
  * @brief  对系统时间进行修改
  * @param  num 为当前用户需要更改的时分秒位置
  * @retval 无
  */
void TimeModification(uint8_t num)
{
	switch (num)
	{
		case 1:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				hour++;
				if (hour > 24)
				{
					hour = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				hour --;
				if (hour > 24)
				{
					hour = 24;
				}				
			}		
			break;		

		case 2:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				minute++;
				if (minute > 60)
				{
					minute = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				minute --;
				if (minute > 60)
				{
					minute = 60;
				}				
			}					
			break;
		case 3:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				second++;
				if (second > 60)
				{
					second = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				second --;
				if (second > 60)
				{
					second = 60;
				}				
			}		
			break;
		default: break;		
	}
}

/**
  * @brief  获取语音模块数据
  * @param  无
  * @retval 无
  */
void Asrpro(void)
{
	if (Usart3_RxFlag == 1)
	{
		Usart3_RxFlag = 0;
		switch (Usart3_RxPacket[3])
		{
			/*控制开关灯*/
			case 1:
				if (!systemModel)
				{
					if (Usart3_RxPacket[4])
					{
						ledDutyRatio = 100;
						TIM_SetCompare1(TIM1, ledDutyRatio);
					}
					else
					{
						ledDutyRatio = 0;
						TIM_SetCompare1(TIM1, ledDutyRatio);						
					}
				}
				break;
				
			/*控制灯暗一点或亮一点*/
			case 2:
				if (!systemModel)
				{
					if (Usart3_RxPacket[4])
					{
						ledDutyRatio += 25;
						if (ledDutyRatio > 100)
						{
							ledDutyRatio = 100;
						}
						TIM_SetCompare1(TIM1, ledDutyRatio);
					}
					else
					{
						ledDutyRatio -= 25;
						if (ledDutyRatio > 100)
						{
							ledDutyRatio = 0;
						}
						TIM_SetCompare1(TIM1, ledDutyRatio);						
					}
				}
				break;
				
			/*控制灯亮度百分比调节*/
			case 3:
				if (!systemModel)
				{
					switch (Usart3_RxPacket[4])
					{
						case 0:
							ledDutyRatio = 0;
							TIM_SetCompare1(TIM1, ledDutyRatio);
							break;
						
						case 1:
							ledDutyRatio = 10;
							TIM_SetCompare1(TIM1, ledDutyRatio);
							break;
												
						case 2:
							ledDutyRatio = 20;
							TIM_SetCompare1(TIM1, ledDutyRatio);
							break;
												
						case 3:
							ledDutyRatio = 30;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 4:
							ledDutyRatio = 40;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 5:
							ledDutyRatio = 50;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 6:
							ledDutyRatio = 60;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 7:
							ledDutyRatio = 70;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 8:
							ledDutyRatio = 80;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 9:
							ledDutyRatio = 90;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
												
						case 16:
							ledDutyRatio = 100;
							TIM_SetCompare1(TIM1, ledDutyRatio);							
							break;
						
						default:
							break;
					}
				}				
				break;
			
			/*控制系统模式*/
			case 4:
				if (Usart3_RxPacket[4])
				{
					systemModel = 1;
					ledDutyRatio = 0;
					TIM_SetCompare1(TIM1, ledDutyRatio);				
				}
				else
				{
					systemModel = 0;
					ledDutyRatio = 0;
					TIM_SetCompare1(TIM1, ledDutyRatio);	
				}
				break;	

			default:
				break;
		}
	}
}

/**
  * @brief  获取传感器的数据
  * @param  无
  * @retval 无
  */
void sensorScan(void)
{
		DHT11_Read_Data(&sensorData.humi, &sensorData.temp);
		HC_SR04_Deboanle(&sensorData.distance);
		LDR_LuxData(&sensorData.lux);
		HC_SR501_Input(&sensorData.people);		
}


int main(void)
{
	ADCX_Init();
	PWM_Init(100 - 1, 720 - 1);
	Timer2_Init(9,14398);
	Uart2_Init(9600);
	Uart1_Init(115200);
	IWDG_Init();	//初始化看门狗
	Uart3_Init();
	
	LDR_Init();
	OLED_Init();
	DHT11_Init();
	LED_Init();
	Key_Init();
	HC_SR501_Init();
	HC_SR04_Init();
	Buzzer_Init();
	MyRTC_Init();

	Sensorthreshold.Illumination_threshold = FLASH_R(FLASH_START_ADDR);	//从指定页的地址读FLASH
	Sensorthreshold.Distance_threshold = FLASH_R(FLASH_START_ADDR+2);	//从指定页的地址读FLASH

	
	GENERAL_TIM_Init();
	userInit();		//完成机智云初始赋值
	gizwitsInit();	//开辟一个环形缓冲区
	while (1)
	{
		do
		{
			currentDataPoint.valueIllumination_threshold = Sensorthreshold.Illumination_threshold;
			currentDataPoint.valueDistance_threshold = Sensorthreshold.Distance_threshold;
		}while(0);
		
 		IWDG_ReloadCounter(); //重新加载计数值 喂狗
		sensorScan();	//获取传感器数据
		Asrpro();	//执行语音指令
		
		switch (menu)
		{
			case display_page:

				MyRTC_ReadTime();	//调用此函数后,RTC硬件电路里时间值将刷新到全局数组
				OLED_Menu_SensorData();	//显示主页面传感器数据、系统模式等内容
				OLED_Menu();	//显示主页面的固定内容
				if (!systemModel)
				{
					LED_PWM_KEY();	//按键控制LED的PWM			
				}

				//切换系统模式
				if (KeyNum == KEY_1)
				{
					KeyNum = 0;
					systemModel = ~systemModel;
					if (systemModel)
					{
						currentDataPoint.valueModel = 1;
						ledDutyRatio = 0;
						TIM_SetCompare1(TIM1, ledDutyRatio);							
					}
					else
					{
						currentDataPoint.valueModel = 0;
						ledDutyRatio = 0;
						TIM_SetCompare1(TIM1, ledDutyRatio);	
					}
				}				
				
				//判断是否进入阈值设置界面
				if (KeyNum == KEY_Long1)
				{
					KeyNum = 0;
					OLED_Clear();	//清屏
					menu = settingsPage;	//跳转到阈值设置界面
				}
				break;
			case settingsPage:
				OLED_SetInterfacevoid();	//显示阈值设置界面的固定内容
				OLED_Option(SetSelection());	//实现阈值设置页面的选择功能
				ThresholdModification(SetSelection());	//实现阈值调节功能	
			
				//判断是否退出阈值设置界面
				if (KeyNum == KEY_2)
				{
					KeyNum = 0;
					OLED_Clear();	//清屏
					menu = display_page;	//跳转到主界面

					//存储修改的传感器阈值至flash内				
					FLASH_W(FLASH_START_ADDR, Sensorthreshold.Illumination_threshold, Sensorthreshold.Distance_threshold);
					currentDataPoint.valueIllumination_threshold = Sensorthreshold.Illumination_threshold;
					currentDataPoint.valueDistance_threshold = Sensorthreshold.Distance_threshold;
				}
				break;
			case timeSettingsPage:
				OLED_ThresholdTime();	//显示时间设置界面的内容
				OLED_Time_Option(SetSelection());	//实现间设置界面的选择功能
				TimeModification(SetSelection());	//实现时间调节功能	
				
				//判断是否退出时间设置界面
				if (KeyNum == KEY_2)
				{
					KeyNum = 0;
					//将更改的数据赋值回RTC数组中
					MyRTC_Time[3] = hour;	
					MyRTC_Time[4] = minute;
					MyRTC_Time[5] = second;		
					MyRTC_SetTime();	//调用此函数后,全局数组里时间值将刷新到RTC硬件电路	
		
					OLED_Clear();	//清屏
					menu = settingsPage;	//回到阈值设置界面
				}
				break;
		}	
		//判断上位机是否更改阈值,如更改则保存至flash中
		if (valueFlashflag)
		{
			valueFlashflag = 0;
			//存储修改的传感器阈值至flash内				
			FLASH_W(FLASH_START_ADDR, Sensorthreshold.Illumination_threshold, Sensorthreshold.Distance_threshold);
		}

		userHandle();	//更新机智云数据点变量存储的值
		gizwitsHandle((dataPoint_t *)&currentDataPoint);	//数据上传至机智云					
	}
}

六、实验效果 

七、资料内容

项目分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值