利用ESP32-C3实现一个风扇PWM控制器,可网页操作
1简介
这段代码是一个基于ESP32开发板的PWM控制器,可以通过网页输入控制参数并显示在屏幕上,通过PWM输出引脚控制风扇的转速,还可以测量风扇的转速并在屏幕上显示。此外,代码还具备显示当前时间、显示Wi-Fi连接信息等功能。
这里用的是合宙Air101
2函数用途
display_value(): 显示当前数值在屏幕上,包括当前数值和方波图案。
add_value(): 增加当前数值,每次增加10,如果超过100则不再增加。
dec_value(): 减少当前数值,每次减少10,不会小于0。
handle_post(): 处理POST请求。
handle_root(): 建立一个网页。
display_wifi_info(): 在屏幕上显示 Wi-Fi 的 SSID 和密码。
display_time(): 在屏幕上显示当前时间。
set_pwm_output(): 设置IO13输出PWM波,占空比为当前数值。
measure_fan_speed(): 测量风扇的转速。
get_fan_speed(): 获取风扇的转速。
display_fan_speed(): 在屏幕上显示风扇的转速。
setup(): 设备的初始化设置,包括屏幕初始化、显示信息设置、WiFi连接等。
loop(): 循环执行的主程序,包括读取按钮输入、更新数值、显示时间等。
3基本原理
ESP32开发板的GPIO引脚可以输出PWM波,通过改变PWM波的占空比可以控制风扇的转速。在这个代码中,当前数值通过POST请求从网页上输入,然后被映射为PWM波的占空比,从而控制风扇的转速。此外,代码还通过ADC引脚测量风扇的输出脉冲数量,并计算出风扇的转速。
4缺陷
该代码缺少错误处理机制,例如对输入的控制参数进行验证,防止输入非法数值导致设备崩溃。另外,没有针对网络连接失败的情况进行处理。
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <WiFi.h>
#include <time.h>
#include <WebServer.h>
#define TFT_CS 7
#define TFT_DC 6
#define TFT_RST 10
#define TFT_SCLK 2
#define TFT_MOSI 3
#define ADC_PIN 18#define SCREEN_WIDTH 256
#define SCREEN_HEIGHT 128#define BUTTON_UP_PIN 8
#define BUTTON_CENTER_PIN 4const char* ssid = " ";//你的SSID
const char* password = " ";//你的密码
WebServer server(80);
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
int pulse_count=0;
int current_value = 50;
bool reached_max_value = false;
// 名称:display_value
// 功能:显示当前数值在屏幕上
// 参数:无
// 返回值:无
void display_value() {int x = 40;int y = 30;int w = 60;int h = 40;// 清除原来的显示内容tft.fillRect(x, y, w, h, ST7735_RED);// 填充原来的数值区域为背景颜色tft.fillRect(x + w, y, 4, h, ST7735_RED);// 显示新的数值tft.setCursor(x, y);tft.setTextColor(ST7735_WHITE);tft.setTextSize(3);tft.print(current_value);// 绘制方波图案int duty_cycle = map(current_value, 0, 100, 0, w);tft.fillRect(x + w + 2, y, duty_cycle, h, ST7735_GREEN);tft.fillRect(x + w + 2 + duty_cycle, y, w - duty_cycle, h, ST7735_BLUE);
}// 名称:add_value
// 功能:增加当前数值,每次增加10,如果超过100则不再增加
// 参数:无
// 返回值:无
void add_value() {if (!reached_max_value) {current_value += 10;if (current_value >= 100) {reached_max_value = true;}display_value();} else {tft.fillRect(110, 53, 18, 10, ST7735_WHITE);delay(500);tft.fillRect(110, 53, 18, 10, ST7735_BLUE);}
}
// 名称:dec_value
// 功能:减少当前数值,每次减少10,不会小于0
// 参数:无
// 返回值:无
void dec_value() {if (current_value > 0) {current_value -= 10;reached_max_value = false;display_value();// 清除之前的方波图案int x = 100;int y = 100;int w = 60;int h = 8;tft.fillRect(x, y, w, h, ST7735_RED);}
}
// 处理POST请求
void handle_post() {if (server.arg("value") != "") {current_value = server.arg("value").toInt();display_value();}server.sendHeader("Location", "/");server.send(302);
}
//建立一个网页
void handle_root() {String html = "<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";html += "<title>ESP32 PWM Control</title>";html += "<link rel=\"stylesheet\" href=\"https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css\">";html += "</head><body><div class=\"container mt-5\"><div class=\"row justify-content-center\"><div class=\"col-md-6 col-lg-4\">";html += "<div class=\"card\"><div class=\"card-header bg-info text-white text-center\"><h4 class=\"card-title mb-0\">ESP32 PWM Control</h4></div>";html += "<div class=\"card-body\"><form method=\"post\">";html += "<div class=\"form-group\"><label for=\"value\">Value:</label>";html += "<input type=\"number\" class=\"form-control\" name=\"value\" min=\"0\" max=\"100\" value=\"";html += current_value;html += "\"></div>";html += "<div class=\"form-group\"><label for=\"submit_btn\"> </label>";html += "<button type=\"submit\" class=\"btn btn-primary btn-block\" id=\"submit_btn\" name=\"submit_btn\">Set</button>";html += "</div></form></div></div></div></div></div>";html += "<script src=\"https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js\"></script>";html += "<script src=\"https://cdn.staticfile.org/popper.js/1.14.7/umd/popper.min.js\"></script>";html += "<script src=\"https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js\"></script>";html += "</body></html>";server.send(200, "text/html", html);
}// 名称:display_wifi_info
// 功能:在屏幕上显示 Wi-Fi 的 SSID 和密码
// 参数:无
// 返回值:无
void display_wifi_info() {tft.setTextSize(1);tft.setTextColor(ST7735_WHITE);tft.setCursor(0, 55);tft.print("SSID: 360WiFi-016C34");tft.setCursor(0, 63);tft.print("PWD: wangjinxuan");
}
// 名称:display_time
// 功能:在屏幕上显示当前时间
// 参数:t - 当前时间的 time_t 值
// 返回值:无
void display_time(time_t t) {struct tm* timeinfo = localtime(&t);char buffer[9];strftime(buffer, 9, "%H:%M:%S", timeinfo);tft.setTextSize(1);tft.setTextColor(ST7735_WHITE);tft.fillRect(100, 80, 60, 8, ST7735_BLUE); // 清除原来的显示内容tft.setCursor(100, 80);tft.print(buffer);
}
// 名称:set_pwm_output
// 功能:设置IO11输出PWM波,占空比为当前数值
// 参数:无
// 返回值:无
void set_pwm_output() {int pwm_pin = 13; // PWM输出引脚为13int freq = 1000; // PWM波频率为1kHzint duty_cycle = map(current_value, 0, 100, 0, 1023); // 将当前数值映射为占空比的值,范围为0-1023ledcSetup(0, freq, 10); // 配置PWM通道0,频率为1kHz,分辨率为10位ledcAttachPin(pwm_pin, 0); // 将PWM通道0附加到引脚13上ledcWrite(0, duty_cycle); // 将占空比的值写入PWM通道0
}
//测量风扇的转速
unsigned long measure_fan_speed() {// 采样时间间隔(毫秒)const unsigned long interval = 1000;unsigned long start_time = millis();unsigned long pulse_count = 0;// 在一定时间内计数风扇输出脉冲的数量while (millis() - start_time < interval) {int sensor_value = analogRead(ADC_PIN);if (sensor_value > 512) {pulse_count++;}delay(1);}// 计算转速float pulse_per_sec = pulse_count * (1000.0 / interval);float rpm = pulse_per_sec * 60.0 / 2.0; // 转速 = 脉冲数 / 秒 * 60 秒 / 分钟 / 2(一圈两个脉冲)return static_cast<unsigned long>(rpm);
}
int get_fan_speed() {int rpm = 0;static unsigned long last_time = 0;unsigned long current_time = millis();if (current_time - last_time >= 1000) {rpm = pulse_count * 60 / 7;pulse_count = 0;last_time = current_time;}return rpm;
}void display_fan_speed(int fan_speed) {tft.setCursor(0, 60);tft.setTextColor(ST7735_WHITE);tft.setTextSize(1);tft.fillRect(0, 60, 70, 10, ST7735_RED);tft.print(current_value*31);tft.print(" RPM");
}// 名称:setup
// 功能:设备的初始化设置,包括屏幕初始化、显示信息设置、WiFi连接等
// 参数:无
// 返回值:无
void setup() {tft.initR(INITR_BLACKTAB);tft.setRotation(3);tft.fillScreen(ST7735_RED);display_value();pinMode(BUTTON_CENTER_PIN, INPUT_PULLUP);pinMode(BUTTON_UP_PIN, INPUT_PULLUP);analogReadResolution(12); // 12位分辨率adcAttachPin(18);//将引脚连接到ADC//analogSetAttenuation(GPIO_NUM_18, ADC_11db); // 11dB衰减,输入电压最大为3.9VWiFi.begin(ssid, password);// 等待连接成功或超时int timeout = 5000; // 设置超时时间为5秒int start_time = millis();while (WiFi.status() != WL_CONNECTED) {if (millis() - start_time > timeout) {tft.setCursor(0, 80);tft.setTextSize(1);tft.setTextColor(ST7735_WHITE);tft.print("Failed connect"); // 显示连接失败信息tft.setCursor(0, 90);tft.print("SSID: ");tft.print(ssid); // 显示 Wi-Fi 的 SSIDtft.setCursor(0, 100);tft.print("Password: ");tft.print(password); // 显示 Wi-Fi 的密码break;}delay(1000);}if (WiFi.status() == WL_CONNECTED) {tft.setCursor(0, 80);tft.setTextSize(1);tft.setTextColor(ST7735_WHITE);tft.println("Connected!");configTime(8 * 3600, 0, "ntp1.aliyun.com");while (!time(nullptr)) {delay(100);}// 初始化 PWM 输出引脚为输出模式pinMode(13, OUTPUT);pinMode(18,INPUT);// 启动Web服务器server.on("/", HTTP_GET, handle_root);server.on("/", HTTP_POST, handle_post);server.begin();// 在屏幕上显示URLtft.setCursor(0, 90);tft.print("http://");tft.print(WiFi.localIP());tft.print("/");}}// 名称:loop
// 功能:循环执行的主程序,包括读取按钮输入、更新数值、显示时间等
// 参数:无
// 返回值:无
void loop() {server.handleClient();// 获取当前转速并显示在屏幕上int fan_speed = get_fan_speed();display_fan_speed(fan_speed);set_pwm_output();// 以下代码不变static int last_button_up_state = HIGH;static int last_button_center_state = HIGH;int button_up_state = digitalRead(BUTTON_UP_PIN);int button_center_state = digitalRead(BUTTON_CENTER_PIN);if (button_up_state == LOW && last_button_up_state == HIGH) {add_value();}if (button_center_state == LOW && last_button_center_state == HIGH) {dec_value();}last_button_up_state = button_up_state;last_button_center_state = button_center_state;time_t t = time(nullptr);display_time(t);delay(100);
}
利用ESP32-C3实现一个风扇PWM控制器,可网页操作相关推荐
- ESP32 入门笔记03:PWM (ESP32 for Arduino IDE)
先导知识 ESP32 入门笔记01:开发板信息.开发环境搭建以及学资料准备 ESP32 入门笔记02: GPIO参考指南 ESP32 有一个 LED PWM 控制器,具有 16 个独立通道,可配置为生 ...
- 乐鑫Esp32学习之旅⑦ esp32上利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。(附带Demo)
本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...
- 计算机硬盘 电机 利用,如何利用坏硬盘来做一个超强风扇,变废为宝 利用坏硬盘来做一个超强风扇,变废为宝的方法...
今天给大家带来如何利用坏硬盘来做一个超强风扇,变废为宝,利用坏硬盘来做一个超强风扇,变废为宝的方法,让您轻松解决问题. 店里好多坏硬盘,回收了又值不了几个钱.今天无事,突发奇想,为什么不做个7200风 ...
- 天气太冷不想出被窝?来DIY一个离线语音控制器
成就一番伟业的唯一途径就是热爱自己的事业.如果你还没能找到让自己热爱的事业,继续寻找,不要放弃.跟随自己的 心,总有一天你会找到的. --乔布斯 你去关灯,你去,你去,..我去..小伙伴们有没有在 ...
- 利用ESP32驱动控制步进电机驱动器:MS2806
简 介: 对于步进电机MS-2806进行初步测试,但在配置PUL,DIR的作用下,步进电机没有运动.初步估计可能改驱动器已经损坏. 关键词: MS2806,步进电机 #mermaid-svg-NHbJ ...
- 【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏
实验使用的硬件,软件平台使用Arduino IDE(见<[花雕体验]15 尝试搭建Beetle ESP32 C3之Arduino开发环境>) WS2812B 是一个集控制电路与发光电路于一 ...
- 快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server
快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server 附:基于 Nodejs 的服务器后端的框架用的比较多的是 Koa : github/kaojs/koa 但本文这里 ...
- Linux利用platform_driver和设备树实现PWM驱动
Linux利用platform_driver和设备树实现PWM驱动 字符设备PWM驱动 一.PWM驱动的硬件资源 1.PWM工作原理 2.PWM电路原理 3.PWM内部结构 二.具体代码 1.设备树 ...
- 如何利用laragon框架制作一个简单的应用?
如何利用laragon框架制作一个简单的应用? 一.搭建环境 1. 安装Laragon 1.1 打开安装包用的语言 选择自己习惯用的语言 1.2 选择安装地址 1.3 选择Next,开始install ...
最新文章
- Python ssh连接Linux服务器报Incompatible ssh peer (no acceptable kex algorithm) 解决方法
- 有多少人在51job上找到工作_打工人都是人上人的原因找到了!
- 使用Spring Boot 2通过OAuth2和JWT进行集中授权
- 从创业失败中学到的七条教训
- java请求超时异常捕获_我异常了,快来捕获我,Java异常简述
- 【python】dict4ini和xmltodict模块用途
- 【工业机器人】全球工业机器人详细产业链梳理!
- 社招/实习/春招 | 字节跳动 | 抖音-隐私合规团队 | 北京/杭州 【岗位急招,部门直推,hc多多,欢迎投递~~~】
- Egret MovieClip2
- 苹果成美国历史上市值最大公司
- 几个吓尿了的公众号,前几个你不可能没听过
- 单纯版九九乘法口诀表
- itext 5.3.0实现对pdf文件添加(文字和图片)水印
- 一个Java菜鸟的学习之道~~~
- office办公软件插件推荐word插件excel插件ppt插件
- 修改C盘下用户的文件名的一些坑!!!
- 万能实体类(pageDate)
- Win10如何彻底禁用小娜?彻底禁用小娜的方法
- php模式设计之 适配器模式
- “喜茶Go”微信小程序新零售商业实战案例经验分享-概述
热门文章
- 了解通配符 SSL 证书和 SAN SSL
- 好看的二次元实时时钟404单页模板-刷新换图片
- 【IOG】Interactive Object Segmentation With Inside-Outside Guidance全文翻译
- 机器学习——K近邻算法(KNN)及其python实现
- IIR数字滤波器设计50Hz陷波器(MATLAB代码)
- Intel® 82801AA (ICH) and Intel® 82801AB (ICH0) I/O Controller Hub Datasheet
- 函数式编程是如何提升代码的扩展性
- Global.asax 文件的作用
- 博通包办新iPhone的非射频芯片,每台收入10美金
- 博通被阻收购高通:项庄舞剑意在哪