PHP код:
/*
Программа термоконтроля за системой охлаждения ДВС. Использует плавную регулировку по ШИМ.
Может применяться и в других проектах, где исходные данные будет выдавать термистор (терморезистор).
В качестве исходных данных - 1 проводной температурный датчик (термистор(терморезистор))
двигателя с которого берется информация на штатную приборную панель автомобиля.
Т.к. датчик имеет нелинейную зависимость сопротивления (падения напряжения),
то необходима аппроксимация по заранее известным точкам. Чем выше температура,
тем ниже сопротивление и больше падение напряжения.
Для достоверной работы программы нужно ввести значения проходящего через датчик напряжения при
различных температурах, желательно во всем диапазоне его работы.
За аппроксимацию спасибо SBorovkov.
*/
#include <Metro.h> //Библиотека регулярных действий по интервалу времени
#include <MyLiquidCrystalRus.h> //Библиотека ЖК дисплея
MyLiquidCrystalRus lcd(12, 11, 10, 5, 4, 3, 2); //Используем ЖК дисплей
#include <avr/pgmspace.h> //Подключаем макрос PROGMEM
//*********************Параметры для работы термоконтроля ОЖ двигателя
#define EngineTemp1Count 14 //Количество точек аппроксимации
#define DestinationEngineTemp 90 //Определяем нужную температуру двигателя
#define EngineTempSensorPin 0 // Аналоговый вход для температурного датчика ОЖ ДВС
#define EnginePowerVentPin 6 //ШИМ выход на вентиляторы основного радиатора ДВС
//Задаем точки аппроксимации. Первая цифра - разность из 1024 и значения на входе от датчика
//(сделано для того чтобы развернуть график зависимости и сделать так чтобы с ростом температуры значение увеличивалось)
//не переводил в напряжение чтобы не морочиться и оперировать целыми числами с достаточной точностью;
//вторая цифра - значение температуры (заранее измеренное) при данном значении на выходе с датчика.
uint16_t EngineTemp1[EngineTemp1Count][2] PROGMEM = {{0,0}, {471,46}, {635,56}, {702,64}, {723,71}, {729,75}, {764,80}, {793,85}, {811, 90}, {836, 95}, {862, 102}, {872, 110}, {882, 120}, {890, 130}};
//************************Процедуры по таймеру*************************
Metro PWMengineMetro = Metro(10); //Плавное изменение мощности вентиляторов каждые ХХ миллисекунд
Metro LCDoutMetro = Metro(250); //Выводим информацию на ЖК каждые ХХ миллисекунд
int EngineCurrentVentPWM; //Текущая мощность вентиляторов ОЖ двигателя
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("****************");
lcd.setCursor(0,1);
lcd.print("****************");
delay(1000);
}
void loop() {
//**********************Расчет всех параметров на основе температуры ОЖ двигателя
int EngineTargetVentPWM; //Целевая точка мощности вентиляторов ОЖ двигателя
// int EngineCurrentVentPWM; //Текущая мощность вентиляторов ОЖ двигателя
int EnginePowerVentPercent; //Мощность вентиляторов на ОЖ двигателя в %
int EngineTargetVentPercent; //Задаваемая мощность вентиляторов на ОЖ двигателя в %
uint16_t EngineRealTemp; //Расчетное значение реальной температуры ОЖ двигателя
int i;
int EngineCount = 20; //Количество значений для усреднения
int EngineIn = 0; //Начальная точка суммирования
int EngineInSrednee; //Усредненное значение со входа
uint16_t EngineInTemp; //Входное значение с датчика температуры
uint16_t EngineInLeftTemp;
//Цикл усреднения значения
for (i = 0; i < EngineCount; i++) {
EngineIn = EngineIn + analogRead(EngineTempSensorPin);
}
EngineInSrednee = EngineIn / EngineCount; //Вычисляем среднее значение
EngineInTemp = 1024 - EngineInSrednee; //Переворачиваем график падения напряжения
i=EngineTemp1Count;
do
{
i--;
EngineInLeftTemp=pgm_read_word(&EngineTemp1[i][0]);
}
while ((i>=0)&&(EngineInTemp<EngineInLeftTemp));
uint16_t EngineInRightTemp=pgm_read_word(&EngineTemp1[i+1][0]);
uint16_t EngineOutLeftTemp=pgm_read_word(&EngineTemp1[i][1]);
uint16_t EngineOutRightTemp=pgm_read_word(&EngineTemp1[i+1][1]);
EngineRealTemp=EngineOutLeftTemp+(EngineOutRightTemp-EngineOutLeftTemp)*(EngineInTemp-EngineInLeftTemp)/(EngineInRightTemp-EngineInLeftTemp); //Вычисление значения реальной температуры
float EngineVoltIn = (5.00 / 1024.00 * EngineInSrednee); //Переводим входные данные к абсолютному значению напряжения для мониторинга
//Если температура входит в определнные значения - запускаем вентиляторы на определенную мощность.
if (EngineRealTemp < DestinationEngineTemp - 5) EngineTargetVentPWM = 0;
if (EngineRealTemp >= DestinationEngineTemp - 5) EngineTargetVentPWM = 36;
if (EngineRealTemp >= DestinationEngineTemp - 4) EngineTargetVentPWM = 72;
if (EngineRealTemp >= DestinationEngineTemp - 3) EngineTargetVentPWM = 108;
if (EngineRealTemp >= DestinationEngineTemp - 2) EngineTargetVentPWM = 144;
if (EngineRealTemp >= DestinationEngineTemp - 1) EngineTargetVentPWM = 180;
if (EngineRealTemp >= DestinationEngineTemp) EngineTargetVentPWM = 216;
if (EngineRealTemp >= DestinationEngineTemp + 1) EngineTargetVentPWM = 255;
EnginePowerVentPercent = 100.00/255.00*EngineCurrentVentPWM; //Вычисляем значение в процентах текущей мощности вентиляторов
EngineTargetVentPercent = 100.00/255.00*EngineTargetVentPWM; //Вычисляем значение в процентах задаваемой мощности вентиляторов
//**********************Процедура плавного изменения мощности вентиляторов
if (PWMengineMetro.check() == 1) {
if (EngineCurrentVentPWM > EngineTargetVentPWM && EngineCurrentVentPWM > 0){
EngineCurrentVentPWM--;
analogWrite(EnginePowerVentPin, EngineCurrentVentPWM); // Уменьшаем мощность
}
if (EngineCurrentVentPWM < EngineTargetVentPWM && EngineCurrentVentPWM < 255)
{
EngineCurrentVentPWM++;
analogWrite(EnginePowerVentPin, EngineCurrentVentPWM); // Увеличиваем мощность
}
}
//***********************Выводим все что нам нужно на ЖК дисплей
if (LCDoutMetro.check() == 1){
// lcd.clear();
lcd.setCursor(0,0);
lcd.print("ВЛТ:");
lcd.setCursor(4,0);
lcd.print(EngineVoltIn); //Входное напряжение с датчика
lcd.setCursor(8,0);
if (EngineVoltIn > 2.70) {
lcd.print(" ТМП:");
lcd.setCursor(13,0);
lcd.print("MIN"); //Ниже минимальной точки аппроксимации
}
else if (EngineVoltIn < 0.65){
lcd.print(" ТМП:");
lcd.setCursor(13,0);
lcd.print("MAX"); //Выше максимальной точки аппроксимации
}
else {
lcd.print(" ТМП:");
lcd.setCursor(13,0);
lcd.print(EngineRealTemp); //Аппроксимированная температура
lcd.print(" ");
}
lcd.setCursor(0,1);
lcd.print("МОЩНОСТЬ:");
lcd.setCursor(9,1);
lcd.print(EnginePowerVentPercent); //Мощность вентиляторов
lcd.print(" ");
lcd.setCursor(12,1);
lcd.print("%");
lcd.setCursor(13,1);
lcd.print(EngineTargetVentPercent); //Заданная мощность вентиляторов
lcd.print(" ");
}
}
Вопрос: Почему мне пришлось вынести