产品选型

单片机控制电风扇 小创意:用单片机给老风扇增加红外遥控,定时及睡眠功能

小编 2024-11-24 产品选型 23 0

小创意:用单片机给老风扇增加红外遥控、定时及睡眠功能

小伙伴们家里是不是还是手动按键式电扇?是的话就跟我改起来,改过之后手动按键不影响,还是可以用哟,增加红外遥控功能,定时增加到8小时(你的是不是还只有1小时定时呀,呵呵!),还有哟!再加个睡眠功能:如果打开睡眠功能,定时时间到之后自动跳到1档,不然下半夜冻坏罗,不打开睡眠功能,定时时间到之后自动关闭。是不是很贴心啦!本来还想加个仿自然风,就是扇一会停一会再扇一会…………,网友们都说那样太伤电机,于是取消了。废话少说,直接上图:

二档走起,中间小灯为电源指示灯,左边有三个小灯,为风量档位指示灯,一档亮一个,二档亮两个,三档亮三个。手动按键的话也一样,会亮指示灯,手动过后再用遥控也是可以的。不按机械按键直接遥控也是可以的,遥控后再按钮也是可以的,如果没按机械按键直接遥控打开的,此时想要按机械按键关闭要先按三档中任一键再按0键关闭。

定时设置状态,数码管亮起,右边一个数码管为小写h,左边一个数码管表示1到8小时设置。

已经确定为6小时,后面的h变为大写的H,100秒之前为剩余小时显示,之后为剩余分钟的倒计时

看到定时数码管下面的小灯了吧,那是睡眠指示灯,表示打开了睡眠模式。

遥控器是这个样子滴

三个并排的键依次为1档、2档、3档,上翻键下翻键为档位的加减,档位加到三档时上翻不再增加,档位减到1档时,再减就关闭了。

OK为关闭。

V-为定时设置键,定时设置状态时,上翻下翻键为定时时间的加减,OK键为确认。

右翻键为睡眠模式开关切换键。V+是管我们家电灯的啦~~

最后给大家看一下我调试的功能板:

电源部分直接用的是旧手机充电器,为了达到更好的效果我特意做了仿真文件如下:

部分参考源代码如下:功能说明

/******************************************************************

/* STC89C52单片机 *

/* 11.0592M晶振 *

/*程序用了外部中断0接收红外信号,IO口为P32 *

/*遥控OK键为关闭,在定时设置状态时为确认 *

/*遥控上、下翻键为档位加、减,在设置定时状态时为定时时间加、减, *

/*遥控V-键为进入设置定时模式 *

/*右翻键为睡眠模式的开启与关闭,睡眠模式指定时时间到后自动切为1档 *

/*遥控返回键为1档,遥控主页键为2档,遥控菜单键为3档, *

/*定时设置状态时,第二个数码管为小写H,设置完成后为大写H. *

/*最多定时8小时,99分钟内显示分钟倒计时 *

/******************************************************************/

#include <reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

#define const_key_time1 20 //按键去抖延时的时间

#define const_1s 440 //大概1秒钟所需要的中断数

void delay_long(unsigned int uiDelaylong);

void delay(uchar x); //x*0.14MS

void delay1(int ms);

void T0_time(); //定时器0中断函数

void key_service(); //按键服务的应用程序

void key_scan(); //按键扫描函数,放在定时中断里

void key_service1(); //关闭的应用程序

void initial_myself(); //初始化单片机

void initial_peripheral();//初始化外围

void LCD_XSservice(); //数码管显示程序

void display_drive(); //数码管字模驱动函数

sfr ISP_CONTR=0xe7; //软复位地址

sbit IRIN = P3^2; //红外接收器数据线,外部中断0

sbit K1 = P2^0; //按键1

sbit K2 = P2^1; //按键2

sbit K3 = P2^2; //按键3

//风量1档最小,3档最大

sbit SC1 = P2^3; //1档输出,控制PNP三极管,三极管再控制BT136双向可控硅

sbit SC2 = P2^4; //2档输出,控制PNP三极管,三极管再控制BT136双向可控硅

sbit SC3 = P2^5; //3档输出,控制PNP三极管,三极管再控制BT136双向可控硅

sbit LED1 = P1^0; //档位指示小灯1

sbit LED2 = P1^1; //档位指示小灯2

sbit LED3 = P1^2; //档位指示小灯3

sbit LED4 = P1^3; //睡眠模式指示小灯

sbit LCD1 = P2^6; //接PNP三极管控制定时显示数码管1的阳极(显示数码管为共阳管)

