找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3276|回复: 3
打印 上一主题 下一主题
收起左侧

学习型空调遥控的实现

[复制链接]
跳转到指定楼层
楼主
ID:82781 发表于 2015-6-13 01:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  经过整整一年的时间,今天终于实现了梦寐以求的控制空调的程序,回顾这段历程,大有曲折轮回之意。

去年此时我从xx辞职了,那时候我留下了一个空调的问题而悬而未决,但是其实走的时候我已经说过了,要用单片机捕捉原始码,不要解码,因为当时我做的电视遥控学习是用的网上的一段程序做的,是解码的,始终没有做这个空调的学习原始码和控制。后来听说后来者做出来了,也就印证了我的思想没有错。然后这个问题在我这里就被搁置了!挂起了。
  一方面是我的主要工作不在是智能家居,两一方面是程序上原来的固件库有问题。不太好做。直到上周吧,近来xx等人做的空调和电视的控制深深的刺激了我,我纵然是不服输的,和他交流了几次,总是骄纵的样子,仿佛他做出来就没有别人一样。于是乎,暗下决心,一定要攻破此问题,他能做我们就不能做?总得试试才知道,说干就干,重新找出来去年的代码,都看不懂了,然后开始分步走。
第一步:确定好TICK时间在基准,
第二步:模拟采样PWM波形,
第三步:采集红外数据
第四步:PWM调制红外波形发送
主要粗分为以上4步。然后分而治之。第一步就遇到很大问题,也是老问题,就是固件库怎么也不能把时钟提高到我需要的精度,并且老有迟滞误差的出现。为了解决这个问题。我专门去官方网站下载了最新的寄存器库,XX人总是自信的认为他是操作寄存器起家的,殊不知大家都是那样过来的,忽悠纯软件的人可以,忽悠我你还是省省得好。然后对比两套库的差异,很明显出来了,是由于代码的回调时的进出栈带来的迟滞,虽然进出、栈时间很短,CPU速度足够快,但是由于是精度比较高,所以速度很快,多次的堆积压栈出栈就会导致时间被占用,于是我在老版本的程序上稍加改动,屏蔽掉系统回调,速度直接呼呼上去。于是这个问题解决了,此问题已解决问题就已经解决一半了,
      今天实现了剩下的3步,上午主要工作是捕捉,很顺利,捕捉很成功,这也是磨刀不误砍柴工的结果。然后自己写了一点逻辑算法,用来接收和发送之间的协同。下午实现数据码的重构,利用PWM发生的38K重构整个码流,下午为了这个特意去办公室拿了示波器。架起来示波器直到发出来的和接收到遥控的数据码一个不差的显示到屏幕上,我知道大概我要去办公室实际测试一下了。

到了办公室废了好一顿周折才进去,没带钥匙,无奈只能爬进去了。一切就绪后,学码,发码。空调哗唥哗唥的跟着变化,我知道成功了,呵呵!



代码如下:

代码简单的不能再简单,几行而已。只是XXX别再装逼,都能!原理都一样只是你做的稍微细一点,我的这个粒度足够我用。

uint8_t StartLeve=0;   //起始电平状态
uint16_t DataLenth=0;    //码型长度
uint16_t  Learn_Finsh=0; //学习完毕
uint16_t ir_raw[512];    //数据码
uint32_t  ir_number;     //计数器

/*
  描述:发送红外调制嘛
************************/
extern void DrvTIMER_Delay(E_TIMER_CHANNEL ch, uint32_t uIntTicks)        ;
void Send_Ir_Code(uint8_t *pt ,uint16_t Lenth )
{       
        uint16_t i;       
        uint8_t k=0;
        uint32_t da,da1;       
           for(i=1;i<Lenth+1;i+=2)
           {
               
                                       
                                                   DrvPWM_Enable(DRVPWM_TIMER0, 1);
                                                da = ir_raw;
                                        DrvTIMER_Delay( E_TMR0, da) ;
                                                DrvPWM_Enable(DRVPWM_TIMER0, 0);
                                                da1 = ir_raw[i+1];
                                                DrvTIMER_Delay( E_TMR0, da1) ;
                                          

           }

                DrvPWM_Enable(DRVPWM_TIMER0, 0);
}


