Управление вентилятором радиатора авто.
- Войдите на сайт для отправки комментариев
Собрал для Волги управление вентилятором радиатора. Готовые варианты блоков управления меня чем-нибуть да не устраивали. Реализовал алгоритм который мне нужен.
Может кому пригодиться.
Температуру получаем с двух датчиков DS18B20 подключенных на одну линию.
Перед каждым замером производим поиск датчиков. (обрыв, временное отключение, замена и т.д.)
Включаем вентилятор если хоть на одном датчике температура больше TEMP_VKL и выключаем когда на обоих меньше TEMP_OTKL.
Индикация режимов:
- нормальная работа ЗЕЛЕНЫЙ светодиод мерцает (контроль зависания ардуинки), красный отображает вкл/выкл вентилятора.
- датчики не найдены или не получилось считать температуру - включается зеленый, красный в это время несколько раз мигнул, затем все гасим и заново цикл показа ошибки.
/* Терморегулятор на двух 18D20 на одной сигнальной линии Включает внешнее рэле низким уровнем Температура вкл/откл TEMP_VKL TEMP_OTKL Выключение не раньше чем через 1 мин после вклю даже если темп сразу упала Нормальная работа - зел мерцает, красный индикация вкл/выкл Индикация ошибки (не нашла датчиков не считала темп) - зеленый горит, красный загорается 1-3 раза (код ошибки) */ #include <OneWire.h> // температура #define TEMP_VKL 73 //75 #define TEMP_OTKL 70 //72 // используемые пины #define PIN_DS18B20_01 8 #define PIN_VENT_RAD 3 #define PIN_IND_VENT 12 #define PIN_IND_WORK 11 // временные интервалы #define TIME_PERIOD_IZM_TEMP 1000 // должен быть больше 1200 т.к. за 1000 мк начало старт определения темп #define TIME_POKAZ_WORK 150 #define TIME_POKAZ_ERROR 6000 // шина температуры OneWire ds1(PIN_DS18B20_01); // on pin 8 (a 4.7K resistor is necessary) //OneWire ds2(PIN_DS18B20_02); // on pin 8 (a 4.7K resistor is necessary) // данные температуры int iTemp[2],iTS,iKolDatTemp; byte bTempAdr[2][8]; // индикация режима работы int iIndTek; // код ошибки int iErr,iIndError; unsigned long ulTimeGetTemp; // период опроса температуры - 1 сек unsigned long ulTimeIndWork; // unsigned long ulTimeVentRad; // контроль длительности включения вентилятора радиатора unsigned long ulTimeIndError; // время индикации ошибки // ОТДЛАДКА ========================= int iPrintPort; //================================================================================= void setup(void) { int i; iPrintPort=0; Serial.begin(9600); // выход управления вентиялятором радиатора pinMode(PIN_VENT_RAD, OUTPUT); digitalWrite(PIN_VENT_RAD, LOW); // индикация включения вент pinMode(PIN_IND_VENT, OUTPUT); digitalWrite(PIN_IND_VENT, LOW); // индикатор работы/ошибки pinMode(PIN_IND_WORK, OUTPUT); digitalWrite(PIN_IND_WORK, LOW); // тестовая проверка индикаторов digitalWrite(PIN_IND_VENT, HIGH); digitalWrite(PIN_IND_WORK, HIGH); delay(1000); digitalWrite(PIN_IND_VENT, LOW); digitalWrite(PIN_IND_WORK, LOW); // индикация нормального режима работы IndWork(1); iTemp[0]=iTemp[1]=9999; iKolDatTemp=iTS=0; iErr=0; iIndError=99; } //================================================================================= // основная программа void loop(void) { int i; while(true) { switch(iTS) { case 0: // поиск датчиков InitAdrrDatTemp(); break; case 1: // работа с датчиками температуры - измерение темп case 2: // работа с датчиками температуры - считывание темп LoopGetTemp(); break; } iErr=0; // проверка есть ли температура если нет то ошибка if(iKolDatTemp<1) iErr=1; // датчики не найдены - код ошибки 1 if(iTemp[0]==9999&&iTemp[1]==9999) iErr=2; // не удалось измерить темп код ошибки 2 // нет ошиок if(iErr==0) { // управлние вентилятором LoopVentRad(); // индикация включения вентилятора IndSostVentRad(); // индикация режима работы IndWork(0); } else // есть ошибка { //iTS=0; // выключаем индикатор VentRadStart(0); // показываем код ошибки IndError(0); } //конец цикла программы } } //================================================================================= // работа с датчиками температуры - опрос, void LoopGetTemp(void) { int iN; if(iKolDatTemp<1) // нет датчиков { iTemp[0]=9999; iTemp[1]=9999; iTS=0; return; } // старт измерения темаратуры if(iTS==1) { ulTimeGetTemp=millis(); iTS=2; for(iN=0;iN<2;iN++) { if(bTempAdr[iN][0]!=0) { ds1.reset(); ds1.select(bTempAdr[iN]); ds1.write(0x44, 0); // начало измерения с внешним питанием } } } // получение темп if(millis()-ulTimeGetTemp>TIME_PERIOD_IZM_TEMP&&iTS==2) { for(iN=0;iN<2;iN++) { if(bTempAdr[iN][0]!=0) // получение температуры { iTemp[iN]=TempGet10(bTempAdr[iN]); } else iTemp[iN]=9999; } iTS=0; if(iPrintPort!=0){ Serial.print(" T1= "); Serial.print(iTemp[0]); Serial.print(" T2= "); Serial.println(iTemp[1]); } } } //================================================================================= // поиск и сохранение адресов датчиков температуры int InitAdrrDatTemp(void) { int i; if(iTS==0) // начало поиска датчиков { iKolDatTemp=0; ds1.reset_search(); // поикс первого датчика for(i=0;i<8;i++) bTempAdr[0][i]=0; if(ds1.search(bTempAdr[0])!=0) { if (OneWire::crc8(bTempAdr[0],7) == bTempAdr[0][7]) iKolDatTemp++; else bTempAdr[0][0]=0; //Serial.print(" ADR1= "); Serial.print(bTempAdr[0][0]); } else bTempAdr[0][0]=0; // поиск второго датчика for(i=0;i<8;i++) bTempAdr[1][i]=0; if(ds1.search(bTempAdr[1])!=0) { if (OneWire::crc8(bTempAdr[1],7) == bTempAdr[1][7]) iKolDatTemp++; else bTempAdr[1][0]=0; //Serial.print(" ADR2= "); Serial.println(bTempAdr[1][0]); } else bTempAdr[1][0]=0; iTS=1; // переход к измерению температуры if(iPrintPort!=0){ Serial.print(" iKolDatTemp = "); Serial.println(iKolDatTemp); } } return(iKolDatTemp); } //================================================================================= // bAddr[]- адрес 8 байт // возвращает температуру умноженую на 10 // попыток чтения 8 раз int TempGet10(byte bAddr[]) { byte bufData[9]; // буфер данных float flTemp; int i,iTemteratura10=9999,iKolRead=0; // 9999-ошибка while(iKolRead<8) { ds1.reset(); ds1.select(bAddr); ds1.write(0xBE); // Read Scratchpad ds1.read_bytes(bufData, 9); // чтение памяти датчика, 9 байтов if(bufData[0]==0&&bufData[1]==0&&bufData[2]==0&&bufData[3]==0&&bufData[4]==0&&bufData[5]==0&&bufData[6]==0&&bufData[7]==0&&bufData[8]==0) { iKolRead++; // ошибка счытивания } else { if(OneWire::crc8(bufData, 8)==bufData[8]) { // температура числом flTemp= (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125; i=flTemp*100; if(i!=8503) { iTemteratura10=flTemp*10; iKolRead=99; } else iKolRead++; // ошибка счытивания } else iKolRead++; // ошибка счытивания } } return(iTemteratura10); } //========================================================== //=== управлние вентилятором void LoopVentRad(void) { if(iTemp[0]<9999||iTemp[1]<9999) { if(GetSostVentRad()==0) // вент выключен - проверка надо ли включать вентилятор { if(iTemp[0]>TEMP_VKL*10&&iTemp[0]<9999) { digitalWrite(PIN_VENT_RAD, HIGH); //HIGH LOW ulTimeVentRad=millis(); } if(iTemp[1]>TEMP_VKL*10&&iTemp[1]<9999) { digitalWrite(PIN_VENT_RAD, HIGH); //HIGH LOW ulTimeVentRad=millis(); } } else // ветн включен - проверка надо ли выкл { if(millis()> ulTimeVentRad+60000) // вентилятр проработал > 1 мин (если меньше - пусть работает) { if(iTemp[0]<TEMP_OTKL*10&&(iTemp[1]<TEMP_OTKL*10||iTemp[1]==9999)) digitalWrite(PIN_VENT_RAD, LOW); } } } } //========================================================== // безусловное вкл/выкл вентилятора void VentRadStart(int iVkl) { if(iVkl==1) digitalWrite(PIN_VENT_RAD, HIGH); //HIGH LOW if(iVkl==0) digitalWrite(PIN_VENT_RAD, LOW); } //========================================================== //=== состояние вентилятора 0-выкл, 1-вкл int GetSostVentRad(void) { return(digitalRead(PIN_VENT_RAD)); } //========================================================== // индикация режима работы PIN_IND_WORK void IndWork(int iRes) { unsigned long ulPer; int iUrovLed; if(iRes==1) { iIndTek=0; } if(iIndTek==0) // начало зажигания { ulTimeIndWork=millis(); analogWrite(PIN_IND_WORK,0); iIndTek=1; } // зажигание if(iIndTek==1) { ulPer=millis()-ulTimeIndWork; if(ulPer<TIME_POKAZ_WORK) { iUrovLed=200.0/(TIME_POKAZ_WORK)*ulPer; //Serial.print(" iUrovLed= "); Serial.println(iUrovLed); analogWrite(PIN_IND_WORK,iUrovLed); } else { iIndTek=2; ulTimeIndWork=millis(); } } // гашение if(iIndTek==2) { ulPer=millis()-ulTimeIndWork; if(ulPer<TIME_POKAZ_WORK) { iUrovLed=200.0-(200.0/(TIME_POKAZ_WORK)*ulPer); analogWrite(PIN_IND_WORK,iUrovLed); //Serial.print(" iUrovLed= "); Serial.println(iUrovLed); } else { iIndTek=1; ulTimeIndWork=millis(); } } } //========================================================== //=== индикация состояние вентилятора void IndSostVentRad(void) { digitalWrite(PIN_IND_VENT, GetSostVentRad()); } //========================================================== // индикация кода ошибки void IndError(int iRes) { unsigned long ulPer; int iUrovLed; // началоиндикации ошибки if(iRes!=0||millis()>ulTimeIndError+TIME_POKAZ_ERROR) { iIndError=0; ulTimeIndError=millis(); if(iPrintPort!=0){ Serial.print(" ulTimeIndError = "); Serial.println(ulTimeIndError); } } // зажигам зел светодиод if(iIndError==0) // начало показа 0,5сек ЗЕЛ { digitalWrite(PIN_IND_WORK, HIGH); //HIGH LOW digitalWrite(PIN_IND_VENT, LOW); //HIGH LOW if(millis()>ulTimeIndError+500) iIndError=1; } // мигаем красным 1 if(iIndError==1) // показ 1 ошибка КРАС ГОРИТ { if(iErr>0) digitalWrite(PIN_IND_VENT, HIGH); //HIGH LOW if(millis()>ulTimeIndError+1000) iIndError=2; } if(iIndError==2) // показ 1 ошибки КРАС погасло { digitalWrite(PIN_IND_VENT, LOW); //HIGH LOW if(millis()>ulTimeIndError+1500) iIndError=11; } // мигаем красным 2 раза if(iIndError==11) // показ 1 ошибка КРАС ГОРИТ { if(iErr>1) digitalWrite(PIN_IND_VENT, HIGH); //HIGH LOW if(millis()>ulTimeIndError+2000) iIndError=12; } if(iIndError==12) // показ 1 ошибки КРАС погасло { digitalWrite(PIN_IND_VENT, LOW); //HIGH LOW if(millis()>ulTimeIndError+2500) iIndError=21; } // мигаем красным 3 раза if(iIndError==21) // показ 1 ошибка КРАС ГОРИТ { if(iErr>2) digitalWrite(PIN_IND_VENT, HIGH); //HIGH LOW if(millis()>ulTimeIndError+3000) iIndError=22; } if(iIndError==22) // показ 1 ошибки КРАС погасло { digitalWrite(PIN_IND_VENT, LOW); //HIGH LOW if(millis()>ulTimeIndError+3500) iIndError=90; } // гасим все все на 0,5 if(iIndError==90) // { digitalWrite(PIN_IND_VENT, LOW); //HIGH LOW digitalWrite(PIN_IND_WORK, LOW); //HIGH LOW if(millis()>ulTimeIndError+5000) { iIndError=0; ulTimeIndError=millis(); } } }