sbit LCD2 = P2^7; //接PNP三极管控制定时显示数码管2的阳极(显示数码管为共阳管)

//定时显示数码管的八个阴极接P0

uchar IRCOM[7]; //定义红外接收数组

uchar code Tab0[]= //定义数码管数组,没有小数点

{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x89

};//0,1,2,3,4,5,6,7,8,9,h

uint code Dingshi0[]= //定义定时数组

{0,60,120,180,240,300,360,420,480

};

unsigned char ly_dis1;//定义显示缓冲区

unsigned char ly_dis2;//定义显示缓冲区

unsigned char ucKeySec=0; //被触发的按键编号

unsigned int uiKeyTimeCnt1=0; //按键1去抖延时计数器

unsigned char ucKeyLock1=0; //按键1触发后自锁的变量标志

unsigned int uiKeyTimeCnt2=0; //按键2去抖延时计数器

unsigned char ucKeyLock2=0; //按键2触发后自锁的变量标志

unsigned int uiKeyTimeCnt3=0; //按键3去抖延时计数器

unsigned char ucKeyLock3=0; //按键3触发后自锁的变量标志

unsigned char anjiank=0; //有按键被触发

unsigned char hw_anjiank=0; //红外按键被触发

unsigned char LCDSec=0; //定时设置状态

unsigned char LCDszxs=0; //数码管定时的变量

unsigned int DSSJ=0; //定时的时间

unsigned char DSBZ=0; //定时标志

unsigned char iii=0; //动态数码管定时显示变量

unsigned char posit=0;//动态数码管扫描步骤

unsigned int uiTimeCnt=0; //倒计时的时间计数器

unsigned int js1m=0;//计时秒

unsigned char Guanbi=0; //关闭标志

unsigned char SMMS=0; //睡眠模式标志

unsigned char SMMSJK=0; //睡眠模式监控

/*******************************************************************/

main()

{

initial_myself(); //初始化

delay_long(100);

initial_peripheral();//初始化外围

while(1)

{

key_service1(); //关闭的应用程序

key_service();//按键服务的应用程序

LCD_XSservice(); //数码管显示程序

}

}

//end main

/**********************************************************/

void LCD_XSservice() //数码管显示程序

{

if (DSBZ==1)

{

if (DSSJ>60)

{

if (DSSJ>99) {iii=2;}

if (DSSJ>120) {iii=3;}

if (DSSJ>180) {iii=4;}

if (DSSJ>240) {iii=5;}

if (DSSJ>300) {iii=6;}

if (DSSJ>360) {iii=7;}

if (DSSJ>420) {iii=8;}

ly_dis1=iii;//P0口驱动数码管2到8的定时显示

ly_dis2=10; //显示个位值

}

if (DSSJ<=99)

{

if (DSSJ>0)

{

ly_dis1=DSSJ/10; //显示十位值

ly_dis2=DSSJ%10; //显示个位值

}

}

if (DSSJ==0)

{

if (SMMS==1)

{

LCD1=1;

LCD2=1;

DSBZ=0;

LED4=1;

SMMSJK=0;

hw_anjiank=1; //表明由红外按键触发

ucKeySec=1;//触发1档按键

}

if (SMMS==0)

{

if (DSBZ==1)

{

ISP_CONTR=0x20; //关闭所有,所有变量清零,软复位

}

}

}

}

}

/**********************************************************/

void key_scan()//按键扫描函数,放在定时中断里

