Управление вентилятором радиатора авто.

sva_khv
Offline
Зарегистрирован: 19.12.2016

Собрал для Волги управление вентилятором радиатора. Готовые варианты блоков управления меня чем-нибуть да не устраивали.  Реализовал алгоритм который мне нужен.

Может кому пригодиться.

Температуру получаем с двух датчиков DS18B20 подключенных на одну линию.

Перед каждым замером производим поиск датчиков. (обрыв, временное отключение, замена  и т.д.)

Включаем вентилятор если хоть на одном датчике температура больше  TEMP_VKL и выключаем когда на обоих меньше TEMP_OTKL.

Индикация режимов:

- нормальная работа ЗЕЛЕНЫЙ светодиод мерцает (контроль зависания ардуинки), красный отображает вкл/выкл вентилятора.

- датчики не найдены или не получилось считать температуру - включается зеленый, красный в это время несколько раз мигнул, затем все гасим  и заново цикл показа ошибки.

 

sva_khv
Offline
Зарегистрирован: 19.12.2016

sva_khv
Offline
Зарегистрирован: 19.12.2016
/*
Терморегулятор на двух 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();
      }  
     
   }
}