小言_互联网的博客

程序员为女友DIY一款红外线遥控器,感动哭了

436人阅读  评论(0)

身为一位资深电子发烧友,他经常自己动手将家中传统电器改造成智能电器。此次,该同学基于涂鸦 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()


  
  1. void Inf_RX_NECcoding(uint8_t *pbuff,uint8_t Length,uint8_t quantity)
  2. {
  3. uint8_t i;
  4. TIM_CtrlPWMOutputs(TIM1,ENABLE); //开输出
  5. TIM_Cmd(TIM3,ENABLE); //开定时器
  6. TIM_Cmd(TIM1,ENABLE);
  7. while(Inf_RX_StartCode()); //起始码
  8. if(Length>InfraredDataLength) //数据有效长度限制
  9. Length = InfraredDataLength;
  10. for(i= 0;i<Length;i++) //发送数据
  11. Inf_RX_Data(pbuff[i],Right);
  12. while(Inf_RX_Stop()); //结束码
  13. while(Inf_RX_Interval()); //间隔码
  14. while(Inf_RX_StartCode());
  15. if(Length>InfraredDataLength)
  16. Length = InfraredDataLength;
  17. for(i= 0;i<Length;i++)
  18. Inf_RX_Data(pbuff[i],Right);
  19. while(Inf_RX_Stop());
  20. for(i= 0;i<quantity;i++) //重复发送
  21. while(Inf_SendRepeatedly());
  22. TIM_CtrlPWMOutputs(TIM1,DISABLE); //关输出
  23. TIM_Cmd(TIM3,DISABLE); //关定时器
  24. TIM_Cmd(TIM1,DISABLE);
  25. }

数据发送(1个8位)


  
  1. uint8_t Inf_RX_StartCode(void)
  2. {
  3. if(!retemp)
  4. {
  5. retemp= 1;
  6. TimerOclk= 0;
  7. TIM_SetCompare1(TIM1, 1100); //设置占空比为50%
  8. }
  9. if(TimerOclk== 441) //低电平时间到
  10. TIM_SetCompare1(TIM1, 0); //设置占空比为0
  11. if(TimerOclk== 881) //高电平时间到
  12. {
  13. retemp= 0;
  14. TimerOclk= 0;
  15. }
  16. return retemp; //状态返回
  17. }

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()函数即可。


  
  1. //USART2中断服务函数
  2. void USART2_IRQHandler(void)
  3. {
  4. uint8_t value ;
  5. if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
  6. {
  7. value = USART_ReceiveData(USART2); //读取接收数据
  8. uart_receive_input( value); //数据存入涂鸦缓冲器
  9. }
  10. }

2)数据轮询函数wifi_uart_service(),要轮询这个函数,不然模组下发的数据MCU接收不到。放在主循环里面就行。


  
  1. while ( 1)
  2. {
  3. wifi_uart_service(); //轮询涂鸦数据
  4. /*
  5. 用户其他函数
  6. */
  7. }

3)协议初始化函数wifi_protocol_init(),这是为涂鸦串口数据提供一个缓存空间,在初始化中调用,初始化后不需要再调用。


  
  1. int main(void)
  2. {
  3. wifi_protocol_init(); //涂鸦模组协议初始化
  4. /*
  5. 用户其他初始化函数
  6. */
  7. while( 1)
  8. {
  9. wifi_uart_service(); //轮询涂鸦数据
  10. /*
  11. 用户其他函数
  12. */
  13. }
  14. }

**protocl.c**

1)串口发送函数uart_transmit_output(),用调用法发送,也可以用中断。

涂鸦提供串口发送数据处理方法,我们也不需要再单独去做处理,只需要将串口发送语句放在uart_transmit_output()函数里即可。


  
  1. void uart_transmit_output(unsigned char value)
  2. {
  3. while((USART2->SR &( 1<< 7))== 0);
  4. USART2->DR = value;
  5. }

2)所有数据上报函数all_data_update()

我们要在all_data_update函数中实现设备数据的传入,涂鸦模组或向MCU申请返回设备全部数据,设备数据通过all_data_update函数发送,所以要把设备的数据项传入到对应的函数中。注意:这个函数根据自己云端定义的功能对应,不能直接添加。


  
  1. void all_data_update(void)
  2. {
  3. //此代码为平台自动生成,请按照实际数据修改每个可下发可上报函数和只上报函数
  4. mcu_dp_bool_update(DPID_SWITCH,AirControlStructure.AirPowerControl); //BOOL型数据上报; //当前开关
  5. mcu_dp_value_update(DPID_TEMP_SET,AirControlStructure.AirRunTemper); //VALUE型数据上报; //当前温度设置
  6. // mcu_dp_value_update(DPID_TEMP_CURRENT,AirControlStructure.AirRunTemper); //VALUE型数据上报; //当前当前温度
  7. mcu_dp_enum_update(DPID_MODE,AirControlStructure.AirRunMode); //枚举型数据上报; //当前工作模式
  8. mcu_dp_enum_update(DPID_FAN_SPEED_ENUM,AirControlStructure.AirRunFan); //枚举型数据上报; //当前风速
  9. // mcu_dp_enum_update(DPID_STATUS,AirControlStructure.AirRunFlag); //枚举型数据上报; //当前状态
  10. mcu_dp_bool_update(DPID_AUTO,AirControlStructure.AirForceful); //BOOL型数据上报; //当前自动模式
  11. mcu_dp_bool_update(DPID_HEAT,AirControlStructure.AirHeat); //BOOL型数据上报; //当前辅热
  12. }

3)单个数据下发处理函数,在protocl.c中涂鸦定义了与功能对应的处理函数,我们要在对应函数中实现控制代码。示例


  
  1. static unsigned char dp_download_switch_handle(const unsigned char value[], unsigned short length) //开关
  2. {
  3. //示例:当前DP类型为BOOL
  4. unsigned char ret;
  5. //0:关/1:开
  6. unsigned char switch_1;
  7. switch_1 = mcu_get_dp_download_bool(value,length);
  8. if(switch_1 == 0) {
  9. AirControlStructure.AirPowerControl=OFF; //关
  10. AirControlStructure.AirHeat = OFF; //辅热关
  11. AirControlStructure.AirForceful = OFF; //强劲关
  12. } else {
  13. AirControlStructure.AirPowerControl=ON; //开
  14. }
  15. AirControlInfRX(); //发送红外代码
  16. //处理完DP数据后应有反馈
  17. ret = mcu_dp_bool_update(DPID_SWITCH,switch_1);
  18. if(ret == SUCCESS)
  19. return SUCCESS;
  20. else
  21. return ERROR;
  22. }

其实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的,可以戳:

建议:涂鸦能开放模组的二次服务,为开发者和物联网设备厂商提供更多的自定义服务和功能,相信会受到更多开发者和物联网爱好者的青睐。

还在等什么!为女友DIY创造一个温暖舒适的家居生活,低成本改造自家空调可真是真香系列~撒花~


转载:https://blog.csdn.net/weixin_50563088/article/details/112401010
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场