{

if (LCDSec!=1)

{

if(K1==1)//IO口是高电平,说明按键1一直没有按下,这时要及时清零一些标志位

{

ucKeyLock1=0; //按键自锁标志清零

uiKeyTimeCnt1=0;//按键去抖延时计数器清零

}

else if(ucKeyLock1==0)//有按键按下,且是第一次按下

{

uiKeyTimeCnt1++; //累计定时中断次数

if(uiKeyTimeCnt1>const_key_time1)

{

uiKeyTimeCnt1=0;

ucKeyLock1=1; //自锁按键置位,避免一直触发

hw_anjiank=0; //表明解除由红外按键触发

anjiank=1; //表明由按键触发

ucKeySec=1; //触发1档按键

}

}

if(K2==1)//IO口是高电平,说明按键2一直没有按下,这时要及时清零一些标志位

{

ucKeyLock2=0; //按键自锁标志清零

uiKeyTimeCnt2=0;//按键去抖延时计数器清零

}

else if(ucKeyLock2==0)//有按键按下,且是第一次按下

{

uiKeyTimeCnt2++; //累计定时中断次数

if(uiKeyTimeCnt2>const_key_time1)

{

uiKeyTimeCnt2=0;

ucKeyLock2=1; //自锁按键置位,避免一直触发

hw_anjiank=0; //表明解除由红外按键触发

anjiank=1; //表明由按键触发

ucKeySec=2; //触发2档按键

}

}

if(K3==1)//IO口是高电平,说明按键3一直没有按下,这时要及时清零一些标志位

{

ucKeyLock3=0; //按键自锁标志清零

uiKeyTimeCnt3=0;//按键去抖延时计数器清零

}

else if(ucKeyLock3==0)//有按键按下,且是第一次按下

{

uiKeyTimeCnt3++; //累计定时中断次数

if(uiKeyTimeCnt3>const_key_time1)

{

uiKeyTimeCnt3=0;

ucKeyLock3=1; //自锁按键置位,避免一直触发

hw_anjiank=0; //表明解除由红外按键触发

anjiank=1; //表明由按键触发

ucKeySec=3; //触发3档按键

}

}

}

}

/**********************************************************/

void key_service1() //关闭的应用程序

{

if(anjiank==1) //判断按键是否有按下,如果按键触发,但三个按键都为高电平,那么表示按了按键关按键

{

if(K1&K2&K3==1)

{

ISP_CONTR=0x20; //关闭所有,所有变量清零,软复位

}

}

if(hw_anjiank==1)//判断红外关按键是否按下

{

if(Guanbi==1) //关闭标志

{

//关闭所有,所有变量清零,软位

initial_myself(); //初始化

delay_long(100);

initial_peripheral();//初始化外围

Guanbi=0; //关闭标志清零

}

}

}

/**********************************************************/

void key_service() //按键服务的应用程序

{

switch(ucKeySec) //按键的切换

{

case 1: //按键1--1档

LED1 = 1;

LED2 = 1;

LED3 = 1;

LED1 = 0;

SC2 = 1;

SC3 = 1;

delay(300);

if (SC2&SC3)

{

SC1 = 0;

}

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一直触发

break;

case 2: //按键2--2档

LED1 = 1;

LED2 = 1;

LED3 = 1;

LED1 = 0;

LED2 = 0;

SC1 = 1;

SC3 = 1;

delay(300);

if (SC1&SC3)

{

SC2 = 0;

}

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一直触发

break;

case 3: //按键3--3档

LED1 = 1;

LED2 = 1;

LED3 = 1;

LED1 = 0;

LED2 = 0;

LED3 = 0;

SC1 = 1;

SC2 = 1;

delay(300);

if (SC1&SC2)

{

SC3 = 0;

}

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一直触发

break;

case 4: //OK按键短按

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一直触发

break;

}

}

/**********************************************************/

void IR_IN() interrupt 0 //using 0 接收红外信号

