[作业贴] DIY一个水温pwm控制器

ZORBYY-avatar

ZORBYY

2021-11-28T03:39:53+00:00

1.材料
Arduino Nano ¥13
[img]https://img.nga.178.com/attachments/mon_202111/30/9aQ2p-fdqnK2iT3cSm8-m8.jpg.thumb.jpg[/img]
BY 10K 测温堵头 ¥21
[img]https://img.nga.178.com/attachments/mon_202111/30/9aQ2p-cdm0KrT1kSb4-b4.jpg.thumb.jpg[/img]

洞洞板、跳线、2.54mm杜邦线插针插座、10K电阻 ¥5

2.软件实现
利用arduino内部Timer2计时器,通过PD3端口输出19.8KHz可调占空比的方波。A0端口测量探头电压,与预设温度比较产生err信号,输入PID控制模块,控制pwm信号。USB转串口可以从软件输入预设温度。
采用PID控制方法比BIOS使用的温度曲线的好处在于调整比较方便,只需设置一个参数,水温就会维持在设置值,风扇转速会根据发热量自动变化。
我看了楼下推荐的贼船控制器,貌似也是用PID控制水温恒定的[s:ac:哭笑]
arduino 代码 ...
#include "wiring_private.h"

int Monitor, Target = 363; // 5.5/(10+5.5)*1023=363
byte Output, off_flag = 0; // 1-byte 0-255
int err; // 2-bytes
float Kp = 1, Ki = 0.00001, Ep, Ei = 0; // Kp Ki 都是正值
int U;
char cmd;
int B3435[] = {750, 741, 732, 723, 714, 705, 696, 686, 677, 667, 658, 648, 638, 629, 619, 609, 599, 590, 580, 570, 560, 550, 541, 531, 521, 512, 502, 492, 483, 474, 464, 455, 446, 437, 428, 419, 410, 402, 393, 385, 377, 368, 360, 352, 345, 337, 329, 322, 315, 308, 301, 294, 287, 280, 274, 267, 261, 255, 249, 243, 237, 232, 226, 221, 216, 211, 206, 201, 196, 191, 187};
int B3950[] = {784, 774, 765, 755, 745, 734, 724, 714, 703, 692, 681, 670, 659, 648, 637, 625, 614, 603, 591, 580, 568, 557, 545, 534, 523, 512, 500, 489, 478, 467, 456, 446, 435, 424, 414, 404, 394, 384, 374, 364, 355, 346, 337, 328, 319, 310, 302, 294, 286, 278, 270, 263, 255, 248, 241, 234, 228, 221, 215, 209, 203, 197, 191, 186, 181, 175, 170, 165, 161, 156, 151};

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(PD3, OUTPUT);
digitalWrite(PD3, LOW);
// datasheet section 17.11
OCR2A = 100;
OCR2B = 20;
TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // COM2B1:0=0b10 WGM2:0=0b111
TCCR2B = _BV(WGM22) | _BV(CS21); // CS22:0=0b010 prescaler=8 16MHz/8
}

void loop() {
delay(1); // 1ms
Monitor = analogRead(A0); // read the input pin
err = Target - Monitor; // NTC电阻的温度越高分压越小
Ep = Kp * err;
Ei += Ki * err;
U = int(Ep + Ei);
if (err < 0 && Ei < 0) {
Ei = 0;
}
else if (err > 0 && Ei > 100) {
Ei = 100;
}

if (U > 100) {
Output = 100;
}
else if (U < 20) { // 小于20%停转
Output = 0;
}
else {
Output = byte(U);
}

if (Output == 0) {
if (off_flag == 0) {
cbi(TCCR2A, COM2B1);
//digitalWrite(6, LOW);
off_flag = 1;
}
}
else {
if (off_flag > 0) {
sbi(TCCR2A, COM2B1);
off_flag = 0;
}
OCR2B = Output;
}

if (Serial.available() > 0) { //监测串口缓存,当有数据输入时,执行下面语句
cmd = char(Serial.read());
if (cmd == 'W') { // 配置目标值
byte Target_b[2];
if (Serial.readBytes(Target_b, 2) == 2) {
Target = Target_b[0] + Target_b[1] * 0x100;
}
}
else if (cmd == 'S') {
byte celsius[1];
//celsius = Serial.read();
Serial.readBytes(celsius, 1);
//Serial.print(celsius[0]);
Target = (celsius[0] >= 0 && celsius[0] < 70) ? B3435[celsius[0]] : Target;
}
else if (cmd == 'R') { // reset Target
Target = 363;
}
else if (cmd == 'M') { // 读取测量值
Serial.print(Monitor);
}
else if (cmd == 'T') { // 读取目标值
Serial.print(Target);
}
else if (cmd == 'P') {
Serial.print(Ep);
}
else if (cmd == 'I') {
Serial.print(Ei);
}
}
}
c

3.电路设计
电路很简单,用10K电阻和探头串联测量分压,即可得到温度信息。这个红黑的飞线是用来接主板前置USB插座的,如果不需要软件调节水温可以不接,直接用固件里面的默认水温。
[img]https://img.nga.178.com/attachments/mon_202111/30/9aQ2p-5yqeK24T3cSsg-g0.jpg.medium.jpg[/img]

4.效果
写了一个python控制的小软件,可以实时显示水温、PWM占空比,用滑块设置温度目标。让显卡跑测试功率基本恒定,风扇曲线很平稳,第一张图是设置水温40度稳定的风扇转速,然后设置到38度,风扇转速如图2变化。
[img]https://img.nga.178.com/attachments/mon_202112/01/9aQ2p-g1bbK16T3cSnr-60.jpg.medium.jpg[/img]
[img]https://img.nga.178.com/attachments/mon_202112/01/9aQ2p-3pkvK1tT3cSz3-60.jpg.medium.jpg[/img]

改变显卡电压,提高功率,从130W增加到230W,整体水温变化不超过1度就达到稳定。
[img]https://img.nga.178.com/attachments/mon_202112/01/9aQ2p-bqaoK11T3cSsg-3e.jpg.medium.jpg[/img]
JcDUBx-avatar

JcDUBx

好东西 适合主板没有水温跳线的
KG-avatar

KG

KY一下[img]http://img4.nga.cn/ngabbs/post/smile/a2_30.png[/img]
贼船指挥官也才200
sundaze-avatar

sundaze

[s:ac:哭笑]调转速还pid啊
ZORBYY-avatar

ZORBYY

Reply to [pid=569977221,29653218,1]Reply[/pid] Post by [uid=43057376]这真的是一个随便打的ID[/uid] (2021-11-30 18:28)

随便尝试一下[s:ac:哭笑]把Ki去掉就是正常曲线控制