博客專欄

        EEPW首頁 > 博客 > 基于STM32的智能燈光控制系統

        基于STM32的智能燈光控制系統

        發布人:霄耀在努力 時間:2022-11-18 來源:工程師 發布文章

        基于STM32的智能燈光控制系統

        一、題目背景和意義:

        隨著社會不斷進步市場在不斷變化,高科技應用含量決定著產品發展的新趨勢和前景,智能化技術在電子產品領域的應用意義深遠。隨著電子產品的快速發展,家用電器也越來越偏向智能化,本文介紹一款基于STM32的智能光照燈。

        回想一下,日常生活中使用燈光時是否有以下情景“老公關一下燈、老公幫我開一下燈,我夠不著”、“石頭剪刀布,誰輸了誰去關燈”、“以及寢室中住在最邊上負責開關燈的同學..........由于我就是這個位置,深有感受啊!!!”。照明燈已是千家萬戶的必需生活用品,但每次要去開關燈的時候總是千難萬阻,基于此,本項目研發了一款智能燈光系統,具備手機app控制燈光、語音控制等功能,更加方便快捷,徹底解決住在下鋪兄弟的煩惱,哈哈哈哈。

         

        二、項目整體展示:

        智能光照燈”使用STM32作為系統的MCU,由于單片機IO口驅動電流過小,搭配三極管放大電流從而滿足光照強度需求,且將單片機IO配置成PWM輸出,以便于調節不同的光強度,也就是一檔、二檔、三檔。在此基礎上增加WiFi模塊搭配手機APP可實現在手機端控制燈光使用su-03t語音識別模塊可實現語音控制燈光等,其他額外功能在下文介紹。所需材料如表1所示。

        1 材料清單

        序號

        名稱

        數量

        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

         

         

        項目整體展示如圖1

        image.png 

        1 項目整體展示

         

        三、主要電子模塊介紹:

        1、STM32核心板:

        STM32是“意法半導體”生產的基于“ARM公司Cortex-M3內核”的32位MCU,其性能強大,資源豐富,被廣泛應用于嵌入式系統的開發,也是高校學生接觸嵌入式的敲門磚。最小系統板如圖2所示,其由處理器、電源、復位、晶振電路等組成,可獨立的完成相應的控制任務,在本次工程中核心知識就是PWM輸出,I/O口引腳電平判斷。

        image.png

        2  STM32最小系統板

        2、三極管:

        三極管的放大作用就是:集電極電流受基極電流的控制(假設電源能夠提供給集電極足夠大的電流的話),并且基極電流很小的變化,會引起集電極電流很大的變化,且變化滿足一定的比例關系:集電極電流的變化量是基極電流變化量的β倍,即電流變化被放大了β倍至于三極管的控制,如圖3所示及其簡單,在圖片中所標的A引腳初,輸出高電平就能導通三極管,上方VCC的電源就能流過三極管。

        image.png

        3 三極管內部電路

        3、WiFi模塊:

        本項目所使用的WiFi模塊是ESP-01S,是ESP8266系列的一種,其可以連接環境中的WiFi,從而使設備上網。本項目主要使用了該模塊串口功能,通過串口與stm32單片機連接,WiFi模塊通過周圍環境中的WiFi信號連接云平臺,如此將WiFi模塊作為中介,可以實現單片機與云平臺的信息交互。WiFi模塊與單片機連接引腳如圖4:

        image.png

        4  WiFi模塊連接圖

        4、su-03t語音識別模塊:

        su-03t是一款低成本、低功耗、小體積的離線語音識別的模組,無需編程,使用刷詞條的方式進行開發,可謂是不愛編程的福音啊。本項目使用該模塊的串口功能,通俗一點講就是模塊識別到相應的語音命令后,通過串口輸出一個數據。關于該模塊的配置,本文再次不過多闡述。該模塊引腳如圖5所示:

        image.png

        5  SU-03T引腳展示圖

         

        5、超聲波模塊:

        超聲波模塊為HC-SR04如圖6所示超聲波測距模塊可提供約2cm~400厘米的非接觸式距離感測功能,測距精度可達高到3毫米該模塊由****裝置與接受裝置組成,****裝置****超聲波,接受裝置接受超聲波并將電平做出相應轉變。

        image.png

        6 超聲波模塊

        6、OLED

        OLED顯示屏是利用有機電自發光二極管制成的顯示屏。由于同時具備自發光有機電激發光二極管,不需背光源、對比度高、厚度薄、視角廣、反應速度快、LCD屏幕顯示效果更好一些,但由于現有技術限制,目前OLED屏幕無法做的很大。本項目主要使用OLED屏幕顯示臺燈的當前狀態、溫濕度信息、以及萬年歷時鐘燈,相關顯示如圖7所示。

        image.png  image.png  image.png

        7 相關顯示結果

         

        四、項目制作

        4.1、先讓燈亮起來

        正如章節3中所說,燈帶是通過三極管驅動的,單片機的IO口連接三極管基極,可以將其看成控制信號,當該引腳輸出高電平時,可以認為三極管導通,電流由****極提供,由集電極輸出,本設計中****極連接VCC,也就是用電源給等待供電,這個電流遠大于IO口直接輸出的電流,足以滿足等待的需求。

        4.2、調節燈光亮度

        剛剛已經介紹過如何使用三極管點亮燈帶。那么又該如何控制燈的亮度哪?也就是如何控制電流呢?這就需要常說的PWM輸出了,可以將三極管看成一個“水龍頭”,PWM可以理解為我們擰水龍頭的力氣,通過調節不同的占空比,使得三極管“打開不同的口子”,控制邏輯如下:

        PWM占空比大→“打開的口子大”→輸出的電流大→燈帶更亮

        PWM占空比小→“打開的口子小”→輸出的電流小→燈帶更暗

        在程序中首先將IO口配置為PWM輸出,本設計選用的定時器4的通道3與通道4產生PWM(兩個燈,一個冷光一個暖光,需要兩路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); //使能定時器4時鐘

             RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外設和AFIO復用功能模塊時鐘

            

             

               /*****輸出TIM4_CH3TIM4_CH4和的PWM脈沖波形*****/

            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //TIM_CH3TIM_CH4

            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //復用推挽輸出

            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

            GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

             

               /********************初始化TIM3*******************/

            TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值

            TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值

            TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鐘分割:TDTS = Tck_tim

            TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計數模式

            TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位

            

            /*******初始化TIM4 Channel3TIM4 Channel4 PWM模式********/  

            TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時器模式:TIM脈沖寬度調制模式2

              TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能

            TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性:TIM輸出比較極性高

            TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //初始化外設TIM4 OC3

            TIM_OC4Init(TIM4, &TIM_OCInitStructure);  //初始化外設TIM4 OC4

             

               /*******使能預裝載寄存器********/

            TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);  

            TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);  

             

            TIM_Cmd(TIM4, ENABLE);  //使能TIM4

        }

        如此PWM的輸出就已經配置好了,下面就在主循環中調用修改PWM占空比函數即可,具體程序見程序2,該程序修改了三個不同的占空比,以對應燈光的一檔、二檔、三檔。

        程序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、遠程控制功能

        正如上文所說,遠程控制功能實現的原理是,手機app開發時連接上云平臺,手機APP相應按鍵觸發時,將相應的控制指令上傳至云平臺,esp-01s通過周圍的WiFi信號連接云平臺,獲取云平臺上的數據,并通過串口將該數據傳輸給STM32單片機,單片機解析數據并完成相應的驅動。接下來就分布實現開發,分為手機端app的制作,手機連接云平臺、設備連接云平臺。

        4.3.1手機端app的制作

        本項目使用一款麻省理工研發的開發安卓app的平臺——appinventor該平臺基于圖形化編程,是不愿意編程黨的福音,不需要使用代碼開發app,使用一些邏輯關系模塊完成開發。首先在主頁面拖放好各種想要的按鍵,之后再編程界面拖放邏輯關系模塊,完成開發(與labview相似)。

        4.3.2手機端連接云平臺

        在使用appinventor開發的過程中,調用連接云平臺接口,連接云平臺,博主使用的是巴法云平臺,再巴法云官網有詳細的教程。打開巴法云官網其界面如圖8所示,點擊圖片中所圈的地方“實例指南”進入八法開放論壇,之后在論壇中找到“APP inventor編寫安卓app控制ESP8266”這篇文章,如圖9所示,里面有詳細的制作過程。

        image.png 

        8 巴法云界面

        image.png 

        9 論壇內容

        額外說一下這個云平臺接口,ClientSocketAI2Ext,這個不是appinventor的原生組件,需要再Extension下導自行導入插件。

         

        另外,有想學習appinventor的可以看一下這個博主的網課,我當時就是跟隨這個博主學的,很詳細,很好學,兩天完成。學習鏈接:老巫婆的程序世界的個人空間_嗶哩嗶哩_bilibili

         

        4.3.3設備(單片機)連接云平臺

        esp-01s也是一個MCU,通過編程開發,本設計通過arduino平臺開發相關的功能,值得注意的是esp-01s通過wifi信號連接云平臺,所以環境中必須要有WiFi,由于此處程序過多,僅展示重要的地方。

        ①云平臺定義及主題相關定義見程序3

        程序3

        #include <ESP8266WiFi.h>

        #include<SimpleDHT.h>

         

        //巴法云服務器地址

        #define TCP_SERVER_ADDR "bemfa.com"

        //服務器端口,tcp創客云端口8344

        #define TCP_SERVER_PORT "8344"

         

        //********************需要修改的部分*******************//

        #define DEFAULT_STASSID  "HUAWEI P30 Pro+"     //WIFI名稱,區分大小寫,不要寫錯

        #define DEFAULT_STAPSW   "18253858772"        //WIFI密碼

        String UID = "23f9a5f2d3584dc8516409db14b4827c";  //用戶私鑰,可在控制臺獲取,修改為自己的UID

        String TOPIC1 ="TD00light";         //主題名字,可在控制臺新建

        String TOPIC2 = "TD00temp";       //用戶私鑰,可在控制臺獲取,修改為自己的UID

        const int LED_Pin = 0;              //單片機LED引腳值,GPIO0引腳

        int pinDHT11 = 2;

        //**************************************************//

         

        ②接下來是連接服務器,向服務器發送指令cmd=1&uid="+UID+"&topic="+

        TOPIC1+"rn,其中的UIDTOPIC1就是程序3中相關的定義具體程序見程序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"; //構建訂閱指令

            sendtoTCPServer(tcpTemp); //發送訂閱指令

            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();

        }

         

        ③獲取云平臺傳來的數據,并通過串口傳輸給STM32,具體程序見程序5

        程序5

        if (TCPclient.available()) //若有數據傳來

        {

           char c =TCPclient.read();

           TcpClient_Buff +=c;        //數據存儲

           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;

          }

        如此就可以將云平臺中的控制指令傳輸給STM32STM32進行解析并完成相應的控制,由于本設計還添加了語音識別功能,所以相關控制的實現等講解完語音識別后在進行講解。

         

        4.4語音識別功能

        語音識別功能主要采用了SU-03T離線語音識別模塊,這個模塊不需要編程,使用廠家提供的云平臺開發,正如前文所說本設計主要用了該模塊的串口功能,該模塊的串口與STM32單片機的另一個串口連接,當識別到相應的語音時,串口輸出相應的控制指令給STM32。該模塊相關配置如圖10所示。

        image.png 

        10 su-03t平臺配置

         

        4.5STM32解析指令并完成相關驅動

        正如前文所說,WiFi模塊與su-03t都是使用串口與STM32單片機建立聯系的,所以我們首先需要完成串口的相關配置,在此以WiFi模塊對應的usart3為例,配置串口,具體程序見程序5

        程序5  

        void usart3_init(u32 bound)

        {  

        NVIC_InitTypeDef NVIC_InitStructure;

            GPIO_InitTypeDef GPIO_InitStructure;

            USART_InitTypeDef USART_InitStructure;

         

        /***********使能時鐘************/

            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                                          RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);

            USART_DeInit(USART3);  //復位串口3

         

        /*******配置輸出引腳*******/

           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10

           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出

           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


        /********串口相關配置********/

            USART_InitStructure.USART_BaudRate = bound;//波特率一般設置為9600

            USART_InitStructure.USART_WordLength = USART_WordLength_8b//字長為8位數據格式

            USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位

            USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位

           USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數據流控制

            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);//開啟中斷   


        /*******設置中斷優先級********/

            NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

            NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//搶占優先級3

            NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //子優先級3

            NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

            NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化VIC寄存器


            TIM3_Int_Init(1000-1,7200-1);  //10ms中斷

            USART3_RX_STA=0;         //清零

            TIM_Cmd(TIM3,DISABLE);   //關閉定時器7

        }

        至此WiFi模塊對應的串口就配置完成,su-0t對應的串口配置與該串口相似,WiFi模塊傳輸來的數據是需要解析的,而su-03t直接傳輸的十六進制,不需要解析,所以接下來就是解析WiFi模塊通過串口傳來的數據,具體程序見程序6

        程序6

        if(USART3_RX_STA&0X8000)  //接收到一次數據了

        {

            rlen=USART3_RX_STA&0X7FFF; //得到本次接收到的數據長度

            USART3_RX_BUF[rlen]=0;  //添加結束符

             

            //數據提取

            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;

            //數據提取結束

            printf("rnrn");

            if(flag==1)

            {

                for(i=k+1;i<strlen(data_tiqu)+1;i++) //此時 i為傳輸接受數據的索引

                {

                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;

        }

        解析好的數據就存放在data這個數組中,接下來就在主循環中判斷data數組中存放的數據以及su-03t通過串口直接傳來的十六進制指令即可,根據相應的指令完成相關外設的驅動,具體程序見程序7

        程序7

        /******************驅動控制**************************/

        //判斷APP控制開關燈

        if((data[0]=='1'&&data[1]=='1') || (temp == 0x11))

        {

            GPIO_SetBits(LED0_PORT,LED0_PIN);   //LED0

            GPIO_ResetBits(LED1_PORT,LED1_PIN); //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顯示的漢字在數組中的索引)

            display_on[6] = 0;      //已為您打開燈(oled顯示的漢字在數組中的索引)

        }

        if((data[0]=='1'&&data[1]=='0') || (temp == 0x10))

        {

            GPIO_ResetBits(LED0_PORT,LED0_PIN); //LED0

            GPIO_ResetBits(LED1_PORT,LED1_PIN); //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控制冷暖光調節

        if((data[0]=='2'&&data[1]=='1') || (temp == 0x21)) //冷亮暖滅

        {

            GPIO_SetBits(LED0_PORT,LED0_PIN); //IN1—開冷光LED0

            GPIO_ResetBits(LED1_PORT,LED1_PIN); //IN3—關暖光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—關冷光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控制123檔位

        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;

        }

        至此臺燈的控制功能已經全部開發完畢,已經實現了APP遠程控制、語音控制功能。

         

        4.6、超聲波識別坐姿

        還記得在第二章節所介紹的超聲波模塊HC-SR04,該模塊主要是用于把該系統做成臺燈時使用,用于檢測坐姿規范的,若是開發家里的照明燈,可不加該模塊。該模塊實現測距的主要原理是:****裝置****超聲波,同時打開定時器,超聲波遇到障礙物反彈,被接收裝置接受,此時獲取定時器的時間,然后根據速度計算距離。其坐姿判斷邏輯如下:

        HC-SR04測距低于閾值→坐姿不對,距離桌面過近→蜂鳴器報警

        HC-SR04測距高于閾值→坐姿正確,距離桌面適宜→蜂鳴器正常

        具體程序見程序8

        程序8

        //一次獲取超聲波測距數據 兩次測距之間需要相隔一段時間,隔斷回響信號

        //為了消除余震的影響,取五次數據的平均值進行加權濾波。

        float Hcsr04GetLength(void )

        {

            u32 t = 0;

            int i = 0;

            float lengthTemp = 0;

            float sum = 0;

            while(i!=5)

            {

                TRIG_Send = 1;      //發送口高電平輸出

                Delay_Us(20);

                TRIG_Send = 0;

                while(ECHO_Reci == 0);      //等待接收口高電平輸出

                OpenTimerForHc();        //打開定時器

                i = i + 1;

                while(ECHO_Reci == 1);

                CloseTimerForHc();        //關閉定時器

                t = GetEchoTimer();        //獲取時間,分辨率為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();                 //測距離

            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.7OLED屏顯示狀態

        本文第二章也介紹了一個OLED模塊,以及展示了相關顯示圖片,這部分實現的原理是,在上方介紹相關控制功能時會更改相應的標志位,然后在主程序中檢查該標志位的狀態,當標志位發生改變時,修改OLED屏幕的顯示,具體程序見程序9

        程序9

        switch(Dis_mode)

        {

            case 0:              //在顯示控制狀態界面

            switch(state_flag_temp)     //定時顯示界面

            {

                case 11:control_part_display(2,6,display_1,display_on);break;      //顯示以為您打開燈

                case 10:control_part_display(2,6,display_1,display_off);break;     //顯示以為您關閉燈

                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;     //顯示當前亮度為一檔

                case 32:control_part_display(1,7,display_1,display_now);break;     //顯示當前亮度為二檔

                case 33:control_part_display(1,7,display_1,display_now);break;     //顯示當前亮度為三檔

            }

            data[0]='0';               //清空控制指令

            data[1]='0';

            state_flag_temp=0;

            if(display_all_flag)       //狀態整體顯示界面

            {

                display_all_flag=0;

                control_all_display(state_flag);

                TIM_Cmd(TIM2,DISABLE);      //關閉TIM2定時器

            }

            break;

             

            case 1:          //始終顯示界面

                RTC_Display();        //顯示時鐘

            break;

         

        至此,智能燈光系統的相關功能已全部開發完畢,給電路板接上電源后,可使用APP控制、語音控制兩種方式,實現燈光的開關、一檔二檔三檔的的調節、冷暖光的調節、以及姿勢糾正等功能。

        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。




        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 临湘市| 金堂县| 大田县| 昌吉市| 高唐县| 道真| 德安县| 区。| 永城市| 广安市| 富民县| 白河县| 尉犁县| 合山市| 邛崃市| 济宁市| 师宗县| 大竹县| 南川市| 利津县| 泗阳县| 鸡东县| 民和| 开阳县| 辽源市| 临泽县| 台山市| 潞城市| 丁青县| 龙井市| 江陵县| 普洱| 松江区| 沙坪坝区| 湖州市| 昌乐县| 义马市| 石泉县| 泸水县| 堆龙德庆县| 横峰县|