void EINT0callback()
{

                 
       
                       
                        ir_raw[DataLenth]=ir_number;//更新计数器
                                ir_number=0;                         //清计数器
                        if(DataLenth==0)                         //获取起始电平,以后按照数组依次排列为高低高低.
                        {
                           if(DrvGPIO_GetBit(E_PORT3,E_PIN2)==0)
                           {
                           StartLeve = 0;
                           }
                           else                                             //取得起始电平
                           {
                           StartLeve = 1;
                           }
                        }
                        //100MS        作为数据码结束的标志,理论上没有大于100MS的红外间隔,可改变。
                        //但是要注意再学习的时候学完一次之后得在按一下,触发之。
                        //此时已经学到了数据并可以返回数据的长度啦。       
                        if((ir_raw[DataLenth]>10000)&&(DataLenth!=0))
                        {                                                               
                        //学码完成 大于0之后表示数据已经记录进缓存中了
                        //        Learn_Finsh = DataLenth-1
                        //RAW数据被记录在raw[1]-raw[Learn_Finsh]之间
                        //                                       
                                Learn_Finsh= DataLenth-1;//       
                                DataLenth=0;                          //准备下一次学习。
                        }       
                                   DataLenth++;                         //下一个数据码



}

void pfP2P3P4Callback(uint32_t u32P2Status, uint32_t u32P3Status, uint32_t u32P4Status)
{
       
}

void pfP0P1Callback        (uint32_t u32P0Status, uint32_t u32P1Status)
{
                       
                if(u32P0Status&(1<<0))  //p0.0
                {
               
               
                               
                }
       

}
  
void init_IR_INTTRUPUT(void)
{
       
//DrvGPIO_SetIntCallback(pfP0P1Callback, pfP2P3P4Callback);//install
//DrvGPIO_EnableInt(E_PORT0, E_PIN0, E_IO_BOTH_EDGE, E_MODE_EDGE);//双边沿
DrvGPIO_EnableEINT(E_EINT0_PIN,E_IO_BOTH_EDGE, E_MODE_EDGE, EINT0callback);

}


void init_PWM(void)
{

  

        S_DRVPWM_TIME_DATA_T sP_PWM;


  /*Initialize PWM*/
    DrvPWM_Open();
        /* Select PWM engine clock */
   DrvPWM_SelectClockSource(DRVPWM_TIMER0, DRVPWM_INTERNAL_22M);
    /* PWM Timer property */
    sP_PWM.u8Mode = DRVPWM_AUTO_RELOAD_MODE;
    sP_PWM.u8HighPulseRatio = 50;   /* High Pulse peroid : Total Pulse peroid = 1 : 100 */
    sP_PWM.i32Inverter = 1;
    sP_PWM.u32Frequency =38000;
    DrvPWM_SetTimerClk(DRVPWM_TIMER0, &sP_PWM);

    /* Enable Output for PWM Timer */
    DrvPWM_SetTimerIO(DRVPWM_TIMER0, 1);
    /* Enable the PWM Timer */       
  //  DrvPWM_Enable(DRVPWM_TIMER0, 0);

           DrvGPIO_InitFunction(E_FUNC_PWM01_P4);
               
        DrvPWM_Enable(DRVPWM_TIMER0, 0);
       
       
        }


到最后做出来了,单独使用确实没啥意思,如果联合TCP/IP使用那就有意义的多了。数据码放在本地FLASH中,服务器只要发送代号即可,小米盒子的遥控功能就是这么做的!

最后结句以自欺:
结庐在人境,而无车马喧。 问君何能尔?心远地自偏。 采菊东篱下,悠然见南山。 山气日夕佳,飞鸟相与还。 此中有真意,欲辨已忘言。


老伟
于日照比特电子






分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:208445 发表于 2017-8-24 11:45 | 只看该作者
问题的是空调的学习,空调不是有好多命令的,都记录下来这么多的脉宽,也是一件费劲的事啊
回复

使用道具 举报

板凳
ID:208445 发表于 2017-8-24 11:45 | 只看该作者
小米盒子 用的是蓝牙吧
回复

使用道具 举报

地板
ID:260347 发表于 2018-8-19 10:54 | 只看该作者
老哥,可否把完整程序发到我邮箱,非常感谢!!向您学习一下Martin_1996@163.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表