yenan1001 发表于 2014-9-6 16:51:33

arduino pro mini 自动控制吊扇

本帖最后由 yenan1001 于 2014-9-14 01:50 编辑

家里吊扇的拉绳被熊孩子弄断了。
想了几天,决定换个arduino+继电器作为风扇换挡开关。
拆开风扇,发现里面控制转速的就是一个电容块,里面集成了三种不同的电容。通过不同的电容值对交流电限流来控制转速。就好像电阻之于直流电。

猜测着画了个原理图。

决定用arduino pro mini 和一个四路继电器控制转速。
外加人体感应器来自动关闭吊扇。
触发开关不打算用实体开关,而是用红外开关。

实现的功能和原来一样,有触发就打开吊扇,再有触发就换一档。
原装的换挡顺序是 停-最快-中等-最慢-停。因为通常都是用最慢。所以程序设置就自动控制风扇换挡到最慢。

原来打算用中断的。可是红外开关触发一次会发送很多抖动到中断。不想用电容啥的了,就算了。
程序很简单。没想到最困扰我的是对自然光的滤波。白天太阳强烈的时候,就会触发红外开关。所以整个程序有一部分都在解决这个问题。
到现在也没有完全搞定。吊扇偶尔还是会发疯。

***我在四楼放了一个很好的解决方案。要试试看。***

/*
   This code is to control the fan to tune the speed and turn on.

   当风扇停止时,触动一次开关会顺次打开3档-停五秒-2档-停五秒-一档。
   如果在五秒停顿时间内再次触发,将会停在当前档位。
   如果风扇在某一档运行,触发开关会降一档。

   LED颜色:蓝色-2档;绿色-3档;红色-1档

   成功2014/5/8
*/


#include <avr/wdt.h>//看门狗头文件
boolean on = LOW;//both relay and LED low is on
boolean off = HIGH;
int speed = 0;


# define brown_line10
# define gray_line   4
# define purple_line 5

# define led_red   6
# define led_green   7
# define led_blue    8

# define body_sensor 11
# define control   3



void setup() {

//attachInterrupt(1, speed_change, FALLING);   //pin 3
//Serial.begin(9600);
wdt_enable(WDTO_8S);//定义看门狗8秒超时。

pinMode(brown_line, OUTPUT);
pinMode(gray_line, OUTPUT);
pinMode(purple_line, OUTPUT);
pinMode(led_blue, OUTPUT);
pinMode(led_green, OUTPUT);
pinMode(led_red, OUTPUT);

pinMode(body_sensor, INPUT);
pinMode(control, INPUT);

speed0();

}

void loop()
{

delay(2000);                      //省电,不要总是运行;等待红外信号

   if (digitalRead(body_sensor)==HIGH)   //if human body detected
   {if (digitalRead(control)==LOW)   //如果有红外信号
    {
   delay(1000);                     //延迟,过滤误触发
   if (digitalRead(control)==LOW)   //如果还有红外信号,不是误触发
   {
       blink_red();
       delay(1000);
       if (digitalRead(control)==HIGH)    //如果没有信号,不是自然光
       {
         wdt_reset();                     //喂狗
         speed_change();                  //换挡
       }
      
   }
    }
   }
wdt_reset();   //喂狗

if (digitalRead(body_sensor)==LOW)   //if no human body detected, off the fan
   {
   speed0();
   }


void blink_red()
{digitalWrite(led_red, on);
delay(50);
digitalWrite(led_red,off);
delay(500);
}

void blink_green()
{digitalWrite(led_green, on);
delay(50);
digitalWrite(led_green,off);
delay(500);
}


void speed1()
{   
   
   digitalWrite(brown_line, off);   //slow fan speed, only purple line on
   digitalWrite(led_blue, off);
   
   digitalWrite(led_red, on);
   speed =1;

}

void speed2()
{   
   digitalWrite(gray_line, off);//off fast fan
   digitalWrite(led_green, off);
   digitalWrite(led_blue, on);
   delay(500);

   digitalWrite(brown_line, on); //middle fan speed
   digitalWrite(purple_line, on);
   
   speed =2;

}   

void speed3()
{      
   digitalWrite(gray_line, on);//fast fan speed
   digitalWrite(led_green, on);
   speed=3;

}

void speed0()
{   
   digitalWrite(gray_line, off);
   digitalWrite(brown_line, off);
   digitalWrite(purple_line, off);
   
   digitalWrite(led_red, off);
   digitalWrite(led_blue, off);
   digitalWrite(led_green, off);
   speed=0;

}

void normal_on()
{   

switch(speed)
    {
      case 0:
         speed3();
         delay(1000);
         if (digitalRead(control)==LOW)
               {
                  delay(1000);
                  if (digitalRead(control)==LOW)
                     {
                      digitalWrite(led_green,off);
                      delay(50);
                      digitalWrite(led_green,on);
                     
                      delay(1000);
                      wdt_reset();                     //喂狗
                      if (digitalRead(control)==HIGH)
                      {break;}
                     }
                  }   
         else {delay(4000);
               wdt_reset();                        //喂狗
                }

               
         
   
      case 3:
         speed2();
         delay(1000);
         if (digitalRead(control)==LOW)   //如果检测到控制信号,
               {
                  delay(1000);
                  if (digitalRead(control)==LOW)   //不是误触发
                     {
                      digitalWrite(led_blue,off);   //闪一下led
                      delay(50);
                      digitalWrite(led_blue,on);
                     
                      delay(1000);
                      wdt_reset();                   //喂狗
                      if (digitalRead(control)==HIGH)   //如果不是自然光
                      {break;}                        //跳出,保持,不再降档
                     }
                  }   
         else {delay(4000);               //否则,等5秒,降档
               wdt_reset();                  //喂狗
               }                     
               
         

      case 2:
         speed1();
   }
   
}


void speed_change()
{   

switch(speed)
{
    case 0:
             normal_on();
             break;
    case 1:
             speed0();
             break;
    case 2:
             speed1();
             break;
    case 3:
             speed2();
             break;
}
}

zgkjzf 发表于 2014-9-6 23:46:45

看门狗一直没明白 看了楼主的文档有点启发

k8706342 发表于 2014-9-6 23:51:45

是不是電容降壓?

yenan1001 发表于 2014-9-10 22:53:01

k8706342 发表于 2014-9-6 23:51
是不是電容降壓?

是,电容在交流电里就是一个电阻的作用。

yenan1001 发表于 2014-9-14 01:49:41

本帖最后由 yenan1001 于 2014-9-14 01:52 编辑

偶然看到了这篇,非常有启发。
可惜我的红外开关是模块,看来要买单独的原件来做了。


http://www.doyoung.net/articles/A_NEAR_IR/index.html
页: [1]
查看完整版本: arduino pro mini 自动控制吊扇