程序員為女友DIY一款紅外線遙控器,感動哭了
身為一位資深電子發(fā)燒友,他經(jīng)常自己動手將家中傳統(tǒng)電器改造成智能電器。此次,該同學(xué)基于涂鴉 IoT 開發(fā)工具,使用涂鴉 WBR1D 云模組、紅外遙控器外殼等器材,借助涂鴉智能紅外遙控開源硬件開發(fā)資料,將家中空調(diào)改造成智能空調(diào),可通過手機(jī) App 輕松控制。
以下內(nèi)容為涂鴉開發(fā)者“李勇”創(chuàng)作,經(jīng)其授權(quán)編輯發(fā)布:
參加此次涂鴉智能&立創(chuàng)EDA實戰(zhàn)訓(xùn)練營,要求做物聯(lián)網(wǎng)相關(guān)項目,使用涂鴉的云模組。一提到云,我最先想到的是智能家居,自己平時工作之余,也做了不少與物聯(lián)網(wǎng)相關(guān)的項目,做的大大小小的項目不少,家里電器差不多都自己動手改造成智能的。
正好最近有做紅外遙控空調(diào)的想法。冬天來了,早上起床太早都不敢掀被子(太冷),一直想改造成智能的,用手機(jī)控制,支持定時開啟/關(guān)閉,智能場景聯(lián)動。加上工作原因,有涂鴉智能的云開發(fā)需求,所以參加此次訓(xùn)練營。
功能設(shè)計
要實現(xiàn)空調(diào)控制,就是要發(fā)送紅外信號,所以要有紅外發(fā)送功能。市面上空調(diào)種類繁多,肯定要適用多種品牌和機(jī)型,所以要有紅外學(xué)習(xí)功能。要支持場景聯(lián)動,就要有環(huán)境感知傳感器。要支持手機(jī)控制,就要有云端和模組。
綜上,設(shè)計功能有:
1、紅外發(fā)送(紅外****管);
2、紅外學(xué)習(xí)(一體化接收頭);
3、室內(nèi)溫度檢測(DHT11);
4、手機(jī)控制(通過涂鴉云模組實現(xiàn))。
成品效果
在實際場景中,空調(diào)的安裝位置一般都不固定,所以,紅外控制器不能近距離控制。參考其他大品牌紅外控制器設(shè)計,采用壁掛式設(shè)計,可以掛在天花板或墻壁上。
控制板全部用立創(chuàng)EDA繪制,自己手工貼片,涂鴉云模組上面的文字是被清洗劑洗掉了,操作時大意了。
使用的公模外殼,安裝效果如下。
硬件設(shè)計
1.電源
電源部分采用Micro USB接口,直接提供5V電源,經(jīng)過內(nèi)部分壓得到3.3V電壓,為MCU、涂鴉云模組和外圍電路供電。降壓采用TI的TLV62569DBVR電源芯片,外圍器件少,功率大,紋波小。
2.云模組
采用涂鴉智能提供的WBR1D-IPEX云模組,WBR1D是雙頻雙模模組,支持WI-FI和藍(lán)牙,采用MCU接入方案,通過串口與MCU連接。
3.MCU
MCU采用ST的STM32F103C8T6,64K的Flash。
4.紅外****
紅外****采用紅外管,因為是壁掛式安裝方式,所以對控制范圍有要求,本設(shè)計中采用8顆紅外****管并聯(lián),每科管子由一顆大功率三極管驅(qū)動,所有三極管由一個控制端驅(qū)動。以提高****功率,提高****功率后,紅外控制范圍會明顯擴(kuò)大。(多顆紅外管最好并聯(lián)控制,不要為畫PCB方便或者節(jié)省器件而選擇串聯(lián),串聯(lián)的管子都不會正常工作,****功率會大幅度下降。)
5.紅外接收
紅外接收比較簡單,直接采用一體化接收頭。
6.附加電路
按鍵
按鍵用于配網(wǎng)使用,但是在實際調(diào)試時,模組會自動配網(wǎng),所以按鍵改為清除紅外預(yù)存的數(shù)據(jù)。
LED
LED用于指示配網(wǎng)狀態(tài)和進(jìn)入紅外學(xué)習(xí)模式,以及故障閃爍。
DHT11
DHT11用于檢測室內(nèi)溫濕度,在本設(shè)計中,紅外遙控器作為單品使用,DHT11可以向云端上報室內(nèi)溫度、濕度,可實現(xiàn)智能場景聯(lián)動。
7.PCB設(shè)計
PCB設(shè)計時,因為是壁掛式,所以選了一個公模外殼。在設(shè)計時器件布局和PCB外形要符合外殼尺寸。
外殼:
PCB:初版PCB有幾個錯誤,按鍵位置與LED位置反了,絲印錯誤,已經(jīng)更新。
軟件設(shè)計
1.紅外接收實現(xiàn)
紅外接收比較簡單,如果是易于解析的NEC格式編碼,直接用定時器捕獲外部輸入電平時間長度即可,對于不易解析的編碼(廠家自定義的編碼)采用外部中斷和定時器方式測電平時間長度。對于NEC格式編碼,按照NEC編碼格式的規(guī)范,先判斷低電平時間,通過長度區(qū)分起始碼、數(shù)據(jù)碼和結(jié)束碼。網(wǎng)上例程比較多,這里就不贅述了,要注意的是:有的廠家空調(diào)雖然是NEC編碼,但是他們的編碼中高低電平長度一般都不同,所以在中斷中判斷電平長度時,要注意設(shè)置范圍。
2.紅外****實現(xiàn)
紅外****是紅外管完成,注意:紅外管不****紅外在接收端輸出1,****紅外在接收端輸出是0,這里要注意區(qū)分。
實現(xiàn)方式用定時器輸出一個38K的方波,控制方波輸出的時間長度即可實現(xiàn)發(fā)送不同的數(shù)據(jù)和編碼。本項目采用兩個定時器來實現(xiàn)發(fā)送紅外,TIM1輸出38K載波,TIM3定時,由TIM3計時,控制TIM1輸出/關(guān)閉PWM,這樣可以實現(xiàn)任意時間長度發(fā)送。但是這樣比較耗費MCU資源,對于STM32來說,影響不大,對于小型MCU就要考慮資源了。
下面是實現(xiàn)紅外發(fā)送的關(guān)鍵代碼:
發(fā)送一組完整紅外編碼Inf_RX_NECcoding()
void Inf_RX_NECcoding(uint8_t *pbuff,uint8_t Length,uint8_t quantity){ uint8_t i; TIM_CtrlPWMOutputs(TIM1,ENABLE); //開輸出 TIM_Cmd(TIM3,ENABLE); //開定時器 TIM_Cmd(TIM1,ENABLE); while(Inf_RX_StartCode()); //起始碼 if(Length>InfraredDataLength) //數(shù)據(jù)有效長度限制 Length = InfraredDataLength; for(i=0;i<Length;i++) //發(fā)送數(shù)據(jù) Inf_RX_Data(pbuff[i],Right); while(Inf_RX_Stop()); //結(jié)束碼 while(Inf_RX_Interval()); //間隔碼 while(Inf_RX_StartCode()); if(Length>InfraredDataLength) Length = InfraredDataLength; for(i=0;i<Length;i++) Inf_RX_Data(pbuff[i],Right); while(Inf_RX_Stop()); for(i=0;i<quantity;i++) //重復(fù)發(fā)送 while(Inf_SendRepeatedly()); TIM_CtrlPWMOutputs(TIM1,DISABLE); //關(guān)輸出 TIM_Cmd(TIM3,DISABLE); //關(guān)定時器 TIM_Cmd(TIM1,DISABLE); }
數(shù)據(jù)發(fā)送(1個8位)
uint8_t Inf_RX_StartCode(void) { if(!retemp) { retemp=1; TimerOclk=0; TIM_SetCompare1(TIM1,1100); //設(shè)置占空比為50% } if(TimerOclk==441) //低電平時間到 TIM_SetCompare1(TIM1,0); //設(shè)置占空比為0 if(TimerOclk==881) //高電平時間到 { retemp=0; TimerOclk=0; } return retemp; //狀態(tài)返回 }
3.紅外學(xué)習(xí)功能
本項目中只實現(xiàn)NEC編碼紅外學(xué)習(xí),當(dāng)按下手機(jī)端空間時,如果沒有指令,會自動進(jìn)入學(xué)習(xí)狀態(tài),等待發(fā)送紅外指令。紅外指令接收到以后,會自動保存。
4.云功能實現(xiàn)
因為使用涂鴉的MCU接入方案,云端只做功能和APP界面的配置,并下載MCU的SDK,將SDK移植到代碼中即可
云端功能配置:
APP界面配置:
5.防跑飛
在實際測試過程中遇到了,設(shè)備掉線和控制無反應(yīng)問題,起初以為是網(wǎng)絡(luò)問題,更換網(wǎng)絡(luò)以后,問題依舊存在。
拆下板子發(fā)現(xiàn)整個PCB發(fā)燙,測量MCU供電只有接近2V左右,照理說可以正常工作。拔掉電源,重插,MCU供電恢復(fù)。
等待問題再次出現(xiàn)時,測得紅外管驅(qū)動三極管控制端一直是低電平,問題發(fā)現(xiàn)了:8顆紅外****管的****功率比較大,在關(guān)閉輸出時可能是被中斷打斷,導(dǎo)致關(guān)斷不成功,紅外管一直處于發(fā)送狀態(tài),時間一長,8顆紅外管總電流增大,提供給MCU的電流減小,出現(xiàn)假死現(xiàn)象。
為了解決這個問題,增加了三道防線,一是每次發(fā)送完成后將輸出和定時器一起關(guān)閉,這樣可以減少中斷沖突的機(jī)率。二是增加STM32內(nèi)部測溫,一旦檢測到溫度超過允許值,再關(guān)定時器和PWM輸出1次,如果超過警報值,直接復(fù)位MCU。三是增加看門狗,定時喂狗,防止假死和程序跑飛。
加上這三道防線后,實測問題不再發(fā)生。
關(guān)鍵點分析
1.MCU_SDK 移植
涂鴉提供配套的MCU SDK,具體使用方式涂鴉也提供很多的文檔,b站也有很多案例。我們只需要移植到MCU中即可,通過串口通訊,實現(xiàn)MCU接入。注意接涂鴉模組串口的波特率,一般默認(rèn)是9600,也可以修改為115200,具體在云端控制臺的硬件開發(fā)->模組固件中修改。在移植時有以下幾個地方要注意:
**mcu_api.c**
1)串口接收函數(shù)uart_receive_input(),要用中斷法接收,防止數(shù)據(jù)丟包
涂鴉提供串口數(shù)據(jù)接收緩存和數(shù)據(jù)處理方法,我們不需要再單獨去做處理,只需要在串口接收中斷里面調(diào)用uart_receive_input()函數(shù)即可。
//USART2中斷服務(wù)函數(shù)void USART2_IRQHandler(void) { uint8_t value ; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中斷 { value = USART_ReceiveData(USART2); //讀取接收數(shù)據(jù) uart_receive_input(value); //數(shù)據(jù)存入涂鴉緩沖器 } }
2)數(shù)據(jù)輪詢函數(shù)wifi_uart_service(),要輪詢這個函數(shù),不然模組下發(fā)的數(shù)據(jù)MCU接收不到。放在主循環(huán)里面就行。
while (1) { wifi_uart_service(); //輪詢涂鴉數(shù)據(jù) /* 用戶其他函數(shù) */}
3)協(xié)議初始化函數(shù)wifi_protocol_init(),這是為涂鴉串口數(shù)據(jù)提供一個緩存空間,在初始化中調(diào)用,初始化后不需要再調(diào)用。
int main(void){ wifi_protocol_init(); //涂鴉模組協(xié)議初始化 /* 用戶其他初始化函數(shù) */ while(1) { wifi_uart_service(); //輪詢涂鴉數(shù)據(jù) /* 用戶其他函數(shù) */ } }
**protocl.c**
1)串口發(fā)送函數(shù)uart_transmit_output(),用調(diào)用法發(fā)送,也可以用中斷。
涂鴉提供串口發(fā)送數(shù)據(jù)處理方法,我們也不需要再單獨去做處理,只需要將串口發(fā)送語句放在uart_transmit_output()函數(shù)里即可。
void uart_transmit_output(unsigned char value){ while((USART2->SR &(1<<7))==0); USART2->DR = value; }
2)所有數(shù)據(jù)上報函數(shù)all_data_update()
我們要在all_data_update函數(shù)中實現(xiàn)設(shè)備數(shù)據(jù)的傳入,涂鴉模組或向MCU申請返回設(shè)備全部數(shù)據(jù),設(shè)備數(shù)據(jù)通過all_data_update函數(shù)發(fā)送,所以要把設(shè)備的數(shù)據(jù)項傳入到對應(yīng)的函數(shù)中。注意:這個函數(shù)根據(jù)自己云端定義的功能對應(yīng),不能直接添加。
void all_data_update(void) { //此代碼為平臺自動生成,請按照實際數(shù)據(jù)修改每個可下發(fā)可上報函數(shù)和只上報函數(shù) mcu_dp_bool_update(DPID_SWITCH,AirControlStructure.AirPowerControl); //BOOL型數(shù)據(jù)上報; //當(dāng)前開關(guān) mcu_dp_value_update(DPID_TEMP_SET,AirControlStructure.AirRunTemper); //VALUE型數(shù)據(jù)上報; //當(dāng)前溫度設(shè)置 // mcu_dp_value_update(DPID_TEMP_CURRENT,AirControlStructure.AirRunTemper); //VALUE型數(shù)據(jù)上報; //當(dāng)前當(dāng)前溫度 mcu_dp_enum_update(DPID_MODE,AirControlStructure.AirRunMode); //枚舉型數(shù)據(jù)上報; //當(dāng)前工作模式 mcu_dp_enum_update(DPID_FAN_SPEED_ENUM,AirControlStructure.AirRunFan); //枚舉型數(shù)據(jù)上報; //當(dāng)前風(fēng)速 // mcu_dp_enum_update(DPID_STATUS,AirControlStructure.AirRunFlag); //枚舉型數(shù)據(jù)上報; //當(dāng)前狀態(tài) mcu_dp_bool_update(DPID_AUTO,AirControlStructure.AirForceful); //BOOL型數(shù)據(jù)上報; //當(dāng)前自動模式 mcu_dp_bool_update(DPID_HEAT,AirControlStructure.AirHeat); //BOOL型數(shù)據(jù)上報; //當(dāng)前輔熱 }
3)單個數(shù)據(jù)下發(fā)處理函數(shù),在protocl.c中涂鴉定義了與功能對應(yīng)的處理函數(shù),我們要在對應(yīng)函數(shù)中實現(xiàn)控制代碼。示例
static unsigned char dp_download_switch_handle(const unsigned char value[], unsigned short length) //開關(guān){ //示例:當(dāng)前DP類型為BOOL unsigned char ret; //0:關(guān)/1:開 unsigned char switch_1; switch_1 = mcu_get_dp_download_bool(value,length); if(switch_1 == 0) { AirControlStructure.AirPowerControl=OFF;//關(guān) AirControlStructure.AirHeat = OFF; //輔熱關(guān) AirControlStructure.AirForceful = OFF; //強(qiáng)勁關(guān) }else { AirControlStructure.AirPowerControl=ON; //開 } AirControlInfRX(); //發(fā)送紅外代碼 //處理完DP數(shù)據(jù)后應(yīng)有反饋 ret = mcu_dp_bool_update(DPID_SWITCH,switch_1); if(ret == SUCCESS) return SUCCESS; else return ERROR; }
其實MCU接入方案,就是串口通訊。涂鴉提供有SDK,在云端定義好功能,配置好固件和APP面板,下載SDK包,移植到MCU代碼中就可以用,不要單獨做函數(shù)設(shè)置配網(wǎng),上云等繁瑣的工序。這對產(chǎn)品研發(fā)者來講,不管是測試,還是研發(fā),都是非常友好的。
2.空調(diào)控制
以上工作完成后,重點來了,代碼寫得再漂亮,電路設(shè)計再完美,控制不了空調(diào)都等于0。大家都知道空調(diào)是紅外遙控控制,所以本項目就是****空調(diào)遙控器****的紅外編碼,代替遙控器控制空調(diào)。這里的難點在于如何獲得空調(diào)的紅外編碼,目前市面上銷售的空調(diào),紅外編碼都是廠家自定義的。售后或者說明書里面也不會提供具體的編碼協(xié)議,所以只能自己去解析。下面簡述解析過程,解析篇幅較多,詳細(xì)內(nèi)容請移步“閱讀原文”。
首先要獲得紅外的編碼,我的方式是用邏輯分析儀和紅外接收頭,按遙控器的一個鍵,查看分析儀捕獲的波形,通過波形解析出數(shù)據(jù),這個過程不難,但是很繁瑣。
以開機(jī)為例,按下開機(jī)鍵,遙控器發(fā)送一組紅外編碼,邏輯分析儀捕獲到波形,如圖
重復(fù)按下開機(jī)鍵,每次分析儀捕獲的波形都相同,將波形放大后打印,如圖:
這就是完整的一組紅外波形,我只要發(fā)送與這組波形一樣的編碼即可控制空調(diào)開機(jī)。但是現(xiàn)在只是知道了電平變換時間,具體變換的時間長度代表什么還不知道。但是通過這組完整的波形可以看出,它是符合NEC編碼格式(不了解NEC紅外編碼格式的,請先查查相關(guān)資料),只是電平變換時間長度略有不同而已,所以先嘗試用NEC編碼接收程序試一下。通過NEC編碼紅外接收程序測試,發(fā)現(xiàn)能夠接收到數(shù)據(jù):
那么現(xiàn)在直接發(fā)送這組紅外數(shù)據(jù),就能控制空調(diào)開機(jī)。但是實測沒有辦法控制,空調(diào)無反應(yīng)。反過來查看邏輯分析儀捕獲的波形,這個波形與標(biāo)準(zhǔn)NEC編碼的****波形除了高低電平變換時間長度不同,總長度也不同。細(xì)看這個開機(jī)波形,它的前半部分和后半部分是相同,按照NEC格式截取前后半個部分波形,
前半部分:
后半部分:
驚奇的發(fā)現(xiàn)它們的起始碼、數(shù)據(jù)碼是相同的,結(jié)束碼略有不同,由此可以看出,這個紅外編碼是由兩幀構(gòu)成,兩幀之間有一個中間碼,是連接以及第一幀和第二幀用的。將第一幀波形、第二幀波形和完整波形,得到中間碼的波形。
通過邏輯分析儀得出,中間的電平變化時間關(guān)系:
由此,解析出起始碼、數(shù)據(jù)碼、中間碼和結(jié)束碼的電平變化時間間隔,按照解析的接收重新定義紅外發(fā)送函數(shù),測試能正常開機(jī)。
3.App功能配置
App界面除了默認(rèn)功能外,加了部分功能,因為使用的公版APP界面,所以界面UI和功能自定義的范圍有限,后期會改成面板SDK開發(fā),現(xiàn)階段時間不多,做不了開發(fā)。
以強(qiáng)勁功能為例,本項目設(shè)計時,沒有添加強(qiáng)勁功能?,F(xiàn)在要添加,首先進(jìn)入涂鴉IoT開發(fā)平臺,找到項目,進(jìn)入APP面板配置頁面,在頁面點擊“編輯”,
進(jìn)入編輯頁面,先選擇按鈕添加的位置,這里添加到更多頁面
配置好屬性和關(guān)聯(lián)功能以后,點擊發(fā)布,涂鴉會自動打包,打包好了以后,會提供測試二維碼,掃二維碼可以測試這個面板,如果測試通過點正式發(fā)布,發(fā)布以后,手機(jī)端退出“涂鴉智能”APP,重新進(jìn)入,添加的功能就生效。
總結(jié)
這次使用涂鴉智能,不管是整體開發(fā)流程,還是技術(shù)服務(wù),涂鴉做得非常好。
涂鴉模組提供MCU SDK,用戶只需要移植到MCU OS中,即可完成上云操作,節(jié)省研發(fā)和調(diào)試周期。
涂鴉提供的穩(wěn)定MCU接入模組SDK,減少用戶程序邏輯架構(gòu)不嚴(yán)謹(jǐn)造成的錯誤,減輕用戶底層代碼量。
涂鴉技術(shù)支持服務(wù)也非常周到,不定期詢問開發(fā)者是否有問題需要解決,這點比某科模組做的好。
如果想自己親自動手DIY的,可以戳:
https://auth.tuya.com/?_source=7c8653b7bd61bf9239a1a6c12e52124d
還在等什么!為女友DIY創(chuàng)造一個溫暖舒適的家居生活,低成本改造自家空調(diào)可真是真香系列~撒花~建議:涂鴉能開放模組的二次服務(wù),為開發(fā)者和物聯(lián)網(wǎng)設(shè)備廠商提供更多的自定義服務(wù)和功能,相信會受到更多開發(fā)者和物聯(lián)網(wǎng)愛好者的青睞。
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。