|
### 概述
前几年买的房子,开发商说是全智能家居,结果几年过去,该智能家居公司倒闭了,最近服务器也关闭了,于是智能家居变成了弱智家居,为此我觉得进行DIY改制。
一般的智能家居都是由网关、遥控发射开关、灯端接收控制等部件组成;而遥控开关最简单的便是采用315Mhz或433Mhz的遥控方式。
由于项目较大,必须进行拆分,进行逐步实现,大致分为:
* 1、遥控通信协议的破解
* 2、智能网关一代,通过继电器控制一路设备,完成自主控制以及网络外控的全部功能,含全套的UI界面控制
* 3、系统集成,实现全屋灯具的控制
### 第一步:通信协议的破解
遥控灯具等设备的开启与关闭,最简单的办法是使用现成的芯片,比如EV1527等,但是这样无法用单片机控制,于是,使用单片机针对协议的解码,编码就成了必要
#### 实现:
硬件图纸:
STM32单片机连接发射模块和接收模块,通过单片机解码和编码用于控制遥控设备;
目前代码只支持EV1527的解码规范;
所谓的自学习遥控器,其实就是先将信号解码并存储,然后再次发送出去就相当于自学习;
前端采用SHMICTRL 神秘魔控串口屏,用于实现UI操作,本版本只制作了一个测试界面,完成主要功能,后期第二个版本我们才制作全功能的界面方便实现控制;
前端和后端单片机采用串口进行通信,通信协议很简单,如下:
当单片机收到遥控信号后,串口传出:
app.work(0x00AEADE2);
串口屏收到语句后立即会执行app控件的work方法,完成界面的刷新显示;
而串口屏需要发送信号时,比如点击了按钮“发送”:
void x1.onclick()
{
echo("SD"+l1.text+"\r\n");
}
按下按钮后,执行了x1按钮的onclick事件,然后将l1这个label控件的显示内容echo出来,而echo是通过串口输出的,因此实际上串口屏向单片机输出了:
SD00ADADE2
单片机收到串口传来的数据,解析后调用发送函数完成遥控数据的发送:
#### 单片机编解码实现:
单片机采用STM32F030F4P6,其中发送和解码代码如下:
发送:
```
void tim3delay(u32 cs){ //延时,单位us
TIM3->CNT = 0;
while(TIM3->CNT < cs);
}
void worksend(u32 data){
// 发送数据
u8 i;
u32 d=0x00800000;
HAL_TIM_Base_Stop_IT(&htim16);
//输出引导码
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_RESET); //0
tim3delay(100);
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_SET); //H
tim3delay(300);
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_RESET); //L
tim3delay(9000); //9ms
//H6L180
for(i=0;i<24;i++){
if (data & d){ //高电平
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_SET); //H
tim3delay(16*50);
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_RESET); //L
tim3delay(8*50);
}else{ //低电平
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_SET); //H
tim3delay(6*50);
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_RESET); //L
tim3delay(18*50);
}
d>>=1;
}
HAL_GPIO_WritePin(P315G, P315, GPIO_PIN_SET); //H
HAL_TIM_Base_Start_IT(&htim16);
}
```
接收解码:
```
#define H1min 14
#define H1max 20
#define L1min 5
#define L1max 8
#define H0min 4
#define H0max 6
#define L0min 14
#define L0max 20
struct DefCode
{
u32 data; //同步码之后的全部24bit的数据
u32 data2; //同步码之后的全部24bit的数据
u8 flag; //=0 表示未进入同步信号 =1表示已进入同步信号
u8 h; //高电平累计
u8 l; //低电平累计
u8 d; //=0 表示上次是低电平 =1表示上次是高电平
u8 js; //记录当前接收数据的编号
u8 issecond;//=1表示接收到第二个数据包 =0表示接收到第一个数据包 =2表示两个数据包相同有效,可以取用
};
void TIM16_IRQHandler(void)
{
//50us 一次中断 ,1024*8=8192*0.1ms=819.2ms
//取用 当code.issecond==2时,才取用,取用后将 code.issecond=0
unsigned char RF;
if (TIM16->SR & TIM_SR_UIF){
TIM16->SR = ~TIM_SR_UIF; // 清除中断标志
if (code.issecond==2) return; //有采集数据未取用,则不处理
RF=(GPIOA->IDR & GPIO_PIN_13) ? 1 : 0; //读取电平
if(RF){ //高电平
if (code.d==0){ //LH
if (code.flag==0){ //需要判断是否是引导码
if ((code.h>=4)&(code.h<=7)&(code.l>=160)&(code.l<=190)){//是引导码
code.flag=1; //开始采集后续数据
code.js=0; //开始采集bit0;
code.data=0;
}
}
else{ //开始采集数据
if ((code.h>=H1min)&(code.h<=H1max)&(code.l>=L1min)&(code.l<=L1max)){ //表示成功采集数据1
code.data|=1<<(23-code.js);
}
else if ((code.h>=H0min)&(code.h<=H0max)&(code.l>=L0min)&(code.l<=L0max)){ //表示成功采集数据0
}
else{ //表示数据错误
code.flag=0; //恢复采集引导码状态
}
code.js++;
if (code.js==24){//数据采集完成,恢复到采集引导码模式
code.flag=0;
if(code.issecond==0){ //采集第一遍数据
code.issecond=1;
code.data2=code.data;
}
else if (code.issecond==1){ //采集第二遍数据
if (code.data==code.data2){
code.issecond=2; //采集有效
}
else{ //采集无效
code.issecond=0;
}
}
}
}
code.h=1;
code.d=1;
}
else{//HH
code.h++;
}
}
else{ //低电平
if (code.d==0){ //LL
code.l++;
}
else{ //HL
code.l=1;
code.d=0;
}
}
}
}
```
#### 实际测试:
#### 本项目全部开源:
电路图、PCB、外壳设计:
https://oshwhub.com/apachectl/315mhz-433mhz
工程源代码:
https://gitee.com/shmictrl/demo/tree/master/shmictrl_315Mhz
实际操作视频:
https://v.douyin.com/xVhKEkGhJS4/
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|