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