1简介

这段代码是一个基于ESP32开发板的PWM控制器,可以通过网页输入控制参数并显示在屏幕上,通过PWM输出引脚控制风扇的转速,还可以测量风扇的转速并在屏幕上显示。此外,代码还具备显示当前时间、显示Wi-Fi连接信息等功能。

这里用的是合宙Air101

2函数用途

  1. display_value(): 显示当前数值在屏幕上,包括当前数值和方波图案。

  2. add_value(): 增加当前数值,每次增加10,如果超过100则不再增加。

  3. dec_value(): 减少当前数值,每次减少10,不会小于0。

  4. handle_post(): 处理POST请求。

  5. handle_root(): 建立一个网页。

  6. display_wifi_info(): 在屏幕上显示 Wi-Fi 的 SSID 和密码。

  7. display_time(): 在屏幕上显示当前时间。

  8. set_pwm_output(): 设置IO13输出PWM波,占空比为当前数值。

  9. measure_fan_speed(): 测量风扇的转速。

  10. get_fan_speed(): 获取风扇的转速。

  11. display_fan_speed(): 在屏幕上显示风扇的转速。

  12. setup(): 设备的初始化设置,包括屏幕初始化、显示信息设置、WiFi连接等。

  13. 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\">&nbsp;</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控制器,可网页操作相关推荐

  1. ESP32 入门笔记03:PWM (ESP32 for Arduino IDE)

    先导知识 ESP32 入门笔记01:开发板信息.开发环境搭建以及学资料准备 ESP32 入门笔记02: GPIO参考指南 ESP32 有一个 LED PWM 控制器,具有 16 个独立通道,可配置为生 ...

  2. 乐鑫Esp32学习之旅⑦ esp32上利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。(附带Demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  3. 计算机硬盘 电机 利用,如何利用坏硬盘来做一个超强风扇,变废为宝 利用坏硬盘来做一个超强风扇,变废为宝的方法...

    今天给大家带来如何利用坏硬盘来做一个超强风扇,变废为宝,利用坏硬盘来做一个超强风扇,变废为宝的方法,让您轻松解决问题. 店里好多坏硬盘,回收了又值不了几个钱.今天无事,突发奇想,为什么不做个7200风 ...

  4. 天气太冷不想出被窝?来DIY一个离线语音控制器

    成就一番伟业的唯一途径就是热爱自己的事业.如果你还没能找到让自己热爱的事业,继续寻找,不要放弃.跟随自己的 心,总有一天你会找到的. --乔布斯   你去关灯,你去,你去,..我去..小伙伴们有没有在 ...

  5. 利用ESP32驱动控制步进电机驱动器:MS2806

    简 介: 对于步进电机MS-2806进行初步测试,但在配置PUL,DIR的作用下,步进电机没有运动.初步估计可能改驱动器已经损坏. 关键词: MS2806,步进电机 #mermaid-svg-NHbJ ...

  6. 【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏

    实验使用的硬件,软件平台使用Arduino IDE(见<[花雕体验]15 尝试搭建Beetle ESP32 C3之Arduino开发环境>) WS2812B 是一个集控制电路与发光电路于一 ...

  7. 快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server

    快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server 附:基于 Nodejs 的服务器后端的框架用的比较多的是 Koa : github/kaojs/koa 但本文这里 ...

  8. Linux利用platform_driver和设备树实现PWM驱动

    Linux利用platform_driver和设备树实现PWM驱动 字符设备PWM驱动 一.PWM驱动的硬件资源 1.PWM工作原理 2.PWM电路原理 3.PWM内部结构 二.具体代码 1.设备树 ...

  9. 如何利用laragon框架制作一个简单的应用?

    如何利用laragon框架制作一个简单的应用? 一.搭建环境 1. 安装Laragon 1.1 打开安装包用的语言 选择自己习惯用的语言 1.2 选择安装地址 1.3 选择Next,开始install ...

最新文章

  1. Python ssh连接Linux服务器报Incompatible ssh peer (no acceptable kex algorithm) 解决方法
  2. 有多少人在51job上找到工作_打工人都是人上人的原因找到了!
  3. 使用Spring Boot 2通过OAuth2和JWT进行集中授权
  4. 从创业失败中学到的七条教训
  5. java请求超时异常捕获_我异常了,快来捕获我,Java异常简述
  6. 【python】dict4ini和xmltodict模块用途
  7. 【工业机器人】全球工业机器人详细产业链梳理!
  8. 社招/实习/春招 | 字节跳动 | 抖音-隐私合规团队 | 北京/杭州 【岗位急招,部门直推,hc多多,欢迎投递~~~】
  9. Egret MovieClip2
  10. 苹果成美国历史上市值最大公司
  11. 几个吓尿了的公众号,前几个你不可能没听过
  12. 单纯版九九乘法口诀表
  13. itext 5.3.0实现对pdf文件添加(文字和图片)水印
  14. 一个Java菜鸟的学习之道~~~
  15. office办公软件插件推荐word插件excel插件ppt插件
  16. 修改C盘下用户的文件名的一些坑!!!
  17. 万能实体类(pageDate)
  18. Win10如何彻底禁用小娜?彻底禁用小娜的方法
  19. php模式设计之 适配器模式
  20. “喜茶Go”微信小程序新零售商业实战案例经验分享-概述

热门文章

  1. 了解通配符 SSL 证书和 SAN SSL
  2. 好看的二次元实时时钟404单页模板-刷新换图片
  3. 【IOG】Interactive Object Segmentation With Inside-Outside Guidance全文翻译
  4. 机器学习——K近邻算法(KNN)及其python实现
  5. IIR数字滤波器设计50Hz陷波器(MATLAB代码)
  6. Intel® 82801AA (ICH) and Intel® 82801AB (ICH0) I/O Controller Hub Datasheet
  7. 函数式编程是如何提升代码的扩展性
  8. Global.asax 文件的作用
  9. 博通包办新iPhone的非射频芯片,每台收入10美金
  10. 博通被阻收购高通:项庄舞剑意在哪