基于STM32的智能燈光控制系統(tǒng)
基于STM32的智能燈光控制系統(tǒng)
一、題目背景和意義:
隨著社會(huì)不斷進(jìn)步,市場(chǎng)在不斷變化,高科技應(yīng)用含量決定著產(chǎn)品發(fā)展的新趨勢(shì)和前景,智能化技術(shù)在電子產(chǎn)品領(lǐng)域的應(yīng)用意義深遠(yuǎn)。隨著電子產(chǎn)品的快速發(fā)展,家用電器也越來(lái)越偏向智能化,本文介紹一款基于STM32的智能光照燈。
回想一下,日常生活中使用燈光時(shí)是否有以下情景“老公關(guān)一下燈、老公幫我開一下燈,我夠不著”、“石頭剪刀布,誰(shuí)輸了誰(shuí)去關(guān)燈”、“以及寢室中住在最邊上負(fù)責(zé)開關(guān)燈的同學(xué).......額...由于我就是這個(gè)位置,深有感受啊?。?!”。照明燈已是千家萬(wàn)戶的必需生活用品,但每次要去開關(guān)燈的時(shí)候總是千難萬(wàn)阻,基于此,本項(xiàng)目研發(fā)了一款智能燈光系統(tǒng),具備手機(jī)app控制燈光、語(yǔ)音控制等功能,更加方便快捷,徹底解決住在下鋪兄弟的煩惱,哈哈哈哈。
二、項(xiàng)目整體展示:
“智能光照燈”使用STM32作為系統(tǒng)的MCU,由于單片機(jī)IO口驅(qū)動(dòng)電流過(guò)小,搭配三極管放大電流,從而滿足光照強(qiáng)度需求,且將單片機(jī)IO配置成PWM輸出,以便于調(diào)節(jié)不同的光強(qiáng)度,也就是一檔、二檔、三檔。在此基礎(chǔ)上增加WiFi模塊搭配手機(jī)APP可實(shí)現(xiàn)在手機(jī)端控制燈光、使用su-03t語(yǔ)音識(shí)別模塊可實(shí)現(xiàn)語(yǔ)音控制燈光等,其他額外功能在下文介紹。所需材料如表1所示。
表1 材料清單
序號(hào) | 名稱 | 數(shù)量 |
1 | STM32核心板 | 1 |
2 | 三極管 | 3 |
3 | LED燈板 | 2 |
4 | WiFi模塊 | 1 |
5 | Su-03t芯片 | 1 |
6 | oled屏幕 | 1 |
7 | 超聲波模塊 | 1 |
8 | dht11 | 1 |
9 | 按鍵 | 4 |
10 | 蜂鳴器 | 1 |
項(xiàng)目整體展示如圖1:
圖1 項(xiàng)目整體展示
三、主要電子模塊介紹:
1、STM32核心板:
STM32是“意法半導(dǎo)體”生產(chǎn)的基于“ARM公司Cortex-M3內(nèi)核”的32位MCU,其性能強(qiáng)大,資源豐富,被廣泛應(yīng)用于嵌入式系統(tǒng)的開發(fā),也是高校學(xué)生接觸嵌入式的敲門磚。最小系統(tǒng)板如圖2所示,其由處理器、電源、復(fù)位、晶振電路等組成,可獨(dú)立的完成相應(yīng)的控制任務(wù),在本次工程中核心知識(shí)就是PWM輸出,I/O口引腳電平判斷。
圖2 STM32最小系統(tǒng)板
2、三極管:
三極管的放大作用就是:集電極電流受基極電流的控制(假設(shè)電源能夠提供給集電極足夠大的電流的話),并且基極電流很小的變化,會(huì)引起集電極電流很大的變化,且變化滿足一定的比例關(guān)系:集電極電流的變化量是基極電流變化量的β倍,即電流變化被放大了β倍。至于三極管的控制,如圖3所示及其簡(jiǎn)單,在圖片中所標(biāo)的A引腳初,輸出高電平就能導(dǎo)通三極管,上方VCC的電源就能流過(guò)三極管。
圖3 三極管內(nèi)部電路
3、WiFi模塊:
本項(xiàng)目所使用的WiFi模塊是ESP-01S,是ESP8266系列的一種,其可以連接環(huán)境中的WiFi,從而使設(shè)備上網(wǎng)。本項(xiàng)目主要使用了該模塊串口功能,通過(guò)串口與stm32單片機(jī)連接,WiFi模塊通過(guò)周圍環(huán)境中的WiFi信號(hào)連接云平臺(tái),如此將WiFi模塊作為中介,可以實(shí)現(xiàn)單片機(jī)與云平臺(tái)的信息交互。WiFi模塊與單片機(jī)連接引腳如圖4:
圖4 WiFi模塊連接圖
4、su-03t語(yǔ)音識(shí)別模塊:
su-03t是一款低成本、低功耗、小體積的離線語(yǔ)音識(shí)別的模組,無(wú)需編程,使用刷詞條的方式進(jìn)行開發(fā),可謂是不愛編程的福音啊。本項(xiàng)目使用該模塊的串口功能,通俗一點(diǎn)講就是模塊識(shí)別到相應(yīng)的語(yǔ)音命令后,通過(guò)串口輸出一個(gè)數(shù)據(jù)。關(guān)于該模塊的配置,本文再次不過(guò)多闡述。該模塊引腳如圖5所示:
圖5 SU-03T引腳展示圖
5、超聲波模塊:
超聲波模塊為HC-SR04如圖6所示,該超聲波測(cè)距模塊可提供約2cm~400厘米的非接觸式距離感測(cè)功能,測(cè)距精度可達(dá)高到3毫米,該模塊由****裝置與接受裝置組成,****裝置****超聲波,接受裝置接受超聲波并將電平做出相應(yīng)轉(zhuǎn)變。
圖6 超聲波模塊
6、OLED屏
OLED顯示屏是利用有機(jī)電自發(fā)光二極管制成的顯示屏。由于同時(shí)具備自發(fā)光有機(jī)電激發(fā)光二極管,不需背光源、對(duì)比度高、厚度薄、視角廣、反應(yīng)速度快、比LCD屏幕顯示效果更好一些,但由于現(xiàn)有技術(shù)限制,目前OLED屏幕無(wú)法做的很大。本項(xiàng)目主要使用OLED屏幕顯示臺(tái)燈的當(dāng)前狀態(tài)、溫濕度信息、以及萬(wàn)年歷時(shí)鐘燈,相關(guān)顯示如圖7所示。
圖7 相關(guān)顯示結(jié)果
四、項(xiàng)目制作
4.1、先讓燈亮起來(lái)
正如章節(jié)3中所說(shuō),燈帶是通過(guò)三極管驅(qū)動(dòng)的,單片機(jī)的IO口連接三極管基極,可以將其看成控制信號(hào),當(dāng)該引腳輸出高電平時(shí),可以認(rèn)為三極管導(dǎo)通,電流由****極提供,由集電極輸出,本設(shè)計(jì)中****極連接VCC,也就是用電源給等待供電,這個(gè)電流遠(yuǎn)大于IO口直接輸出的電流,足以滿足等待的需求。
4.2、調(diào)節(jié)燈光亮度
剛剛已經(jīng)介紹過(guò)如何使用三極管點(diǎn)亮燈帶。那么又該如何控制燈的亮度哪?也就是如何控制電流呢?這就需要常說(shuō)的PWM輸出了,可以將三極管看成一個(gè)“水龍頭”,PWM可以理解為我們擰水龍頭的力氣,通過(guò)調(diào)節(jié)不同的占空比,使得三極管“打開不同的口子”,控制邏輯如下:
PWM占空比大→“打開的口子大”→輸出的電流大→燈帶更亮
PWM占空比小→“打開的口子小”→輸出的電流小→燈帶更暗
在程序中首先將IO口配置為PWM輸出,本設(shè)計(jì)選用的定時(shí)器4的通道3與通道4產(chǎn)生PWM(兩個(gè)燈,一個(gè)冷光一個(gè)暖光,需要兩路PWM輸出)具體程序見程序1:
程序1:
void Motor_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定時(shí)器4時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘
/*****輸出TIM4_CH3和TIM4_CH4和的PWM脈沖波形*****/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //TIM_CH3和TIM_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
/********************初始化TIM3*******************/
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
/*******初始化TIM4 Channel3、TIM4 Channel4 PWM模式********/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性:TIM輸出比較極性高
TIM_OC3Init(TIM4, &TIM_OCInitStructure); //初始化外設(shè)TIM4 OC3
TIM_OC4Init(TIM4, &TIM_OCInitStructure); //初始化外設(shè)TIM4 OC4
/*******使能預(yù)裝載寄存器********/
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_Cmd(TIM4, ENABLE); //使能TIM4
}
如此PWM的輸出就已經(jīng)配置好了,下面就在主循環(huán)中調(diào)用修改PWM占空比函數(shù)即可,具體程序見程序2,該程序修改了三個(gè)不同的占空比,以對(duì)應(yīng)燈光的一檔、二檔、三檔。
程序2:
/********兩端都使能 1檔**********/
TIM_SetCompare3(TIM4,800);
TIM_SetCompare4(TIM4,800);
/********兩端都使能 2檔**********/
TIM_SetCompare3(TIM4,2000);
TIM_SetCompare4(TIM4,2000);
/********兩端都使能 3檔**********/
TIM_SetCompare3(TIM4,5000);
TIM_SetCompare4(TIM4,5000);
4.3、遠(yuǎn)程控制功能
正如上文所說(shuō),遠(yuǎn)程控制功能實(shí)現(xiàn)的原理是,手機(jī)app開發(fā)時(shí)連接上云平臺(tái),手機(jī)APP相應(yīng)按鍵觸發(fā)時(shí),將相應(yīng)的控制指令上傳至云平臺(tái),esp-01s通過(guò)周圍的WiFi信號(hào)連接云平臺(tái),獲取云平臺(tái)上的數(shù)據(jù),并通過(guò)串口將該數(shù)據(jù)傳輸給STM32單片機(jī),單片機(jī)解析數(shù)據(jù)并完成相應(yīng)的驅(qū)動(dòng)。接下來(lái)就分布實(shí)現(xiàn)開發(fā),分為手機(jī)端app的制作,手機(jī)連接云平臺(tái)、設(shè)備連接云平臺(tái)。
4.3.1手機(jī)端app的制作:
本項(xiàng)目使用一款麻省理工研發(fā)的開發(fā)安卓app的平臺(tái)——appinventor,該平臺(tái)基于圖形化編程,是“不愿意編程黨”的福音,不需要使用代碼開發(fā)app,使用一些邏輯關(guān)系模塊完成開發(fā)。首先在主頁(yè)面拖放好各種想要的按鍵,之后再編程界面拖放邏輯關(guān)系模塊,完成開發(fā)(與labview相似)。
4.3.2手機(jī)端連接云平臺(tái):
在使用appinventor開發(fā)的過(guò)程中,調(diào)用連接云平臺(tái)接口,連接云平臺(tái),博主使用的是巴法云平臺(tái),再巴法云官網(wǎng)有詳細(xì)的教程。打開巴法云官網(wǎng)其界面如圖8所示,點(diǎn)擊圖片中所圈的地方“實(shí)例指南”進(jìn)入八法開放論壇,之后在論壇中找到“APP inventor編寫安卓app控制ESP8266”這篇文章,如圖9所示,里面有詳細(xì)的制作過(guò)程。
圖8 巴法云界面
圖9 論壇內(nèi)容
額外說(shuō)一下這個(gè)云平臺(tái)接口,ClientSocketAI2Ext,這個(gè)不是appinventor的原生組件,需要再Extension下導(dǎo)自行導(dǎo)入插件。
另外,有想學(xué)習(xí)appinventor的可以看一下這個(gè)博主的網(wǎng)課,我當(dāng)時(shí)就是跟隨這個(gè)博主學(xué)的,很詳細(xì),很好學(xué),兩天完成。學(xué)習(xí)鏈接:老巫婆的程序世界的個(gè)人空間_嗶哩嗶哩_bilibili
4.3.3設(shè)備(單片機(jī))連接云平臺(tái)
esp-01s也是一個(gè)MCU,通過(guò)編程開發(fā),本設(shè)計(jì)通過(guò)arduino平臺(tái)開發(fā)相關(guān)的功能,值得注意的是esp-01s通過(guò)wifi信號(hào)連接云平臺(tái),所以環(huán)境中必須要有WiFi,由于此處程序過(guò)多,僅展示重要的地方。
①云平臺(tái)定義及主題相關(guān)定義見程序3:
程序3:
#include <ESP8266WiFi.h>
#include<SimpleDHT.h>
//巴法云服務(wù)器地址
#define TCP_SERVER_ADDR "bemfa.com"
//服務(wù)器端口,tcp創(chuàng)客云端口8344
#define TCP_SERVER_PORT "8344"
//********************需要修改的部分*******************//
#define DEFAULT_STASSID "HUAWEI P30 Pro+" //WIFI名稱,區(qū)分大小寫,不要寫錯(cuò)
#define DEFAULT_STAPSW "18253858772" //WIFI密碼
String UID = "23f9a5f2d3584dc8516409db14b4827c"; //用戶私鑰,可在控制臺(tái)獲取,修改為自己的UID
String TOPIC1 ="TD00light"; //主題名字,可在控制臺(tái)新建
String TOPIC2 = "TD00temp"; //用戶私鑰,可在控制臺(tái)獲取,修改為自己的UID
const int LED_Pin = 0; //單片機(jī)LED引腳值,GPIO0引腳
int pinDHT11 = 2;
//**************************************************//
②接下來(lái)是連接服務(wù)器,向服務(wù)器發(fā)送指令cmd=1&uid="+UID+"&topic="+
TOPIC1+"rn,其中的UID與TOPIC1就是程序3中相關(guān)的定義具體程序見程序4。
程序4:
void startTCPClient(){
if(TCPclient.connect(TCP_SERVER_ADDR,atoi(TCP_SERVER_PORT))){ Serial.print("nConnected toserver:");
Serial.printf("%s:%drn",TCP_SERVER_ADDR,atoi(TCP_SERVER_POR T));
String tcpTemp=""; //初始化字符串
tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC1+"rn"; //構(gòu)建訂閱指令
sendtoTCPServer(tcpTemp); //發(fā)送訂閱指令
tcpTemp="";//清空
preTCPConnected = true;
preHeartTick = millis();
TCPclient.setNoDelay(true);
}
else{
Serial.print("Failed connected to server:");
Serial.println(TCP_SERVER_ADDR);
TCPclient.stop();
preTCPConnected = false;
}
preTCPStartTick = millis();
}
③獲取云平臺(tái)傳來(lái)的數(shù)據(jù),并通過(guò)串口傳輸給STM32,具體程序見程序5:
程序5:
if (TCPclient.available()) //若有數(shù)據(jù)傳來(lái)
{
char c =TCPclient.read();
TcpClient_Buff +=c; //數(shù)據(jù)存儲(chǔ)
TcpClient_BuffIndex++;
TcpClient_preTick = millis();
if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1)
{
TcpClient_BuffIndex = MAX_PACKETSIZE-2;
TcpClient_preTick = TcpClient_preTick - 200;
}
preHeartTick = millis();
}
if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200))
{
TCPclient.flush();
Serial.println(TcpClient_Buff); //串口傳輸
if((TcpClient_Buff.indexOf("&msg=11") > 0))
{
turnOnLed();
}else if((TcpClient_Buff.indexOf("&msg=10") > 0))
{
turnOffLed();
}
TcpClient_Buff="";
TcpClient_BuffIndex = 0;
}
如此就可以將云平臺(tái)中的控制指令傳輸給STM32,STM32進(jìn)行解析并完成相應(yīng)的控制,由于本設(shè)計(jì)還添加了語(yǔ)音識(shí)別功能,所以相關(guān)控制的實(shí)現(xiàn)等講解完語(yǔ)音識(shí)別后在進(jìn)行講解。
4.4語(yǔ)音識(shí)別功能
語(yǔ)音識(shí)別功能主要采用了SU-03T離線語(yǔ)音識(shí)別模塊,這個(gè)模塊不需要編程,使用廠家提供的云平臺(tái)開發(fā),正如前文所說(shuō)本設(shè)計(jì)主要用了該模塊的串口功能,該模塊的串口與STM32單片機(jī)的另一個(gè)串口連接,當(dāng)識(shí)別到相應(yīng)的語(yǔ)音時(shí),串口輸出相應(yīng)的控制指令給STM32。該模塊相關(guān)配置如圖10所示。
圖10 su-03t平臺(tái)配置
4.5、STM32解析指令并完成相關(guān)驅(qū)動(dòng)
正如前文所說(shuō),WiFi模塊與su-03t都是使用串口與STM32單片機(jī)建立聯(lián)系的,所以我們首先需要完成串口的相關(guān)配置,在此以WiFi模塊對(duì)應(yīng)的usart3為例,配置串口,具體程序見程序5:
程序5:
void usart3_init(u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/***********使能時(shí)鐘************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
USART_DeInit(USART3); //復(fù)位串口3
/*******配置輸出引腳*******/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
/*******配置輸入引腳*******/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11
/********串口相關(guān)配置********/
USART_InitStructure.USART_BaudRate = bound;//波特率一般設(shè)置為9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長(zhǎng)為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無(wú)奇偶校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無(wú)硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure); //初始化串口3
USART_Cmd(USART3, ENABLE); //使能串口
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//開啟中斷
/*******設(shè)置中斷優(yōu)先級(jí)********/
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//搶占優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
TIM3_Int_Init(1000-1,7200-1); //10ms中斷
USART3_RX_STA=0; //清零
TIM_Cmd(TIM3,DISABLE); //關(guān)閉定時(shí)器7
}
至此WiFi模塊對(duì)應(yīng)的串口就配置完成,su-0t對(duì)應(yīng)的串口配置與該串口相似,WiFi模塊傳輸來(lái)的數(shù)據(jù)是需要解析的,而su-03t直接傳輸?shù)氖M(jìn)制,不需要解析,所以接下來(lái)就是解析WiFi模塊通過(guò)串口傳來(lái)的數(shù)據(jù),具體程序見程序6。
程序6:
if(USART3_RX_STA&0X8000) //接收到一次數(shù)據(jù)了
{
rlen=USART3_RX_STA&0X7FFF; //得到本次接收到的數(shù)據(jù)長(zhǎng)度
USART3_RX_BUF[rlen]=0; //添加結(jié)束符
//數(shù)據(jù)提取
if(strncmp(USART3_RX_BUF,"cmd=2",5)==0)
{
for(i=0;i<strlen(USART3_RX_BUF)+1;i++)
{
data_tiqu[s]=USART3_RX_BUF[i];
s++;
}
printf("%s",data_tiqu);
for(i=0;i<strlen(data_tiqu);i++)
{
if(data_tiqu[i]==cmd[0])
{
k=i;
k++;
for(j=1;j<strlen(cmd);j++)
{
if(data_tiqu[k]==cmd[j])
{
k++;
flag=1;
}
else
{
flag=0;
}
}
}
}
s=0;
//數(shù)據(jù)提取結(jié)束
printf("rnrn");
if(flag==1)
{
for(i=k+1;i<strlen(data_tiqu)+1;i++) //此時(shí) i為傳輸接受數(shù)據(jù)的索引
{
data[s]=data_tiqu[i];
s++;
}
printf("%s",data);
printf("zaici"); //作用:程序定位
printf("rn");
}
}
if(strncmp(USART3_RX_BUF,"cmd=0&res=1",11)==0)
{
printf("%s",USART3_RX_BUF);
}
USART3_RX_STA=0;
}
解析好的數(shù)據(jù)就存放在data這個(gè)數(shù)組中,接下來(lái)就在主循環(huán)中判斷data數(shù)組中存放的數(shù)據(jù)以及su-03t通過(guò)串口直接傳來(lái)的十六進(jìn)制指令即可,根據(jù)相應(yīng)的指令完成相關(guān)外設(shè)的驅(qū)動(dòng),具體程序見程序7。
程序7:
/******************驅(qū)動(dòng)控制**************************/
//判斷APP控制開關(guān)燈
if((data[0]=='1'&&data[1]=='1') || (temp == 0x11))
{
GPIO_SetBits(LED0_PORT,LED0_PIN); //開LED0
GPIO_ResetBits(LED1_PORT,LED1_PIN); //關(guān)LED1
TIM_SetCompare3(TIM4,800); //兩端都使能 1檔
TIM_SetCompare4(TIM4,800);
temp=0;
state_flag_temp=11;
state_flag[0]=1; //冷亮
state_flag[2]=1; //一檔
display_on[5] = 24; //已為您打開燈(oled顯示的漢字在數(shù)組中的索引)
display_on[6] = 0; //已為您打開燈(oled顯示的漢字在數(shù)組中的索引)
}
if((data[0]=='1'&&data[1]=='0') || (temp == 0x10))
{
GPIO_ResetBits(LED0_PORT,LED0_PIN); //關(guān)LED0
GPIO_ResetBits(LED1_PORT,LED1_PIN); //關(guān)LED1
temp=0;
state_flag_temp=10;
state_flag[0]=0;
state_flag[1]=0;
state_flag[2]=0;
display_off[5] = 24;
display_off[6] = 0;
}
//判斷APP控制冷暖光調(diào)節(jié)
if((data[0]=='2'&&data[1]=='1') || (temp == 0x21)) //冷亮暖滅
{
GPIO_SetBits(LED0_PORT,LED0_PIN); //IN1—開冷光LED0
GPIO_ResetBits(LED1_PORT,LED1_PIN); //IN3—關(guān)暖光LED1
temp=0;
state_flag_temp=21;
state_flag[0]=1; //冷亮
state_flag[1]=0; //暖滅
display_on[5] = 26;
display_on[6] = 25;
}
if((data[0]=='2'&&data[1]=='2') || (temp == 0x22)) //冷滅暖亮
{
GPIO_ResetBits(LED0_PORT,LED0_PIN); //IN1—關(guān)冷光LED0
GPIO_SetBits(LED1_PORT,LED1_PIN); //IN3—開暖光LED1
temp=0;
state_flag_temp=22;
state_flag[0]=0; //冷滅
state_flag[1]=1; //暖亮
display_on[5] = 27;
display_on[6] = 25;
}
//判斷APP控制1、2、3檔位
if((data[0]=='3'&&data[1]=='1')|| (temp == 0x31)) //1檔
{
TIM_SetCompare3(TIM4,800); //兩端都使能 1檔
TIM_SetCompare4(TIM4,800);
temp=0;
state_flag_temp=31;
state_flag[2]=1; //一檔
display_now[5] = 37;
}
if((data[0]=='3'&&data[1]=='2')|| (temp == 0x32)) //2檔
{
TIM_SetCompare3(TIM4,2000); //兩端都使能 2檔
TIM_SetCompare4(TIM4,2000);
temp=0;
state_flag_temp=32;
state_flag[2]=2; //二檔
display_now[5] = 38;
}
if((data[0]=='3'&&data[1]=='3')|| (temp == 0x33)) //3檔
{
TIM_SetCompare3(TIM4,5000); //兩端都使能 3檔
TIM_SetCompare4(TIM4,5000);
temp=0;
state_flag_temp=33;
state_flag[2]=3; //三檔
display_now[5] = 39;
}
至此臺(tái)燈的控制功能已經(jīng)全部開發(fā)完畢,已經(jīng)實(shí)現(xiàn)了APP遠(yuǎn)程控制、語(yǔ)音控制功能。
4.6、超聲波識(shí)別坐姿
還記得在第二章節(jié)所介紹的超聲波模塊HC-SR04,該模塊主要是用于把該系統(tǒng)做成臺(tái)燈時(shí)使用,用于檢測(cè)坐姿規(guī)范的,若是開發(fā)家里的照明燈,可不加該模塊。該模塊實(shí)現(xiàn)測(cè)距的主要原理是:****裝置****超聲波,同時(shí)打開定時(shí)器,超聲波遇到障礙物反彈,被接收裝置接受,此時(shí)獲取定時(shí)器的時(shí)間,然后根據(jù)速度計(jì)算距離。其坐姿判斷邏輯如下:
HC-SR04測(cè)距低于閾值→坐姿不對(duì),距離桌面過(guò)近→蜂鳴器報(bào)警
HC-SR04測(cè)距高于閾值→坐姿正確,距離桌面適宜→蜂鳴器正常
具體程序見程序8:
程序8:
//一次獲取超聲波測(cè)距數(shù)據(jù) 兩次測(cè)距之間需要相隔一段時(shí)間,隔斷回響信號(hào)
//為了消除余震的影響,取五次數(shù)據(jù)的平均值進(jìn)行加權(quán)濾波。
float Hcsr04GetLength(void )
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
TRIG_Send = 1; //發(fā)送口高電平輸出
Delay_Us(20);
TRIG_Send = 0;
while(ECHO_Reci == 0); //等待接收口高電平輸出
OpenTimerForHc(); //打開定時(shí)器
i = i + 1;
while(ECHO_Reci == 1);
CloseTimerForHc(); //關(guān)閉定時(shí)器
t = GetEchoTimer(); //獲取時(shí)間,分辨率為1US
lengthTemp = ((float)t/58.0);//cm
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
Hcsr_num++;
if(Hcsr_num == 5)
{
Hcsr_num = 0;
length_C = Hcsr04GetLength(); //測(cè)距離
printf("距離為:%.3frn",length_C);
if(length_C < 20)
{
state_flag[3] =1;
BEEP =~ BEEP;
delay_ms(300);
}
else
{
state_flag[3] =0;
BEEP = 0;
}
if(Hcsr_flag != state_flag[3])
{
Hcsr_flag = state_flag[3];
display_all_flag=1;
}
}
4.7、OLED屏顯示狀態(tài)
本文第二章也介紹了一個(gè)OLED模塊,以及展示了相關(guān)顯示圖片,這部分實(shí)現(xiàn)的原理是,在上方介紹相關(guān)控制功能時(shí)會(huì)更改相應(yīng)的標(biāo)志位,然后在主程序中檢查該標(biāo)志位的狀態(tài),當(dāng)標(biāo)志位發(fā)生改變時(shí),修改OLED屏幕的顯示,具體程序見程序9。
程序9:
switch(Dis_mode)
{
case 0: //在顯示控制狀態(tài)界面
switch(state_flag_temp) //定時(shí)顯示界面
{
case 11:control_part_display(2,6,display_1,display_on);break; //顯示“以為您打開燈”
case 10:control_part_display(2,6,display_1,display_off);break; //顯示“以為您關(guān)閉燈”
case 21:control_part_display(1,7,display_1,display_on);break; //顯示“以為您打開冷燈”
case 22:control_part_display(1,7,display_1,display_on);break; //顯示“以為您打開暖燈”
case 31:control_part_display(1,7,display_1,display_now);break; //顯示“當(dāng)前亮度為一檔”
case 32:control_part_display(1,7,display_1,display_now);break; //顯示“當(dāng)前亮度為二檔”
case 33:control_part_display(1,7,display_1,display_now);break; //顯示“當(dāng)前亮度為三檔”
}
data[0]='0'; //清空控制指令
data[1]='0';
state_flag_temp=0;
if(display_all_flag) //狀態(tài)整體顯示界面
{
display_all_flag=0;
control_all_display(state_flag);
TIM_Cmd(TIM2,DISABLE); //關(guān)閉TIM2定時(shí)器
}
break;
case 1: //在始終顯示界面
RTC_Display(); //顯示時(shí)鐘
break;
至此,智能燈光系統(tǒng)的相關(guān)功能已全部開發(fā)完畢,給電路板接上電源后,可使用APP控制、語(yǔ)音控制兩種方式,實(shí)現(xiàn)燈光的開關(guān)、一檔二檔三檔的的調(diào)節(jié)、冷暖光的調(diào)節(jié)、以及姿勢(shì)糾正等功能。
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。