Arduino教程13--自制风扇「DFR0100 」

2014-06-0513万
AI 快速预览详细 收起
本教程介绍了如何使用Arduino制作一个按钮控制的小风扇。项目名称为“自制风扇”,硬件清单包括继电器、直流电机和按钮等。最终效果是通过按钮控制风扇的启动和停止。难度等级适中,适合初学者和STEM教育场景。
【本篇课程内容于 2024年11月14日更新】
>本系教程配套硬件套件:【新版】Arduino入门套件 DFR0100


这次,我们会做一个用按钮控制小风扇。同时会接触两件新元件——继电器、直流电机。继电器,我们可以理解为是用较小的电流去控制较大电流的一种“自动开关”。在这里,继电器是用来控制电机转动的。

元件清单
Arduino教程13--自制风扇「DFR0100 」图4


硬件连接


按下图进行连线,按钮接线与项目【交通信号灯】类似,连接到数字2。按钮一端连接5V,另一端连接GND,并用一个220Ω的电阻作为下拉电阻,以防引脚悬空干扰。继电器有6个引脚,分别标有序号。1,2引脚为继电器的输入信号,分别接Arduino的数字引脚和GND。3,4,5,6为继电器输出的控制引脚,这里只使用4,6两个引脚。我们把继电器想成一个开关,开关也只要用到两个引脚。

Arduino教程13--自制风扇「DFR0100 」图1

图 1 自制风扇连线图


代码示例

Sample code:


  1. //项目 – 自制风扇
  2. int buttonPin = 2;                        // button连接到数字2
  3. int relayPin = 3;                         // 继电器连接到数字3
  4. int relayState = HIGH;                    // 继电器初始状态为HIGH
  5. int buttonState;                          // 记录button当前状态值
  6. int lastButtonState = LOW;                // 记录button前一个状态值
  7. long lastDebounceTime = 0;                  
  8. long debounceDelay = 50;                  //去除抖动时间
  9. void setup() {
  10.   pinMode(buttonPin, INPUT);
  11.   pinMode(relayPin, OUTPUT);
  12.   digitalWrite(relayPin, relayState);     // 设置继电器的初始状态
  13. }
  14. void loop() {
  15.   int reading = digitalRead(buttonPin);   
  16. //reading用来存储buttonPin的数据
  17.   
  18.   // 一旦检测到数据发生变化,记录当前时间
  19.   if (reading != lastButtonState) {   
  20.     lastDebounceTime = millis();
  21.   }
  22.   
  23.   // 等待50ms,再进行一次判断,是否和当前button状态相同
  24.   // 如果和当前状态不相同,改变button状态
  25.   // 同时,如果button状态为高(也就是被按下),那么就改变继电器的状态
  26.   if ((millis() - lastDebounceTime) > debounceDelay) {
  27.     if (reading != buttonState) {
  28.       buttonState = reading;
  29.       
  30.       if (buttonState == HIGH) {
  31.         relayState = !relayState;
  32.       }
  33.     }
  34.   }
  35.   digitalWrite(relayPin, relayState);
  36.   // 改变button前一个状态值
  37.   lastButtonState = reading;
  38. }
复制代码


代码回顾

代码的大部分内容,基本应该没有什么难度了,主要说下按键去抖的代码进行说明。
去抖代码如下:

  1. if (reading != lastButtonState) {   
  2.     lastDebounceTime = millis();
  3.   }
  4. if ((millis() - lastDebounceTime) > debounceDelay) {
  5.     if (reading != buttonState) {
  6.      ...
  7.     }
  8.   }
复制代码


reading有变化之后,不是立马就采取相应的行动,而是先“按兵不动”,先看看这个信号是不是“错误信号”,所以再等待一阵,(也就是通过millis来实现这个等待过程的),发现确实是前方发过来的正确信号,然后执行相关动作。这么做的原因是,按键在被按下时,会有个抖动的过程,而不是立马由低变高,或者由高变低。所以这个过程中,可能会产生错误信号,我们通过程序中的这种方法,来解决硬件上的这个问题。

硬件回顾

继电器

我们可以把继电器理解为一个“开关”,实际上是用比较小的电流去控制较大电流的“开关”。这里只是为了让初学者了解继电器工作原理,所以没有使用较大的电源器件,而是选用需要5V就能驱动的直流电机。
我们来看下继电器的内部构造:

Arduino教程13--自制风扇「DFR0100 」图2


这款继电器一共有6个引脚。1,2引脚是用来接Arduino数字引脚和GND。通过数字引脚来驱动继电器。1,2两端为线圈两端。Arduino给HIGH后,线圈中就有电流,线圈就会产生磁性(就像磁铁一样),吸合中间的触片(能听到“哒”一声),常开端(NO)就与公共端导通。相反,如果Arduino给LOW,线圈中没有电流,常闭端(NC)就与公共端导通。所以,电路中我们接了4,6引脚用于控制电机和LED的通断,(当然也可以用引脚3,6)。

直流电机、直流减速电机与舵机的区别

普通直流电机是我们接触比较多的电机。一般只有两个引脚,上电就能转,正负极反接则反向转动。如你所见,它做着周而复始的圆周运动,无法进行角度的控制,不过可以通过电机驱动板,可以对转速进行控制,不过由于普通电机转速过快,所以,一般不直接用在智能小车上。

直流减速电机是在普通电机加上了减速箱,这样便降低了转速,使得普通电机有更广泛的使用空间,比如可以用于智能小车上。同样也可以通过PWM来进行调速。