{

unsigned char j,k,N=0;

EX0 = 0;

delay(15);

if (IRIN==1)

{ EX0 =1;

return;

}

//确认IR信号出现

while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。

{delay(1);}

for (j=0;j<4;j++) //收集四组数据

{

for (k=0;k<8;k++) //每组数据有8位

{

while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。

{delay(1);}

while (!IRIN) //等 IR 变为高电平

{delay(1);}

while (IRIN) //计算IR高电平时长

{

delay(1);

N++;

if (N>=30)

{ EX0=1;

return;} //0.14ms计数过长自动离开。

} //高电平计数完毕

IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”

if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”

N=0;

}//end for k

}//end for j

if (IRCOM[2]!=~IRCOM[3])

{ EX0=1;

return; }

if (LCDSec!=1)

{

if (IRCOM[2]==0xC5)//返回键 这一步就是判断,如果对应按键,则执行下面动作!

{

anjiank=0; //表明解除由按键触发

hw_anjiank=1; //表明由红外按键触发

ucKeySec=1;//触发1档按键

}

if (IRCOM[2]==0x88)// 主页键 这一步就是判断,如果对应按键,则执行下面动作!

{

anjiank=0; //表明解除由按键触发

hw_anjiank=1; //表明由红外按键触发

ucKeySec=2;//触发2档按键

}

if (IRCOM[2]==0x82)//菜单键 这一步就是判断,如果对应按键,则执行下面动作!

{

anjiank=0; //表明解除由按键触发

hw_anjiank=1; //表明由红外按键触发

ucKeySec=3;//触发3档按键

}

}

if (IRCOM[2]==0xCA)//上翻键,这一步就是判断,如果对应按键,则执行下面动作!

{

if (LCDSec==1)//如果在时间设置状态,就是设置时间的加

{

LCDszxs++;

if (LCDszxs>8)

{

LCDszxs=0;

}

}

else //除了时间设置状态,为风量档位加

{

if (SC1&SC2&SC3)

{

ucKeySec=1;

}

if (SC1==0)

{

ucKeySec=2;

}

if (SC2==0)

{

ucKeySec=3;

}

anjiank=0; //表明解除由按键触发

hw_anjiank=1; //表明由红外按键触发

}

}

if (IRCOM[2]==0xD2)//下翻键,这一步就是判断,如果对应按键,则执行下面动作!

{

if (LCDSec==1)//如果在时间设置状态,就是设置时间的减

{

if (LCDszxs>0)

{

LCDszxs--;

}

if (LCDszxs==0)

{

LCDszxs=8;

}

}

else //除了时间设置状态,为风量档位减

{

if (SC1==0)

{

Guanbi=1; //关闭标志打开

}

if (SC2==0)

{

ucKeySec=1;

}

if (SC3==0)

{

ucKeySec=2;

}

anjiank=0; //表明解除由按键触发

hw_anjiank=1; //表明由红外按键触发

}

}

if (IRCOM[2]==0x81)// V-键 这一步就是判断,如果对应按键,则执行下面动作!定时设置

{

if ((SC1&SC2&SC3)==0)

{

LCDSec=1; //定时设置状态,数码管闪动

LCDszxs=0; //数码管定时的变量

LCD1=0;

LCD2=0;

}

}

if (IRCOM[2]==0xce)//OK键 这一步就是判断,如果对应按键,则执行下面动作!确认并退出定时设置

{

if (LCDSec==1)

{

if (LCDszxs>0)

{

DSSJ=Dingshi0[LCDszxs];

DSBZ=1;

LCDSec=0;

SMMSJK=0;

}

else

{

LCD1=0;

LCD2=0;

LCDSec=0;

}

}

else

{

initial_myself(); //初始化

delay_long(100);

initial_peripheral();//初始化外围

Guanbi=0; //关闭标志清零

}

}

if (IRCOM[2]==0xC1)//右翻键,这一步就是判断,如果对应按键,则执行下面动作!

{

if ((SC1&SC2&SC3)==0)

{

if (LCDSec==0)

{

LED4=!LED4; //LED4取反

if (LED4==0)

{

SMMS=1;

if (DSBZ==0)

{

if(SMMSJK==0)

{

LCD1=0;

LCD2=0;

LCDszxs=3;

DSSJ=Dingshi0[LCDszxs];

DSBZ=1;

SMMSJK=1;

}

}

}

if (LED4==1)

{

SMMS=0;

if (DSBZ==1)

{

if(SMMSJK==1)

{

LCD1=1;

LCD2=1;

DSBZ=0;

LCDszxs=0;

DSSJ=Dingshi0[LCDszxs];

SMMSJK=0;

}

}

}

}

}

}

- EX0 = 1;

}

/**********************************************************/

void display_drive() //数码管字模驱动函数

{

if (DSBZ|LCDSec)

{

switch(posit)

{

case 1:

LCD1=0;

LCD2=1;

if (LCDSec==1)

{

P0=Tab0[LCDszxs];//P0口驱动数码管0到8的定时显示

}

else

{

P0=Tab0[ly_dis1];//P0口驱动数码管1到8的定时显示

}

break;

case 2:

LCD1=1;

LCD2=0;

if (LCDSec==1)

{

P0=0X8b;//显示H

}

else

{

P0=Tab0[ly_dis2];//P0口驱动数码管1到8的定时显示

}

break;

}

posit++;

if(posit>2)

{

posit=1;

}

}

else

{

LCD1=1;

LCD2=1;

}

}

/**********************************************************/

void T0_time() interrupt 1 //定时器0函数

{

TF0=0; //清除中断标志

TR0=0; //关中断

key_scan(); //按键扫描函数

- if(DSBZ==1) //启动定时倒计时计数器

{

uiTimeCnt++;

if(uiTimeCnt>=const_1s) //1秒时间到

{

js1m++;

if (js1m==210)

{

if(DSSJ!=0) //防止倒计时到0秒

{

DSSJ--; //倒计时直减1

}

js1m=0;

}

uiTimeCnt=0; //计时器清零,准备重新开始

}

}

display_drive(); //数码管字模驱动函数

TH0=0xfe; //重装初始值(65535-500)=635035=0xfe0b

TL0=0x0b;

TR0=1; //开中断

}

