|
楼主 |
发表于 2017-10-22 00:22
|
显示全部楼层
机器开始服役,发现一些问题,就是原来源码里,风扇的控制不够连续,例如CPU从42上升到43度,风扇因为提速,声音变化比较突兀,夜深人静工作的时候,会被转移注意力。所以修改了下源码,把风扇的速度变化的时候过度的更柔和,用最近10次温度的移动平均来做控制。
新的代码:
定义部分:
[mw_shl_code=bash,true]const int TEMP_AVG_CYCLE = 10;
int tempCpuAvg[TEMP_AVG_CYCLE];
int tempNorthAvg[TEMP_AVG_CYCLE];
long tempCpuAvgTotal;
long tempNorthAvgTotal;
int avgIndex = 0;[/mw_shl_code]
loop函数中PWM部分:
[mw_shl_code=cpp,true] // pwm
tempCpuAvgTotal = 0;
tempNorthAvgTotal = 0;
tempCpuAvg[avgIndex] = max(tempCpu1, tempCpu2) * 100;
tempNorthAvg[avgIndex] = tempNorth * 100;
avgIndex++;
if (avgIndex >= TEMP_AVG_CYCLE) {
avgIndex = 0;
}
for ( int i = 0; i < TEMP_AVG_CYCLE; ++i ) {
tempCpuAvgTotal += tempCpuAvg;
tempNorthAvgTotal += tempNorthAvg;
}
fanPwmMaster = map2(tempCpuAvgTotal / TEMP_AVG_CYCLE, TEMP_CPU_START, TEMP_CPU_MAX, 0, 254);
fanPwmNorth = map2(tempNorthAvgTotal / TEMP_AVG_CYCLE, TEMP_NORTH_START, TEMP_NORTH_MAX, 0, 254);
if (fanPwmMaster != fanPwmMaster_pre) {
analogWrite(PIN_MASTERFAN_PWM, fanPwmMaster);
//analogWrite(PIN_MASTERFAN2_PWM, fanPwmMaster);
fanPwmMaster_pre = fanPwmMaster;
}
if (fanPwmNorth != fanPwmNorth_pre) {
analogWrite(PIN_NORTHFAN_PWM, fanPwmNorth);
fanPwmNorth_pre = fanPwmNorth;
}[/mw_shl_code]
完整代码:
[mw_shl_code=cpp,true]#include <OneWire.h>
#include <DallasTemperature.h>
#include <PZEM004T.h>
// pin settings
#define PIN_MASTERFAN1_SPEED 2
#define PIN_MASTERFAN2_SPEED 3
#define PIN_NORTHFAN_SPEED 21
#define PIN_MASTERFAN_PWM 6
#define PIN_NORTHFAN_PWM 7
#define PIN_ONEWIRE_BUS 22
#define PIN_TOUCHPAD 53
#define PIN_LIGHT_SENSOR 15
#define PIN_SPEAKER 52
#define DELAY_REFRESH 1618
// lcd module: serial1
// power module: serial2
// consts
const int TEMP_CPU_START = 35 * 100;
const int TEMP_CPU_ALERT = 50 * 100;
const int TEMP_CPU_MAX = 55 * 100;
const int TEMP_NORTH_START = 40 * 100;
const int TEMP_NORTH_ALERT = 50 * 100;
const int TEMP_NORTH_MAX = 55 * 100;
const int TEMP_AVG_CYCLE = 10;
const int FAN_SPEED_MIN = 1000;
const long LCD_BACKLIGHT_AUTO_OFF = 5 * 60000;
const int CHART_MAX_W = 200;
const int CHART_X_FROM = 209;
const int CHART_X_TO = 377;
const int CHART1_Y_FROM = 51;
const int CHART1_Y_POINTER_FROM = 50;
const int CHART1_Y_TO = 89;
const int CHART1_Y_POINTER_TO = 90;
const int CHART2_Y_FROM = 120;
const int CHART2_Y_POINTER_FROM = 121;
const int CHART2_Y_TO = 144;
const int CHART2_Y_POINTER_TO = 145;
const int CHART3_Y_FROM = 153;
const int CHART3_Y_POINTER_FROM = 154;
const int CHART3_Y_TO = 177;
const int CHART3_Y_POINTER_TO = 178;
const int CHART4_Y_FROM = 185;
const int CHART4_Y_POINTER_FROM = 186;
const int CHART4_Y_TO = 209;
const int CHART4_Y_POINTER_TO = 210;
const String COLOR_RED = "3";
const String COLOR_GREEN = "2";
const String COLOR_WHITE = "1";
const String COLOR_BLACK = "9";
// vars
volatile int fanCounter1 = 0;
volatile int fanCounter2 = 0;
volatile int fanCounter3 = 0;
int chartTempMin = min(TEMP_CPU_START, TEMP_NORTH_START);
int chartTempMax = min(TEMP_CPU_MAX, TEMP_NORTH_MAX);
int chartCurrentX = CHART_X_FROM;
int chartCurrentX1 = CHART_X_FROM + 1;
int chartCurrentY1 = 0;
int chartCurrentY2 = 0;
int chartCurrentY3 = 0;
int chartCurrentY4 = 0;
String chartColor0 = "1";
String chartColor1 = "1";
String chartColor2 = "1";
String chartColor3 = "1";
String fontColor1 = "1";
String fontColor2 = "1";
String fontColor3 = "1";
String fontColor4 = "1";
String fontColor5 = "1";
String fontColor6 = "1";
long millisLogStart = 0;
int logDuration = 0;
int fanRpm1 = 0;
int fanRpm2 = 0;
int fanRpm3 = 0;
int fanPwmMaster = 0;
int fanPwmMaster_pre = 0;
int fanPwmNorth = 0;
int fanPwmNorth_pre = 0;
int tempCpu1 = 0;
int tempCpu2 = 0;
int tempNorth = 0;
int tempCpuAvg[TEMP_AVG_CYCLE];
int tempNorthAvg[TEMP_AVG_CYCLE];
long tempCpuAvgTotal;
long tempNorthAvgTotal;
int avgIndex = 0;
int v = 0;
int i = 0;
int p = 0;
int e = 0;
String vStr = "";
String iStr = "";
String pStr = "";
String eStr = "";
String tempCpu1Str = "";
String tempCpu2Str = "";
String tempNorthStr = "";
String fanRpm1Str = "";
String fanRpm2Str = "";
String fanRpm3Str = "";
int envLight = 0;
int envLight_pre = 0;
int lcdBacklight = 1;
int lcdBacklight_pre = 0;
bool bgLightOn = true;
bool isBootBgLight = true;
volatile long millisTouch_this = 0;
volatile long millisTouch_pre = 0;
volatile long millisTouchInterval = 0;
volatile bool singleTouched = false;
volatile bool doubleTouched = false;
long millisBacklightDuration = 0;
long lcdBacklightOn = 0;
String serialPrintBgLight = "";
String serialPrintToggleBorder = "";
char tmpChar = "";
String tmpString = "";
byte tempSensors[4];
bool beep = false;
int alertCount = 0;
OneWire oneWire(PIN_ONEWIRE_BUS);
DallasTemperature Dallas(&oneWire);
PZEM004T pzem(&Serial2);
IPAddress ip(192, 168, 1, 1);
// functions
void count1() {
fanCounter1++;
}
void count2() {
fanCounter2++;
}
void count3() {
fanCounter3++;
}
void genSerialPrintBgLight() {
lcdBacklight = map(analogRead(PIN_LIGHT_SENSOR), 0, 800, 9, 1);
if (lcdBacklight != lcdBacklight_pre) {
bgLightOn = true;
lcdBacklight_pre = lcdBacklight;
serialPrintBgLight = "SEBL(" + String(lcdBacklight * 10) + ");";
} else {
serialPrintBgLight = "";
}
}
String formatDigits_2(int num) {
String numStr = String(num);
if (numStr.length() == 2) {
return numStr;
} else if (numStr.length() == 1) {
return "0" + numStr;
} else {
return "ER";
}
}
String formatDigits_3(int num) {
String numStr = String(num);
if (numStr.length() == 3) {
return numStr;
} else if (numStr.length() == 2) {
return "0" + numStr;
} else if (numStr.length() == 1) {
return "00" + numStr;
} else {
return "ERR";
}
}
String formatDigits_4(int num) {
String numStr = String(num);
if (numStr.length() == 4) {
return numStr;
} else if (numStr.length() == 3) {
return "0" + numStr;
} else if (numStr.length() == 2) {
return "00" + numStr;
} else if (numStr.length() == 1) {
return "000" + numStr;
} else {
return "ERRO";
}
}
String formatDigits_5(int num) {
String numStr = String(num);
if (numStr.length() == 5) {
return numStr;
} else if (numStr.length() == 4) {
return "0" + numStr;
} else if (numStr.length() == 3) {
return "00" + numStr;
} else if (numStr.length() == 2) {
return "000" + numStr;
} else if (numStr.length() == 1) {
return "0000" + numStr;
} else {
return "ERROR";
}
}
void LCD_DS(String fontSize, String x, String y, String str, String colorId) {
Serial1.print("DS");
Serial1.print(fontSize);
Serial1.print("(");
Serial1.print(x);
Serial1.print(",");
Serial1.print(y);
Serial1.print(",'");
Serial1.print(str);
Serial1.print("',");
Serial1.print(colorId);
Serial1.print(");");
}
void LCD_PL(int x1, int y1, int x2, int y2, String colorId) {
Serial1.print("PL(");
Serial1.print(x1);
Serial1.print(",");
Serial1.print(y1);
Serial1.print(",");
Serial1.print(x2);
Serial1.print(",");
Serial1.print(y2);
Serial1.print(",");
Serial1.print(colorId);
Serial1.print(");");
}
void LCD_PS(int x, int y, String colorId) {
Serial1.print("PS(");
Serial1.print(x);
Serial1.print(",");
Serial1.print(y);
Serial1.print(",");
Serial1.print(colorId);
Serial1.print(");");
}
void LCD_OFF() {
if (bgLightOn) {
bgLightOn = false;
lcdBacklight_pre = 0;
Serial1.println("SEBL(0,1);");
}
}
long map2(long x, long in_min, long in_max, long out_min, long out_max) {
if (x <= in_min) {
return out_min;
} else if (x >= in_max) {
return out_max;
} else {
return map(x, in_min, in_max, out_min, out_max);
}
}
void setup() {
pinMode(PIN_MASTERFAN1_SPEED, INPUT);
pinMode(PIN_MASTERFAN2_SPEED, INPUT);
pinMode(PIN_NORTHFAN_SPEED, INPUT);
pinMode(PIN_TOUCHPAD, INPUT);
pinMode(PIN_MASTERFAN_PWM, OUTPUT);
pinMode(PIN_NORTHFAN_PWM, OUTPUT);
pinMode(PIN_SPEAKER, OUTPUT);
attachInterrupt(digitalPinToInterrupt(PIN_MASTERFAN1_SPEED), count1, RISING);
attachInterrupt(digitalPinToInterrupt(PIN_MASTERFAN2_SPEED), count2, RISING);
attachInterrupt(digitalPinToInterrupt(PIN_NORTHFAN_SPEED), count3, RISING);
Dallas.begin();
Dallas.getAddress(tempSensors, 0);
Dallas.setResolution(tempSensors, 9);
Dallas.setWaitForConversion(false);
// tempAvg init
for ( int i = 0; i < TEMP_AVG_CYCLE; ++i ) {
tempCpuAvg = 0;
}
pzem.setAddress(ip);
Serial1.begin(115200);
// flash screnn
genSerialPrintBgLight();
Serial1.println(serialPrintBgLight);
delay(3000);
// special thanks
Serial1.println("SPG(3);");
delay(5000);
// supports
Serial1.println("SPG(7);");
delay(3000);
// show charts
Serial1.println("SPG(4);");
String chartRange1 = "0-" + String(CHART_MAX_W) + "W";
String chartRange2 = String(chartTempMin / 100) + "-" + String(chartTempMax / 100);
LCD_DS("12", "345", "35", chartRange1, "1");
LCD_DS("12", "346", "106", chartRange2, "1");
delay(618);
Serial1.println("SPG(10);");
lcdBacklightOn = millis();
// ignore the first value
Dallas.requestTemperatures();
// finish beep
digitalWrite(PIN_SPEAKER, HIGH);
delay(62);
digitalWrite(PIN_SPEAKER, LOW);
}
void loop () {
// temperature mudule
Dallas.requestTemperatures();
tempCpu1 = Dallas.getTempCByIndex(0);
tempCpu2 = Dallas.getTempCByIndex(1);
tempNorth = Dallas.getTempCByIndex(2);
// power module
v = pzem.voltage(ip);
i = round(pzem.current(ip) * 1000);
p = pzem.power(ip);
e = round(pzem.energy(ip) / 1000);
// calc fan speed
fanCounter1 = 0;
fanCounter2 = 0;
fanCounter3 = 0;
sei();
delay(DELAY_REFRESH);
cli();
fanRpm1 = (30000 / DELAY_REFRESH) * fanCounter1;
fanRpm2 = (30000 / DELAY_REFRESH) * fanCounter2;
fanRpm3 = (30000 / DELAY_REFRESH) * fanCounter3;
// pwm
tempCpuAvgTotal = 0;
tempNorthAvgTotal = 0;
tempCpuAvg[avgIndex] = max(tempCpu1, tempCpu2) * 100;
tempNorthAvg[avgIndex] = tempNorth * 100;
avgIndex++;
if (avgIndex >= TEMP_AVG_CYCLE) {
avgIndex = 0;
}
for ( int i = 0; i < TEMP_AVG_CYCLE; ++i ) {
tempCpuAvgTotal += tempCpuAvg;
tempNorthAvgTotal += tempNorthAvg;
}
fanPwmMaster = map2(tempCpuAvgTotal / TEMP_AVG_CYCLE, TEMP_CPU_START, TEMP_CPU_MAX, 0, 254);
fanPwmNorth = map2(tempNorthAvgTotal / TEMP_AVG_CYCLE, TEMP_NORTH_START, TEMP_NORTH_MAX, 0, 254);
if (fanPwmMaster != fanPwmMaster_pre) {
analogWrite(PIN_MASTERFAN_PWM, fanPwmMaster);
//analogWrite(PIN_MASTERFAN2_PWM, fanPwmMaster);
fanPwmMaster_pre = fanPwmMaster;
}
if (fanPwmNorth != fanPwmNorth_pre) {
analogWrite(PIN_NORTHFAN_PWM, fanPwmNorth);
fanPwmNorth_pre = fanPwmNorth;
}
// color and alert
if (p >= CHART_MAX_W) {
chartColor0 = COLOR_RED;
} else {
chartColor0 = COLOR_GREEN;
}
if (tempCpu1 >= TEMP_CPU_ALERT / 100) {
fontColor1 = COLOR_RED;
chartColor1 = COLOR_RED;
alertCount++;
} else {
fontColor1 = COLOR_WHITE;
chartColor1 = COLOR_GREEN;
}
if (tempCpu2 >= TEMP_CPU_ALERT / 100) {
fontColor2 = COLOR_RED;
chartColor2 = COLOR_RED;
alertCount++;
} else {
fontColor2 = COLOR_WHITE;
chartColor2 = COLOR_GREEN;
}
if (tempNorth >= TEMP_NORTH_ALERT / 100) {
fontColor3 = COLOR_RED;
chartColor3 = COLOR_RED;
alertCount++;
} else {
fontColor3 = COLOR_WHITE;
chartColor3 = COLOR_GREEN;
}
if (fanRpm1 < FAN_SPEED_MIN) {
fontColor4 = COLOR_RED;
alertCount++;
} else {
fontColor4 = COLOR_WHITE;
}
if (fanRpm2 < FAN_SPEED_MIN) {
fontColor5 = COLOR_RED;
alertCount++;
} else {
fontColor5 = COLOR_WHITE;
}
if (fanRpm3 < FAN_SPEED_MIN) {
fontColor6 = COLOR_RED;
alertCount++;
} else {
fontColor6 = COLOR_WHITE;
}
// chart
chartCurrentX1 = chartCurrentX + 1;
chartCurrentY1 = map2(p, 0, CHART_MAX_W, CHART1_Y_TO, CHART1_Y_FROM);
chartCurrentY2 = map2(tempCpu1 * 100, chartTempMin, chartTempMax , CHART2_Y_TO, CHART2_Y_FROM);
chartCurrentY3 = map2(tempCpu2 * 100, chartTempMin, chartTempMax, CHART3_Y_TO, CHART3_Y_FROM);
chartCurrentY4 = map2(tempNorth * 100, chartTempMin, chartTempMax, CHART4_Y_TO, CHART4_Y_FROM);
if (p >= 0) LCD_DS("64", "17", "39", formatDigits_3(p), "1");
if (v >= 0) LCD_DS("12", "168", "47", formatDigits_3(v), "1");
if (i >= 0) LCD_DS("12", "156", "64", formatDigits_5(i), "1");
if (e >= 0) LCD_DS("12", "156", "81", formatDigits_5(e), "1");
if (tempCpu1 >= 0) LCD_DS("32", "18", "133", formatDigits_2(tempCpu1), fontColor1);
if (tempCpu2 >= 0)LCD_DS("32", "78", "133", formatDigits_2(tempCpu2), fontColor2);
if (tempNorth >= 0)LCD_DS("32", "138", "133", formatDigits_2(tempNorth), fontColor3);
if (fanRpm1 >= 0) LCD_DS("12", "20", "200", formatDigits_4(fanRpm1), fontColor4);
if (fanRpm2 >= 0) LCD_DS("12", "80", "200", formatDigits_4(fanRpm2), fontColor5);
if (fanRpm3 >= 0) LCD_DS("12", "140", "200", formatDigits_4(fanRpm3), fontColor6);
LCD_PL(chartCurrentX, CHART1_Y_POINTER_FROM, chartCurrentX, chartCurrentY1 - 1, COLOR_BLACK);
LCD_PL(chartCurrentX, chartCurrentY1, chartCurrentX, CHART1_Y_TO, chartColor0);
LCD_PL(chartCurrentX1, CHART1_Y_POINTER_FROM, chartCurrentX1, CHART1_Y_POINTER_TO, COLOR_WHITE);
LCD_PS(chartCurrentX, CHART1_Y_TO + 1, COLOR_BLACK);
LCD_PL(chartCurrentX, CHART2_Y_POINTER_FROM, chartCurrentX, chartCurrentY2 - 1, COLOR_BLACK);
LCD_PL(chartCurrentX, chartCurrentY2, chartCurrentX, CHART2_Y_TO, chartColor1);
LCD_PL(chartCurrentX1, CHART2_Y_POINTER_FROM, chartCurrentX1, CHART2_Y_POINTER_TO, COLOR_WHITE);
LCD_PS(chartCurrentX, CHART2_Y_TO + 1, COLOR_BLACK);
LCD_PL(chartCurrentX, CHART3_Y_POINTER_FROM, chartCurrentX, chartCurrentY3 - 1, COLOR_BLACK);
LCD_PL(chartCurrentX, chartCurrentY3, chartCurrentX, CHART3_Y_TO, chartColor2);
LCD_PL(chartCurrentX1, CHART3_Y_POINTER_FROM, chartCurrentX1, CHART3_Y_POINTER_TO, COLOR_WHITE);
LCD_PS(chartCurrentX, CHART3_Y_TO + 1, COLOR_BLACK);
LCD_PL(chartCurrentX, CHART4_Y_POINTER_FROM, chartCurrentX, chartCurrentY4 - 1, COLOR_BLACK);
LCD_PL(chartCurrentX, chartCurrentY4, chartCurrentX, CHART4_Y_TO, chartColor3);
LCD_PL(chartCurrentX1, CHART4_Y_POINTER_FROM, chartCurrentX1, CHART4_Y_POINTER_TO, COLOR_WHITE);
LCD_PS(chartCurrentX, CHART4_Y_TO + 1, COLOR_BLACK);
chartCurrentX++;
if (chartCurrentX > CHART_X_TO) {
LCD_PL(chartCurrentX, CHART1_Y_POINTER_FROM, chartCurrentX, CHART1_Y_POINTER_TO, COLOR_BLACK);
LCD_PL(chartCurrentX, CHART2_Y_POINTER_FROM, chartCurrentX, CHART2_Y_POINTER_TO, COLOR_BLACK);
LCD_PL(chartCurrentX, CHART3_Y_POINTER_FROM, chartCurrentX, CHART3_Y_POINTER_TO, COLOR_BLACK);
LCD_PL(chartCurrentX, CHART4_Y_POINTER_FROM, chartCurrentX, CHART4_Y_POINTER_TO, COLOR_BLACK);
chartCurrentX = CHART_X_FROM;
}
// backlight
if (digitalRead(PIN_TOUCHPAD) == HIGH) {
if (isBootBgLight) {
isBootBgLight = false;
lcdBacklight_pre = 0;
}
genSerialPrintBgLight();
} else {
if (isBootBgLight) {
millisBacklightDuration = millis() - lcdBacklightOn;
if (millisBacklightDuration >= LCD_BACKLIGHT_AUTO_OFF || millisBacklightDuration <= 0) {
LCD_OFF();
isBootBgLight = false;
} else {
genSerialPrintBgLight();
}
} else {
LCD_OFF();
}
}
Serial1.println(serialPrintBgLight);
interrupts();
// alert beep
if (alertCount > 0) {
digitalWrite(PIN_SPEAKER, HIGH);
delay(618);
digitalWrite(PIN_SPEAKER, LOW);
delay(382);
digitalWrite(PIN_SPEAKER, HIGH);
delay(618);
digitalWrite(PIN_SPEAKER, LOW);
beep = true;
alertCount = 0;
} else {
if (beep) {
digitalWrite(PIN_SPEAKER, LOW);
beep = false;
}
}
}
[/mw_shl_code]
|
|