舵机也是一种电机,它使用一个反馈系统来控制电机的位置,可以用来控制角度。所以,舵机经常用来控制一些机器人手臂关节的转动。


示例代码下载附件Moter_Fan_Chinese.rar

下一篇教程:Arduino教程 14--红外遥控灯


DFRobot版权所有,欢迎转载。
转载请务必标注来源: DF创客社区+作者姓名+原文网址。

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(29)
正版2025
正版2025
10年前(2015年)就对大家造成困扰的问题,一直没有个明确的解释。
就是那个通电风扇就转一会儿然后停止的问题,
我来说一下吧,
教程上关于继电器引脚的说明错了,实际上5号是常开端(NO),6号是常闭端(NC),按照教程上的接线法和代码,电机正极是连在继电器6号引脚的,上电瞬间就开始转动了,等到执行
void setup() {
digitalWrite(relayPin, relayState);   
}
因为继电器状态被设为高电平HIGH,6号断开,5号连通,风扇反而停止了。
接下来就一切正常了,接收按钮的信号,继电器正常工作。
正版2025
正版2025回复正版2025
要想解决这个问题也很简单,电机正极、发光二极管正极都接继电器5号引脚(常开端),继电器初始状态设置为LOW:
int relayState = LOW; //继电器初始状态设为LOW,
因为接的是常开端,所以上电时电机、指示灯都是不通电的,不会工作。
执行setup时,因为继电器设置的初始状态为LOW,电机、指示灯仍然是不会工作的。
然后就能正常接收按钮信号,正常工作了。
johnhuxley
johnhuxley
接线图里的LED灯好像接错了,220R电阻接到正极才亮了起来,按照上图接到负极有点弱弱微光,害怕击穿,赶紧换到正极后正常发亮控制,下图里还没接马达。
在水里窒息的鱼
在水里窒息的鱼

常开端,常闭端这张图,是指1接到高电平状态下,5是常闭端;1接到低电平状态下,5是常开端。这么理解对么?
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
千南
千南
谢谢指导,学习了
绝地智者
绝地智者
厉害了,新手来顶一顶帖子,加油学习~
Shuuei
Shuuei
想调电机转速。两个想当然的想法,均未达到预期效果。
第一个方案是想着在6脚下接一个10k电位器,通过分压来达到电压不同转速不同的效果。结果失败,一动不动。
于是第二个方案,想着通过analogin来读取电位器电压,pwm口接继电器4脚依据模拟口输入来供电电压值。结果是转动了,但都是低速转动,不对旋钮调节做出响应。
想想两个原因是否均为电流不足,130马达参考电流300-400mA,arduino引脚输出最大40mA,至于10k电位器分压... 所以是想当然了。
请问:
1、不知道能不能加个三极管放大下电流来达到驱动效果
2、不知道电机驱动版是什么原理
Shuuei
Shuuei
感觉注释中的“等待50ms”会让人产生误解,以为是有个delay(50)的语句漏写了。但是想想应该是含在紧接着的if语句中的debounceDelay中,不直接delay(50)而设置抖动时间变量是为了照顾不同批次按键质量不一导致的抖动时间有长有短吗?
esojourn
esojourn
请问这个LED是负级接电阻的。和前面的例子不一样。这样也没问题是吗?
shijinxianzhe
shijinxianzhe
学习啦!
Cherry_island
Cherry_island
按照原接线图,一接上风扇就会转动,按键开关并没有起到任何作用;
后面仔细检查了一下,发现不是代码的问题;而是按键开关哪里的接线有问题;数字信号控制口的2引脚那跟线不应该接按键开关的GND那个出接口,要换到高电平的那个入接口;
最后观察到的现象就是开始风扇转动,按键开关按下风扇停止转动;再按,风扇重新开始转动
木龙小驴
木龙小驴
我也遇到过上面朋友的问题,就是点开开关,会转大概1s左右,然后电机停止,灯泡灭。
如果把电机拆下来的话,灯泡都是正常的。
是不是电压太小的缘故????求明白的大神给小弟解释
Cherry_island
Cherry_island回复木龙小驴
原电路图接线有问题,数字信号控制口的2引脚那跟线不应该接按键开关的GND那个出接口,要换到高电平的那个入接口;这样就成功了;
1522631876
1522631876
老师 我想问一下
if (reading != lastButtonState)这句last ButtonState初始值是LOW
if (reading != buttonState) 这句buttonState 没有初始值,前面也没有赋值语句,我想知道reading是怎么和buttonState比较的
1522631876
1522631876回复Cain
哦哦 好的 谢谢你啦
Cain
Cain回复1522631876
int 的默认值是0,也就是low
EricKong
EricKong
我接通电源也是直接电机转了,所以我把电机放在继电器5脚,默认relayState=LOW。
另外我有个问题是关于直流电机对IR的干扰,我用IR电源键控制继电器(开关)进而控制直流电机,启动电机没有问题,但是电机一旦启动,
用于监控红外的串口就是各种错误码刷屏了,根本停不下来。。。
[code]
void loop()
{
//是否接收到解码数据,把接收到的数据存储在变量results中
if (irrecv.decode(&results))
{
//接收到的数据以16进制的方式在串口输出
Serial.println(results.value, HEX);
//如果红外的电源键,则处理直流电机开关(继电器)
if(results.value == 0xFD00FF)
{
relayState = !relayState; // 取反
digitalWrite(relayPin,relayState); // 改变继电器状态
}
irrecv.resume(); // 继续等待接收下一组信号
}
}
[/code]
Cain
Cain回复EricKong
直流电机干扰一是保证供电足,二是在电击两端加电容滤波