/*******************************************************/

void initial_myself() //初始化单片机

{

//I/O口初始化

IRIN=1; //红外接收器数据线,外部中断0

K1 = 1; //按键1

K2 = 1; //按键2

K3 = 1; //按键3

SC1 = 1; //1档输出

SC2 = 1; //2档输出

SC3 = 1; //3档输出

LED4 = 1; //仿自然风指示小灯

……………………

鉴于篇幅限制,只能写部分代码,通过仿真和实践完美实现了所需要的远程遥控定时和睡眠功能,小伙伴们如果感兴趣你们也试一下吧,如果硬件方面有困难也可以直接用开发板哦!

最后,如果有什么意见或者建议欢迎您留言给我,让我们共同学习一起进步,如果需要 完整代码或设计文件,请在下方留言或者私信我,看到后会第一时间回复。

谢谢!

如果喜欢我的文章请评论转发加关注哦。

MCU单片机智能控制落地扇解决方案

随着科技进步和消费升级,消费者对电风扇的智能化需求日趋强烈。为了快速响应市场需求,以更低的成本打造智能电风扇。 MCU单片机智能控制落地扇解决方案以灵动微MM32SPIN040C主控。 方案采用的主控MM32SPIN040工作频率可达48MHz,内置16KB Flash,2KB SRAM高速存储器,针对电机应用内置2个运放,预驱工作电压高达36V。适合于三相永磁无刷电机,电动工具等多种应用场合。该方案适用于落地扇、塔扇、循环扇、吊扇等多种品类的风扇设备。我司英尚微可提供高速吹风筒、电扇等各种电机应用方案。 方案功能 支持顺逆风启动 无级变速调节 支持多种保护 应用框图

相关问答

科技小制作小发明之 电风扇 怎么做 - 学点总对 的回答 - 懂得

如果想要比较好一点的,可以弄一个步进电机,通过单片机编程控制它的转速,如果还要好点的,可以通过摇控器控制单片机,就和市面上的电风扇差不多了。具...

电风扇 换挡与消耗功率的关系同一台 电风扇 ,一档和二档风扇...

[最佳回答]不同的转速肯定消耗的功率不同.可以肯定的是,转速越高,消耗功率越大.不同的风扇,调速原理是不同的.有的是串联一个小变压器(其实不是变压器,形状类...

谁来说下怎么 控制 风扇转速-家居装修–手机房天下问答

[回答]单片机输出pwm通过9013控制可控硅控制电扇转速。单片机为热地。单片机输出通过9013控制继电器,控制电扇1,2,3档速度单片机输出pwm通过...

电风扇 自动开关-家居装修–手机房天下问答

[回答]不是,现在多为单片机控制,应该是控制电路失灵,可以拔下插头,过半小时再插,看能否恢复。看是否单片机程序跑飞。也许可以恢复,如果不行,找人修理。...

可以接收风机转速的继电器?

接收风机转速都是通过模块控制24V继电器的,把消防控制模块的控制线接到继电器的线圈端子(13、14号)上,然后在继电器上找一组未用的动作端子,将模块的反馈线...

盆友们,能问一下,电子日历 单片机 制作?,制作 单片机 服务体...

[回答]51学习用的比较多,单片机能做很多事,比方说电磁炉,微波炉,遥控电风扇,,,很多家用电器其实就有单片机,因为比以往靠硬件来做功能的机器成本会低很多,...

电子调速风扇功率和转速有关吗?

不同的转速肯定消耗的功率不同。可以肯定的是,转速越高,消耗功率越大。不同的风扇,调速原理是不同的。有的是串联一个小变压器(其实不是变压器,形状类似而...

帮忙设置空调的 智能控制 可根据温度自动开关机,有原理,可有智...

如若需要考虑节能,那么你还需要人体感应,季节感知,时间控制等等这些智能程序,那么就还需要加上单片机!就可以了!小马哥6861天前扩展回答1门窗自动开关机价...

电子开关制作方法谁知道?-设计本有问必答

把火线进线接一头(一头有两个插孔,插一侧即可)。另一头插控制引线即可(要插到通一侧的位置孔内)。希望我的回答对您有帮助。电子开关制作方法,据我...

四个开关各 控制 四个灯泡?

方法很多,比如使用旋转式的档位开关就可以.,这样只用一个开关就行了.使用类似电扇上的带自锁互锁的按键开关也可以.这个最符合你的要求.其他的方法,你就要使用...

猜你喜欢