基于Arduino UNO的智能温控风扇 您所在的位置:网站首页 风扇的电路图标志 基于Arduino UNO的智能温控风扇

基于Arduino UNO的智能温控风扇

2024-06-27 22:46| 来源: 网络整理| 查看: 265

基于Arduino UNO的智能温控风扇

本文主要介绍一个基于Arduino UNO的智能温控风扇demo,其主要实现两种切换模式,分别为自动模式以及手动模式。在自动模式下,风扇可根据DS18B20检测到的环境温度,并根据温度梯度达到不同风速,同时通过2Y0A21模块检测是否有人,若无人,则30s后关闭风扇;在手动模式下,可通过红外遥控以及按键控制风速。

文章目录 基于Arduino UNO的智能温控风扇前言一、硬件模块二、接线1.屏幕接线2.DS18B20接线3.2Y0A21接线4.驱动模块+电机接线5.红外接收器接线6.轻触按键接线 三、所需库四、源码1.整合代码:完整功能代码(直接接线、安装对应的库即可)2.测试代码:自动模式代码(采用U8g2lib库显示)3.测试代码:遥控模式代码(未显示温度、距离) 五、遇到的一些问题1.问题12.问题23.问题3

前言

本文主要介绍一个基于Arduino UNO的智能温控风扇demo,其主要实现两种切换模式,分别为自动模式以及手动模式。在自动模式下,风扇可根据DS18B20检测到的环境温度,并根据温度梯度达到不同风速,同时通过2Y0A21模块检测是否有人,若无人,则30s后关闭风扇;在手动模式下,可通过红外遥控以及按键控制风速。在这两种模式下,均实现在LCD12864屏幕上。显示实时温度以及距离,还有当前所处模式。

硬件模块包含:Arduino UNO板,LCD12864,DS18B20,2Y0A21,小电机,L298N(2.1A双路电机模块),红外遥控器(含红外接收器),轻触按键,上拉电阻,面包板,若干杜邦线。

在这里插入图片描述

一、硬件模块

硬件模块包含: 在这里插入图片描述 Arduino UNO板, 在这里插入图片描述 LCD12864, 在这里插入图片描述 DS18B20, 在这里插入图片描述 2Y0A21, 在这里插入图片描述 小电机, 在这里插入图片描述 L298N(2.1A双路电机模块), 在这里插入图片描述 红外遥控器(含红外接收器), 在这里插入图片描述 轻触按键, 上拉电阻,面包板,若干杜邦线。

二、接线

硬件模块包含:Arduino UNO板,LCD12864,DS18B20,2Y0A21,小电机,L298N(2.1A双路电机模块),红外遥控器(含红外接收器),轻触按键,上拉电阻,面包板,若干杜邦线。

1.屏幕接线

接线可参考链接: arduino如何驱动LCD12864显示器?(使用U8g2库)

LCD12864模块--------------------------------Arduino UNO模块 GND、PSB、BLK引脚--------------------------GND引脚 VCC、BLA引脚-----------------------------------5V引脚 RS引脚----------------------------------------------2引脚 R/W(SID)引脚-------------------------------------3引脚 E(CLK)引脚----------------------------------------4引脚 RST引脚--------------------------------------------5引脚

2.DS18B20接线

DS18B20模块----------------------------------Arduino UNO模块 GND引脚-------------------------------------------GND引脚 VCC引脚--------------------------------------------5V引脚 信号引脚---------------------------------------------6引脚

3.2Y0A21接线

2Y0A21模块----------------------------------Arduino UNO模块 GND引脚-------------------------------------------GND引脚 VCC引脚--------------------------------------------5V引脚 信号引脚--------------------------------------------A5引脚

4.驱动模块+电机接线

接线可参考链接: 2.5A双路电机驱动模块 正反转 PWM调速 双H桥 步进电机 超L298N

电机模块-----------------驱动模块--------------------Arduino UNO模块 a引脚--------------------MOTOR-A-----------------------10引脚 b引脚--------------------MOTOR-A-----------------------11引脚 ------------------------GND引脚(排针)---------------GND引脚

