Всем здравствуйте!
Это моё первое знакомство с МК Arduino, который приобрел специально для реализации этого проекта. Для этого пришлось бегло ознакомится с основами программирования в Arduino IDE, не имея никакого практического опыта (за исключением уроков информатики по Pascal и C в студенческие времена 25 лет назад). Спасибо за это коротким и доходчивым урокам и отличной шпаргалке от Алекса. Поэтому сначала будет описание проекта, а в конце несколько уточняющих вопросов к опытным ардуинщикам.
Итак, суть проекта. Как известно, дизельные ДВС обладают высоким КПД, и поэтому очень долго греются до рабочей температуры ОЖ (а на холостых оборотах приктически никогда её не достигают, особенно в холода). Как следствие, необходимо очень длительное время, чтобы прогреть салон авто. Поэтому и существуют всяческие подогреватели ОЖ типа Webasto, Бинар и т.п., а так же электрические догреватели на свечах накаливания (я взял такой от дизельного Renault Laguna II, как на фото ниже). Сам догреватель ставится перед входом радиатора печки.
Догреватель от Рено Лагуна
Вот его нагревом и будет управлять мой конроллер.
Питание на догреватель будет подаваться через твердотельное реле постоянного тока ZGT-200DD.
Вход реле управляется ШИМ с Ардуино.
Из входных параметров для контроллера будут использоваться напряжение бортовой сети автомобиля и термодатчик DS18B20 для измерения температуры ОЖ на выходе догревателя (как его приспособить внутрь догревателя еще в процессе обдумывания).
В общем виде схема контроллера выглядит так:
Суть работы контроллера заключается в контроле напряжения бортовой сети автомобиля для определени просадок напряжения и защиты аккумулятора от разряда, если двигатель не заведен или генератор не справляется с высокой нагрузкой. На дисплей выводятся показания текущего напряжения сети авто, уровень ШИМ в % на выходе Ардуино, и температура ОЖ после догревателя. Энкодер с кнопкой для изменения порогового напряжения включения догревателя и желаемой температуры ОЖ на выходе.
Программа контролирует напряжение сети авто. Если напряжение ниже 12.6В считаем двигатель заглушеным или аккумулятор разряженным - догреватель выключен (или мгновенно выключаем, если был включен). Если напряжение выше порогового (по-умолчанию 13.2В), то считаем, что идет зарядка с генератора (соответственно двигатель запущен), и начинаем постепенно увеличивать напряжение на свечах догревателя до 100%. Если напряжение ниже порогового, то вероятно генератор не справляется с общей нагрузкой, мы начинаем снижать (немного быстрее, чем увеличение) нагрузку догревателя вплоть до 0%. Таким образом мы защищаем аккумулятор от разряда и генератор от излишней нагрузки.
Так же при достижении целевой температуры (по-умолчанию 80 градусов), мы сразу отключаем догреватель. При снижении температуры ниже целевого, догреватель снова начнет увеличивать нагрузку.
Энкодер с кнопкой служит для корректировки на лету пороговых значений напряжения включения и целевой температуры, заданных по-умолочанию). При длительном удержании кнопки энкодера переходим в режим изменения порогового напряжения включения догрева, значение напряжения мигает, вращением энкодера меняем значение. Повторное длительное нажатие переводит в настройку целевой температуры, значение температуры мигает, вращение энкодера меняет значение. Пределы напряжения ограничил от 12.8В до 14В, температуры - от 40 до 90 градусов. Следущее длительное нажатие возвращает в обычный режим отображения текущих параметров.
Вроде бы всё описал достаточно подробно. Теперь вопросы к опытным ардуинщикам.
1) Насколько точно и стабильно внутреннее опорное напряжение китайской Arduino Nano?
Возможно вместо формулы vBat = (float)analogRead(7) * VREF * ((DIV_R1 + DIV_R2) / DIV_R2) / 1024; лучше использовать map, заранее измерив эталонное напряжение и показания АЦП. Тогда меня не будут беспокоить точность номиналов резисторов и точное соответствие опорного напряжения 1.1В. Один раз откаибровать и всё. Что думаете?
2) Могу ли я безбоязненно питать Ардуино через Vin от бортовой сети авто, учитывая обычное напряжение при запущенном двигателе выше 12В (около 14.4В в идеале)? При этом датчик температуры и энкодер будут питаться от 5В Ардуино. Твердотельное реле управляться напрямую с выхода ШИМ, но там по паспорту ток потребления тоже не больше 25 мА. Не проблема поставить понижайку DC-DC. Но может тогда поставить её опять же на Vin, отрегулировав выход , например, на 8В?
3) По поводу ШИМ. Время переключения реле, согластно паспорта, менее 10 мс. Поэтому я использую низкочастотный ШИМ 61 Гц. Но может быть кто-нибудь знает на практике про выбранное мной реле - может оно работать на высокой частоте? Ведь внутри него стоит mosfet. Не настолько же он медленный. А высокочастотный ШИМ позволил бы снизить ощутимые пульсации в бортовой сети из-за достаточно мощной нагрузки в виде свечей догревателя. Есть у кого опыт работы с таким реле?
Схема и скетч работают. Просто хотелось бы уточнить некоторые озвученные моменты.
Спасибо за внимание!
Это моё первое знакомство с МК Arduino, который приобрел специально для реализации этого проекта. Для этого пришлось бегло ознакомится с основами программирования в Arduino IDE, не имея никакого практического опыта (за исключением уроков информатики по Pascal и C в студенческие времена 25 лет назад). Спасибо за это коротким и доходчивым урокам и отличной шпаргалке от Алекса. Поэтому сначала будет описание проекта, а в конце несколько уточняющих вопросов к опытным ардуинщикам.
Итак, суть проекта. Как известно, дизельные ДВС обладают высоким КПД, и поэтому очень долго греются до рабочей температуры ОЖ (а на холостых оборотах приктически никогда её не достигают, особенно в холода). Как следствие, необходимо очень длительное время, чтобы прогреть салон авто. Поэтому и существуют всяческие подогреватели ОЖ типа Webasto, Бинар и т.п., а так же электрические догреватели на свечах накаливания (я взял такой от дизельного Renault Laguna II, как на фото ниже). Сам догреватель ставится перед входом радиатора печки.
Догреватель от Рено Лагуна
Вот его нагревом и будет управлять мой конроллер.
Питание на догреватель будет подаваться через твердотельное реле постоянного тока ZGT-200DD.
Вход реле управляется ШИМ с Ардуино.
Из входных параметров для контроллера будут использоваться напряжение бортовой сети автомобиля и термодатчик DS18B20 для измерения температуры ОЖ на выходе догревателя (как его приспособить внутрь догревателя еще в процессе обдумывания).
В общем виде схема контроллера выглядит так:
Суть работы контроллера заключается в контроле напряжения бортовой сети автомобиля для определени просадок напряжения и защиты аккумулятора от разряда, если двигатель не заведен или генератор не справляется с высокой нагрузкой. На дисплей выводятся показания текущего напряжения сети авто, уровень ШИМ в % на выходе Ардуино, и температура ОЖ после догревателя. Энкодер с кнопкой для изменения порогового напряжения включения догревателя и желаемой температуры ОЖ на выходе.
AntifreezeHeaterController:
/* Контроллер догревателя антифриза
с индикацией напряжения бортовой сети
и температуры ОЖ на выходе догревателя
©2022 by reziarlleh */
/* Формат выводв 16x2
________________
0 |V=14.40 PWM 100%|
1 |TEMP AF = 100°C |
----------------
0123456789ABCDEF
*/
// Делитель напряжения GND --[R2_470]-- A7 --[R1_9k1]-- VIN
#define VREF 1.1 // опорное напряжение INTERNAL 1.1V
#define DIV_R1 9100 // точное значение резистора R1
#define DIV_R2 470 // точное значение резистора R2
#define V_OFF 12.6 // напряжение отключения догревателя
#define V_ON 13.2 // пороговое напряжение (определение зарядки с генератора)
#define TARGET_TEMP 80 // целевое значение температуры ОЖ
#define PWM_PIN 10 // ШИМ догревателя на пине D10
float vBat; // измеренное напряжение батареи
int8_t afTemp; // температура ОЖ на выходе догревателя
int8_t afTarget; // целевая температура ОЖ на выходе догревателя
uint16_t vOff; // напряжение отключения догревателя (*100)
uint16_t vOn; // напряжение активации догревателя (*100)
int8_t heaterPWM; // значение выхода ШИМ догревателя в %
int8_t modeAFH; // режим настроки (0 - отображение состояния, 1 - настройка порога напряжения, 2 - настройка целевой температуры)
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // инициализация дисплея 16x2
#include <microDS18B20.h>
MicroDS18B20<5> tempSensor; // подключение температурного датчика к пину D5
#include <EncButton.h>
EncButton<EB_TICK, 2, 3, 4> encBtn; // энкодер с кнопкой на пигах D2, D3 и D4
void setup() {
// Приветствие
lcd.init();
lcd.backlight();
lcd.setCursor(1, 0);
lcd.print("Antifreeze");
lcd.setCursor(1, 1);
lcd.print("Heater Control");
delay(1000);
lcd.clear();
// Шаблон отображения
lcd.setCursor(0, 0);
lcd.print("V");
lcd.setCursor(8, 0);
lcd.print("PWM");
lcd.setCursor(0, 1);
lcd.print("Temp AF ");
//Инициализация
// режим ШИМ для Timer1 (D9 и D10)
TCCR1A = 0b00000011; // 10bit
//TCCR1B = 0b00001001; // x1 fast pwm (15.6 кГц)
//TCCR1B = 0b00000001; // x1 phase correct (7.8 кГц)
//TCCR1B = 0b00001010; // x8 fast pwm (2 кГц)
//TCCR1B = 0b00000010; // x8 phase correct (977 Гц)
//TCCR1B = 0b00001011; // x64 fast pwm (244 Гц)
//TCCR1B = 0b00000011; // x64 phase correct (122 Гц)
TCCR1B = 0b00001100; // x256 fast pwm (61 Гц)
//TCCR1B = 0b00000100; // x256 phase correct (30 Гц)
//TCCR1B = 0b00001101; // x1024 fast pwm (15 Гц)
//TCCR1B = 0b00000101; // x1024 phase correct (7.5 Гц)
analogReference(INTERNAL); // внутреннее опорное напряжение АЦП 1.1V
modeAFH = 0;
heaterPWM = 0;
vOff = V_OFF * 100;
vOn = V_ON * 100;
afTarget = TARGET_TEMP;
}
void loop() {
// измерение напряжения
vBat = (float)analogRead(7) * VREF * ((DIV_R1 + DIV_R2) / DIV_R2) / 1024;
// получение температуры с датчика
static uint32_t timerT = millis ();
if (millis() - timerT >= 1000) { // раз в секунду
timerT = millis();
if (tempSensor.readTemp()) afTemp = tempSensor.getTempInt();
else afTemp = 127; // если датчик не подключен или неисправен (error)
tempSensor.requestTemp();
}
// вывод на дисплей
static uint32_t timerD = millis();
if (millis() - timerD >= 400) { // обновляем экран c с периодом 400 мс
timerD = millis();
myDisplay();
}
//управление ШИМ догревателя
static uint32_t timerP = millis();
static int8_t prevPWM;
if (millis() - timerP >= 100) { // обновляем уровень ШИМ 10 раз в секунду
timerP = millis();
myPWM();
if (heaterPWM != prevPWM) {
analogWrite(PWM_PIN, map(heaterPWM, 0, 100, 0, 1023)); // 0-100% переводим в значения от 0 до 1023 (10 bit)
prevPWM = heaterPWM;
}
}
// обработка энкодера и кнопки (переключение режимов настройки и отображения)
encBtn.tick();
if (encBtn.held()) { // переключение режимов при длительном нажатии кнопки энкодера
if (modeAFH == 2) modeAFH = 0;
else modeAFH++;
}
if (modeAFH == 1) {
if (encBtn.right() && vOn < 1400) vOn += 10; // увеличиваем порог напряжения включения (max 14V)
if (encBtn.left() && vOn > 1280) vOn -= 10; // уменьшаем порог напряжения включения (min 12.8V)
}
if (modeAFH == 2) {
if (encBtn.right() && afTarget < 90) afTarget++; // увеличиваем целевое значение температуры (max 90°C)
if (encBtn.left() && afTarget > 40) afTarget--; // уменьшаем целевое значение температуры (min 40°C)
}
}
// Вывод на дисплей
void myDisplay() {
static boolean blinkVar; // для мигания настраиваемым значением
char vBatStr[5] = "";
lcd.setCursor(12, 0);
lcd.print(heaterPWM);
lcd.print("% ");
lcd.noBlink();
lcd.noCursor();
lcd.setCursor(1, 0);
switch (modeAFH) {
case 0: // обычный режим индикации параметров
{
lcd.print("=");
dtostrf(vBat, 5, 2, vBatStr);
lcd.print(vBatStr);
lcd.setCursor(8, 1);
lcd.print("= ");
if (afTemp == 127) lcd.print("error!");
else {
lcd.print(afTemp);
lcd.write(223); // символ градуса
lcd.print("C ");
}
}
break;
case 1: // режим настройки порогового напрядения активации догревателя
{
lcd.write(126); // символ стрелки вправо
dtostrf((float)vOn / 100, 5, 2, vBatStr);
if (blinkVar == true) lcd.print(vBatStr); // мигаем устанавливаемым значением
else lcd.print(" ");
blinkVar = !blinkVar;
lcd.setCursor(8, 1);
lcd.print("= ");
if (afTemp == 255) lcd.print("error!");
else {
lcd.print(afTemp);
lcd.write(223); // символ градуса
lcd.print("C ");
}
}
break;
case 2: // режим настройки целевой температуры ОЖ
{
lcd.print("=");
dtostrf(vBat, 5, 2, vBatStr);
lcd.print(vBatStr);
lcd.setCursor(8, 1);
lcd.write(126); // символ стрелки вправо
lcd.print(" ");
if (blinkVar == true) { // мигаем устанавливаемым значением
lcd.print(afTarget);
lcd.write(223); // символ градуса
lcd.print("C ");
}
else lcd.print(" ");
blinkVar = !blinkVar;
}
break;
}
}
// Управление ШИМ догревателя на твердотельном реле
void myPWM() {
uint16_t vBat100 = vBat * 100; // немного оптимизации кода ;)
if (vBat100 <= vOff || afTemp >= afTarget) {
heaterPWM = 0;
}
else if (vBat100 >= vOn && heaterPWM < 100) {
heaterPWM++;
}
else if (vBat100 < vOn && heaterPWM > 0) {
heaterPWM -= 2;
heaterPWM = constrain(heaterPWM, 0, 100); // ограничиваем значение от 0% до 100%
}
}
Программа контролирует напряжение сети авто. Если напряжение ниже 12.6В считаем двигатель заглушеным или аккумулятор разряженным - догреватель выключен (или мгновенно выключаем, если был включен). Если напряжение выше порогового (по-умолчанию 13.2В), то считаем, что идет зарядка с генератора (соответственно двигатель запущен), и начинаем постепенно увеличивать напряжение на свечах догревателя до 100%. Если напряжение ниже порогового, то вероятно генератор не справляется с общей нагрузкой, мы начинаем снижать (немного быстрее, чем увеличение) нагрузку догревателя вплоть до 0%. Таким образом мы защищаем аккумулятор от разряда и генератор от излишней нагрузки.
Так же при достижении целевой температуры (по-умолчанию 80 градусов), мы сразу отключаем догреватель. При снижении температуры ниже целевого, догреватель снова начнет увеличивать нагрузку.
Энкодер с кнопкой служит для корректировки на лету пороговых значений напряжения включения и целевой температуры, заданных по-умолочанию). При длительном удержании кнопки энкодера переходим в режим изменения порогового напряжения включения догрева, значение напряжения мигает, вращением энкодера меняем значение. Повторное длительное нажатие переводит в настройку целевой температуры, значение температуры мигает, вращение энкодера меняет значение. Пределы напряжения ограничил от 12.8В до 14В, температуры - от 40 до 90 градусов. Следущее длительное нажатие возвращает в обычный режим отображения текущих параметров.
Вроде бы всё описал достаточно подробно. Теперь вопросы к опытным ардуинщикам.
1) Насколько точно и стабильно внутреннее опорное напряжение китайской Arduino Nano?
Возможно вместо формулы vBat = (float)analogRead(7) * VREF * ((DIV_R1 + DIV_R2) / DIV_R2) / 1024; лучше использовать map, заранее измерив эталонное напряжение и показания АЦП. Тогда меня не будут беспокоить точность номиналов резисторов и точное соответствие опорного напряжения 1.1В. Один раз откаибровать и всё. Что думаете?
2) Могу ли я безбоязненно питать Ардуино через Vin от бортовой сети авто, учитывая обычное напряжение при запущенном двигателе выше 12В (около 14.4В в идеале)? При этом датчик температуры и энкодер будут питаться от 5В Ардуино. Твердотельное реле управляться напрямую с выхода ШИМ, но там по паспорту ток потребления тоже не больше 25 мА. Не проблема поставить понижайку DC-DC. Но может тогда поставить её опять же на Vin, отрегулировав выход , например, на 8В?
3) По поводу ШИМ. Время переключения реле, согластно паспорта, менее 10 мс. Поэтому я использую низкочастотный ШИМ 61 Гц. Но может быть кто-нибудь знает на практике про выбранное мной реле - может оно работать на высокой частоте? Ведь внутри него стоит mosfet. Не настолько же он медленный. А высокочастотный ШИМ позволил бы снизить ощутимые пульсации в бортовой сети из-за достаточно мощной нагрузки в виде свечей догревателя. Есть у кого опыт работы с таким реле?
Схема и скетч работают. Просто хотелось бы уточнить некоторые озвученные моменты.
Спасибо за внимание!
Вложения
-
120.6 KB Просмотры: 5