Arduino制作可调速电风扇

feature

暑假到了,随之而来的是炎热的天气,这篇文章将会教大家使用一个电脑主板上淘汰下来的CPU散热风扇来制作一个电扇。

这个风扇可以通过按下一个开关来进行开,关,和调速。

用到的工具

  • 废旧的CPU风扇(我的是4pin的)
  • Arduino UNO
  • 面包板
  • 电阻(1-10千欧)
  • 12V 电源
  • 电脑(用来编程)
  • 按钮开关

既然是第一次在博客上发关于Arduino的文章,那么先来介绍一下吧。

Arduino是一款开源的电子平台点击进入官网, 可以使用这个硬件来进行物联网方面的DIY,制作飞行器,3D打印机等等都可以用到Arduino,售价低廉,某宝上20元就能拿下,总之,只有你想不到,没有Arduino做不到,今天的这个文章只会初步的来使用Arduino。

既然要做个风扇,那么首先要让这个风扇可以动起来,根据经验,任何电器只要给正负极通上电就可以工作,所以先来试一下。首先,这个风扇的正常工作电压是12V,坏消息是我手上并没有这么高电压的电源,只有一个10V输出的电源(一个笔记本电脑电池),不过没有关系,先凑合用吧。不过正负极怎么接呢?看下一般4pin CPU风扇的规格:

Pin Name Color
1 GND black
2 +12VDC yellow
3 FAN_TACH green
4 FAN_CONTROL blue

所以首先把,电源正极和负极分别接到,pin2 和 pin1 上,风扇就可以工作了。

注:这样将导线直接接入电池两级的做法很危险,请不要模仿

既然大概的功能实现了,接下来就要开始调整转速了。通常调整电机转速使用了PWM技术,下面来科普一下PWM,

  • PWM

PWM(Pulse-width modulation)脉冲宽度调制,这个技术可以利用微处理器的数字输出来对模拟电路进行控制。简单地说,PWM信号是一个方形波,在方波中,波峰代表高电平,波谷代表低电平,虽然这个方形波的频率是固定的,但是高电平的时间除以总时间的值是可以从0到100%改变的,这个值叫做占空比。 通过控制占空比,就可以对电路进行进一步控制。

  • Duty Cycle(占空比)

占空比就是一个脉冲周期内高电平所在整个周期中占得比例,比如一个脉冲周期10秒,其中9秒是高电平,那么占空比就是90%。具体点的话:如果一个脉冲周期由10个信号(0或1)组成,那么1111100000信号就代表50%的duty cycle,因为整个信号由5个1,5个0组成.

  • PWM用途

PWM的用途很广,举几个例子

  • 调整LED亮度(在最高输出电压恒定的时候)
  • 控制电机,舵机转速(使用很广泛)
  • 生成声音信号
  • 调整信号

在Arduino中,很容易就能实现PWM,只要调用 analogWrite(pin,dutyCycle) 函数就行,其中,dutyCycle的值是从0到255中的任意一个,pin只能是PWM专用PIN(3,5 ,6,9, 10 或者11)。虽然这个函数已经提供了一个简单的方法来控制PWM,但是还不能通过频率来控制,不过对于这个项目来说够用了。想要更深层次的控制,可以使用ATmega的PWM寄存器来直接控制(Arduino的ATmega 168P/328P芯片拥有3个PWM计时器,可以控制6个PWM输出,通过这些可以实现比analogWrite() 函数更强大的功能)

  • 调速按钮

知道了PWM,的功能与用法之后,现在开始做开关,这个开关充当调速的功能。

在这里使用一个很常见的四角开关:四个角分别为A,B,C,D,平时A,B是连通的,C,D是连通的,当开关被按下后,ABCD四个角就都会被连通。

通过以下方式接线,5V输出接AB脚,A5 pin接CD脚,A5pin可以读到当前电路的电压,当开关按下后,A5的度数会增高,从而知道开关被按下。

电路搭建好了之后测试试一下,编写以下代码:

其中,analogRead(int pin),是模拟输入函数,他把5V电压分为1024份,也就是说,输出值为0-1023,我设定当这个值大于1000,也就是4.8V差不多的时候判定为开,否则视为开关为关。