---------------------------2V-10V引脚--------------------外接电源5V ---------------------------GND引脚-----------------------外接电源GND

5.红外接收器接线

红外接收器模块-----------------------------Arduino UNO模块 GND引脚-------------------------------------------GND引脚 VCC引脚--------------------------------------------5V引脚 信号引脚---------------------------------------------7引脚

6.轻触按键接线

轻触按键模块-----------------------------Arduino UNO模块 1引脚-------------------------------------------GND引脚 2引脚--------------------------------------------A3引脚 2引脚----------------上拉电阻----------------5V引脚 同时2引脚接一个上拉电阻之后连到Arduino UNO模块5V引脚

三、所需库 IRremote库 版本:4.3.0OneWire库 版本:2.3.7DallasTemperature库 版本3.9.0U8glib库 版本1.19.1 四、源码 1.整合代码:完整功能代码(直接接线、安装对应的库即可) #include // #include #include #include #include #define irReceiverPin 7 #define motorPin1 10 #define motorPin2 11 #define ONE_WIRE_BUS 6 #define ds18b20TimeInterval 1000 #define pin A5 #define pushButton A3 IRrecv irrecv(irReceiverPin); decode_results results; //U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /*clock*/4, /*data*/3, /*cs*/2, /*reset*/5); U8GLIB_ST7920_128X64_4X u8g(4, 3, 2); OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer; unsigned long ds18b20Times = 0; unsigned long lastPersonDetectedTime = 0; float ds18b20Temp = 0; unsigned long manu_flag = 0; // 存储红外信号值 bool automaticMode = true; // 初始为自动模式 int buttonState = 0;// 按键次数 void setup() { Serial.begin(9600); irrecv.enableIRIn(); // u8g2.begin(); if ( u8g.getMode() == U8G_MODE_R3G3B2 ) { u8g.setColorIndex(255); // white } else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) { u8g.setColorIndex(3); // max intensity } else if ( u8g.getMode() == U8G_MODE_BW ) { u8g.setColorIndex(1); // pixel on } else if ( u8g.getMode() == U8G_MODE_HICOLOR ) { u8g.setHiColorByRGB(255,255,255); } sensors.begin(); sensors.getAddress(insideThermometer, 0); pinMode(pin, INPUT); pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(pushButton, INPUT); } void loop() { if (irrecv.decode(&results)) { if (results.value == 0xFFA25D) { // 如果按下红外遥控的 CH- 按钮 automaticMode = true; // 切换到自动模式 } else if (results.value == 0xFFE21D) { // 如果按下红外遥控的 CH+ 按钮 automaticMode = false; // 切换到遥控模式 } irrecv.resume(); // 准备接收下一个红外信号 } if (automaticMode) { controlFanAutomatic(); } else { controlFanManual(); } } void controlFanAutomatic() { if (millis() - ds18b20Times >= ds18b20TimeInterval) { ds18b20Times = millis(); sensors.requestTemperatures(); ds18b20Temp = sensors.getTempC(insideThermometer); uint16_t value = analogRead(pin); uint16_t range = get_gp2d12(value); // u8g2.firstPage(); u8g.firstPage(); do { u8g.setFont(u8g_font_6x10); // 使用较小的字体 u8g.drawStr(0, 12, "Auto"); // 第一行显示温度 u8g.drawStr(0, 24, "Temp:"); u8g.setPrintPos(40, 24); u8g.print(ds18b20Temp); u8g.print(" C"); // 第二行显示距离 u8g.drawStr(0, 36, "Distance:"); u8g.setPrintPos(60, 36); u8g.print(range); u8g.print(" mm"); // 如果检测到人,则更新上次检测到人的时间 if (range analogWrite(motorPin1, 40); analogWrite(motorPin2, 0); u8g.drawStr(40, 12, "Mode0"); } else if (ds18b20Temp >= 26 && ds18b20Temp analogWrite(motorPin1, 75); analogWrite(motorPin2, 0); u8g.drawStr(40, 12, "Mode2"); } else if (ds18b20Temp >= 28 && ds18b20Temp analogWrite(motorPin1, 150); analogWrite(motorPin2, 0); u8g.drawStr(40, 12, "Mode4"); } else if (ds18b20Temp >= 30) { analogWrite(motorPin1, 200); analogWrite(motorPin2, 0); u8g.drawStr(40, 12, "Mode5"); } } else { // 如果30秒内没有检测到人,则关闭电机 if (millis() - lastPersonDetectedTime >= 30000) { analogWrite(motorPin1, 0); analogWrite(motorPin2, 0); } } } while (u8g.nextPage()); } } // 计算距离 uint16_t get_gp2d12(uint16_t value) { if (value ds18b20Times = millis(); sensors.requestTemperatures(); ds18b20Temp = sensors.getTempC(insideThermometer); uint16_t value = analogRead(pin); uint16_t range = get_gp2d12(value); // u8g2.firstPage(); u8g.firstPage(); do { u8g.setFont(u8g_font_6x10); // 使用较小的字体 u8g.drawStr(0, 12, "Manu"); // 第一行显示温度 u8g.drawStr(0, 24, "Temp:"); u8g.setPrintPos(40, 24); u8g.print(ds18b20Temp); u8g.print(" C"); // 第二行显示距离 u8g.drawStr(0, 36, "Distance:"); u8g.setPrintPos(60, 36); u8g.print(range); u8g.print(" mm"); if (digitalRead(pushButton) == 0){ delay(20); while(digitalRead(pushButton) == 0); delay(20); buttonState++; if (buttonState == 6){ buttonState = 0; } } if (buttonState == 0) { // 按键0 analogWrite(motorPin1, 0); // 停止电机 analogWrite(motorPin2, 0); // u8g.drawStr(40, 12, "Mode0"); buttonState = 0; } else if (buttonState == 1) { // 按键1 analogWrite(motorPin1, 50); // analogWrite(motorPin2, 0); // u8g.drawStr(40, 12, "Mode1"); buttonState = 1; } else if (buttonState == 2) { // 按键2 analogWrite(motorPin1, 75); // analogWrite(motorPin2, 0); // u8g.drawStr(40, 12, "Mode2"); buttonState = 2; } else if (buttonState == 3) { // 按键3 analogWrite(motorPin1, 100); // analogWrite(motorPin2, 0); // u8g.drawStr(40, 12, "Mode3"); buttonState = 3; } else if (buttonState == 4) { // 按键4 analogWrite(motorPin1, 150); // analogWrite(motorPin2, 0); // u8g.drawStr(40, 12, "Mode4"); buttonState = 4; } else if (buttonState == 5) { // 按键5 analogWrite(motorPin1, 200); // analogWrite(motorPin2, 0); // u8g.drawStr(40, 12, "Mode5"); buttonState = 5; } if (irrecv.decode(&results)) { // 打印接收到的红外信号的值和位数 Serial.print("irCode: "); Serial.print(results.value, HEX); Serial.print(", bits: "); Serial.println(results.bits); manu_flag = results.value; // 根据不同的红外信号值来控制电机转速 if (results.value == 0xFF6897) { // 按键0 buttonState = 0; } else if (results.value == 0xFF30CF) { // 按键1 buttonState = 1; } else if (results.value == 0xFF18E7) { // 按键2 buttonState = 2; } else if (results.value == 0xFF7A85) { // 按键3 buttonState = 3; } else if (results.value == 0xFF10EF) { // 按键4 buttonState = 4; } else if (results.value == 0xFF38C7) { // 按键5 buttonState = 5; } else { // 其他按键值不进行任何操作 } delay(300); irrecv.resume(); // 准备接收下一个红外信号 } }while (u8g.nextPage()); } } 2.测试代码:自动模式代码(采用U8g2lib库显示) #include #include #include #include U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /*clock*/4, /*data*/3, /*cs*/2 , /*reset*/5); #define ONE_WIRE_BUS 6 // DS18B20 #define ds18b20TimeInterval 1000 #define pin A5 // 2Y0A21 // 89号引脚控制一个电机的两个引脚 const int motorPin1 = 10; // 第一个引脚连接到 8 号引脚 const int motorPin2 = 11; // 第二个引脚连接到 9 号引脚 unsigned long lastPersonDetectedTime = 0; // 上次检测到人的时间 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer; unsigned long ds18b20Times = 0; float ds18b20Temp = 0; void setup() { u8g2.begin(); Serial.begin(9600); sensors.begin(); if (!sensors.getAddress(insideThermometer, 0)) { Serial.println("设备未上线!"); } Serial.println("设备上线!"); pinMode(pin, INPUT); //电机 pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); } void loop() { printData(); } void printData() { if (millis() - ds18b20Times >= ds18b20TimeInterval) { ds18b20Times = millis(); sensors.requestTemperatures(); ds18b20Temp = sensors.getTempC(insideThermometer); uint16_t value = analogRead(pin); uint16_t range = get_gp2d12(value); u8g2.firstPage(); do { u8g2.setFont(u8g2_font_6x10_tr); // 使用较小的字体 // 第一行显示温度 u8g2.drawStr(0, 12, "Temp:"); u8g2.setCursor(40, 12); u8g2.print(ds18b20Temp); u8g2.print(" C"); // 第二行显示距离 u8g2.drawStr(0, 24, "Distance:"); u8g2.setCursor(60, 24); u8g2.print(range); u8g2.print(" mm"); // 如果检测到人,则更新上次检测到人的时间 if (range analogWrite(motorPin1, 0); // analogWrite(motorPin2, 0); // } else if (ds18b20Temp>=26 && ds18b20Temp analogWrite(motorPin1, 75); // analogWrite(motorPin2, 0); // } else if (ds18b20Temp>=28 && ds18b20Temp analogWrite(motorPin1, 150); // analogWrite(motorPin2, 0); // } else if(ds18b20Temp>=30){ analogWrite(motorPin1, 200); // analogWrite(motorPin2, 0); // } } else{ if (millis() - lastPersonDetectedTime >= 10000) { analogWrite(motorPin1, 0); // analogWrite(motorPin2, 0); // } } } while (u8g2.nextPage()); } } // 计算距离 uint16_t get_gp2d12(uint16_t value) { if (value if (irrecv.decode(&results)) { // 打印接收到的红外信号的值和位数 Serial.print("irCode: "); Serial.print(results.value, HEX); Serial.print(", bits: "); Serial.println(results.bits); // 根据不同的红外信号值来控制电机转速 if (results.value == 0xFF6897) { // 按键0 analogWrite(motorPin1, 0); // 停止电机 analogWrite(motorPin2, 0); // } else if (results.value == 0xFF30CF) { // 按键1 analogWrite(motorPin1, 100); // analogWrite(motorPin2, 0); // } else if (results.value == 0xFF18E7) { // 按键2 analogWrite(motorPin1, 150); // analogWrite(motorPin2, 0); // } else if (results.value == 0xFF7A85) { // 按键3 analogWrite(motorPin1, 200); // analogWrite(motorPin2, 0); // } else { // 其他按键值不进行任何操作 } delay(300); irrecv.resume(); // 准备接收下一个红外信号 } } 五、遇到的一些问题 1.问题1

问题1:红外遥控测试时候会出现无论按什么键均打印FFFFFF的问题 原因分析:IRremote库版本过高 解决方法:换成低版本即可,本文所用版本的库能正常使用

参考方法链接: 【Arduino】红外遥控实验按遥控器没反应 解决

2.问题2

问题2:用Arduino UNO的5V给电机模块供电,电机转不动 原因分析:Arduino UNO上面的电源管理电流过低,不足以支撑电机转动 解决方法:外接5V电源给电机模块供电,同时注意要共地!

3.问题3

问题3:各模块代码整合的时候出现Arduino UNO的内存显示不足,例如

Sketch uses 1978 bytes (6%) of program storage space. Maximum is 32256 bytes. Global variables use 188 bytes (9%) of dynamic memory, leaving 1860 bytes for local variables. Maximum is 2048 bytes.

原因分析:经过测试发现,本项目中原本使用的U8g2lib库严重占用内存,换成小一些的屏幕显示库U8glib即可 解决方法:换成小一些的屏幕显示库U8glib即可

参考方法链接: 解决Arduino Uno上传代码时提示内存不足的问题



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有