// 用esp32使用pid算法控制pwm占空比使得温度恒定的代码示例
// 假设使用DS18B20传感器测量温度,使用TIP120晶体管控制半导体制冷器件的电流
// 使用Arduino PID库和OneWire库
// 需要安装这两个库并引用它们
#include <PID_v1.h>
#include <OneWire.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <DallasTemperature.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "MI";
const char* password = "963852741";
String sliderValue = "25"; // 滑动条的初始值
// 定义DS18B20传感器的引脚
#define DS_PIN 19
// 定义PWM输出引脚
#define PWM_PIN 23
// 定义PID控制器的参数
#define KP 2.0 // 比例系数
#define KI 0.5 // 积分系数
#define KD 1.0 // 微分系数
// 定义温度设定点,单位为摄氏度
#define SETPOINT 25.0
// 定义PWM输出的范围,单位为百分比
#define MIN_PWM 0.0
#define MAX_PWM 100.0
// 创建OneWire对象
OneWire ds(DS_PIN);
// 创建DallasTemperature对象
DallasTemperature sensors(&ds);
double input; // 输入值
double output; // 输出值
double setpoint; // 设定值
int direction = DIRECT; // 控制方向
// 创建PID控制器对象
PID pid(&input, &output, &setpoint, KP, KI, KD, direction);
const char* PARAM_INPUT = "value"; // 滑动条的参数名
// 创建AsyncWebServer对象,监听80端口
AsyncWebServer server(80);
// HTML页面,包含一个滑动条
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Temperature Control Web</title>
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 2.3rem;}
p {font-size: 1.9rem;}
body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}
.slider {
-webkit-appearance: none;
margin: 14px;
width: 360px;
height: 25px;
background: #FFD65C;
outline: none;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 35px;
height: 35px;
background: #003249;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 35px;
height: 35px;
background: #003249;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Temperature Control</h2>
<p><span id="textSliderValue">%SLIDERVALUE%</span></p>
<p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="5" max="40" value="%SLIDERVALUE%" step="1" class="slider"></p>
<script>
function updateSliderPWM(element) {
var sliderValue = document.getElementById("pwmSlider").value;
document.getElementById("textSliderValue").innerHTML = sliderValue;
var xhr = new XMLHttpRequest();
xhr.open("GET", "/slider?value="+sliderValue, true);
xhr.send();
}
</script>
</body>
</html>
)rawliteral";
// 处理HTML页面中的变量
String processor(const String& var) {
if (var == "SLIDERVALUE") {
return sliderValue;
}
return String();
}
void setup() {
// 初始化串口通信,用于调试输出
Serial.begin(115200);
// 初始化PWM输出引脚,设置为输出模式
pinMode(PWM_PIN, OUTPUT);
// 连接WiFi网络
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
// 处理GET请求,返回HTML页面
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
request->send_P(200, "text/html", index_html, processor);
});
// 处理GET请求,获取滑动条的值
server.on("/slider", HTTP_GET, [](AsyncWebServerRequest* request) {
if (request->hasParam(PARAM_INPUT)) {
sliderValue = request->getParam(PARAM_INPUT)->value();
// Serial.print("Slider value: ");
// Serial.println(sliderValue);
// 赋值
double a = sliderValue.toDouble();
setpoint = a;
}
request->send(200, "text/plain", "OK");
});
// 启动服务器
server.begin();
// 设置温度设定点
setpoint = SETPOINT;
// 初始化PID控制器,设置模式为自动,方向为直接(即输出随输入增加而增加)
pid.SetMode(AUTOMATIC);
pid.SetOutputLimits(MIN_PWM, MAX_PWM);
pid.SetControllerDirection(DIRECT);
}
uint64_t ser_id;
void loop() {
// 获取当前温度,单位为摄氏度
sensors.requestTemperatures();
// 获取第一个传感器的温度值,单位为摄氏度
double input = sensors.getTempCByIndex(0);
// 如果温度读数无效,打印错误信息并返回
if (isnan(input)) {
Serial.println("Error reading temperature!");
return;
}
// 调用PID计算函数,得到输出值
pid.Compute();
// 根据输出值设置PWM占空比
analogWrite(PWM_PIN, output);
// 打印温度和输出值,用于调试
Serial.print("Temperature: ");
Serial.print(input);
Serial.print(",Output: ");
Serial.print(output);
Serial.print(",Target: ");
Serial.println(setpoint);
// 延时一秒,避免过于频繁的读取和输出
delay(1000);
}