void setup(){
   Serial.begin(9600);
}
  
 void loop(){  
    handleSwitch();
}


void handleSwitch(){  
    int i;
    i=analogRead(5); //读取5号pin
    if(i>1000){    
      Serial.println("High");      
    } else{       
        Serial.println("Low");      
    }
}

之后运行一下程序,看一下串口监视器,情况并不是我们想象的那样乐观:

在输出结果里居然有很多High,可是我并没有按下开关,这是由于外界信号对开关的干扰导致的。

需要并联一个下拉电阻来克服这个问题

  • 下拉电阻

在开关的接口与GND之间接一个1K-10K Ω的电阻。其作用是当外界有干扰源的时候(不确定信号),在断开状态下,这个信号会通向GND从而被被电阻消耗掉。

这样连接电阻后,再运行代码,会发现一直输出Low,按下时输出High,没有干扰问题了。

之后就可以去连接电扇了,CPU风扇的Pin 1,Pin2,还是连接电池的正极,负极,pin 3,连接到Arduino的Pin 6, Pin 4连接到 Arduino的Pin 3 。我又加了3个LED等分别代表低档,中档,高档三个档位的指示灯。(图中的电机是我随便放的部件,代指CPU风扇)

代码如下:

int lastStatus = 0; //储存上一次开关的状态
int counter = 0;   //计数器
int fanPulse = 6;	//风扇数据读取pin
unsigned long pulseDuration;

int pin_low_speed_led = 13;
int pin_mid_speed_led = 12;
int pin_high_speed_led = 11;

void setup(){
   pinMode(pin_low_speed_led, OUTPUT);
   pinMode(pin_mid_speed_led, OUTPUT);
   pinMode(pin_high_speed_led, OUTPUT);
   Serial.begin(9600);
   pinMode(fanPulse, INPUT);
   digitalWrite(fanPulse,HIGH);
   counter++;
   shift();
}
  
  void loop(){
  while(1)
  {
    handleSwitch();
  }
}

void updateLED(){  //更新led指示灯
  switch(counter%3){
    case 0: digitalWrite(pin_low_speed_led, HIGH);digitalWrite(pin_mid_speed_led, LOW);digitalWrite(pin_high_speed_led, LOW);break;
    case 1: digitalWrite(pin_mid_speed_led, HIGH);digitalWrite(pin_high_speed_led, LOW);digitalWrite(pin_low_speed_led, LOW);break;
    case 2: digitalWrite(pin_high_speed_led, HIGH);digitalWrite(pin_mid_speed_led, LOW);digitalWrite(pin_low_speed_led, LOW);break;
  }
}

void handleSwitch(){  //处理开关
  
    int i;
    i=analogRead(5);
    if(i>1000){
      
      if (lastStatus == 0){
        // Serial.println("High");
          counter++;
          shift();
      }
      lastStatus = 1;
      
    } else{
       if (lastStatus == 1){
        //  Serial.println("Low");
       }
       lastStatus = 0;
    }
     delay(10);
}

void shift(){  //换挡
  Serial.println("Current Fan Speed Mode:");
  switch(counter%3){
    case 0: Serial.println("LOW");analogWrite(3,0); delay(500);readPulse();break;
    case 1: Serial.println("MID");analogWrite(3,150); delay(500);readPulse();break;
    case 2: Serial.println("HIGH"); analogWrite(3,255);delay(500);readPulse();break;
  }
  updateLED();
}

void readPulse() {  //读取相关信息
  pulseDuration = pulseIn(fanPulse, LOW);
  double frequency = 1000000/pulseDuration;

  Serial.print("pulse duration:");
  Serial.println(pulseDuration);

  Serial.println("");
}

之后烧录程序,风扇就可以调速了,每次按下按钮就会调速,不同的指示灯会根据不同的速度亮。

好了,这次就介绍到这里,不过CPU风扇的扇叶是反的,必须对着底部才能吹到风哦~

我的博客MikeTech app现已登陆iPhone和Android

iPhone版下载
Android版下载

 

 

打赏

Leave a Reply

Your email address will not be published. Required fields are marked *