Терморегулятор на микроконтроллере PIC16F676

  • Печать

TRIcoТерморегулирование сегодня является одной из самых ярких и распространенных областей применения автоматики. Оборудование для управления тепловыми процессами можно встретить в каждом доме, автомобиле или промышленном производстве. Применение современной электроники позволяет строить простые и при этом высокофункциональные системы, благодаря использованию датчиков с цифровым выходом, микроконтроллеров и других элементов. Реализовать алгоритм терморегулирования в подобных системах также не составляет особой сложности.

Позиционный принцип терморегулирования

Для регулирования температуры какого-либо объекта можно на выбор использовать несколько алгоритмов. В промышленных системах наиболее часто встречается позиционное управление, либо управление по ПИ или ПИД закону. Наиболее просто реализуется позиционный принцип. Его можно встретить в огромном количестве устройств. Практически все современные полупроводниковые датчики температуры имеют встроенный выход термостатирования, позволяющий максимально упростить итоговую систему. Но подобный подход отличается неинформативностью и сложностью перенастройки. Решить эту проблему можно с применением микроконтроллера и какого-либо индикатора.

Структурная схема терморегулятора
Структурная схема терморегулятора

Позиционное управление по своей сути реализует релейную логику в классической системе с обратной связью. В такой системе выходной сигнал не изменяется по амплитуде, а работает по принципу Включено/Выключено.

Позиционное управление
Позиционное управление температурой

Выходное устройство в этом случае легко реализуется с помощью реле, коммутирующего сеть и нагреватель. При достижении температурой заданного значения, реле отключается и соответственно отключает нагреватель. Единственной проблемой становится частое срабатывание реле, при колебаниях температуры вблизи задания. Это может быть вызвано неточностью датчика, малой инерционностью системы и другими факторами, но в общем случае такой режим негативно скажется на работе и долговечности регулятора. Избежать подобного развития событий можно введением гистерезиса на включение и отключение выходного устройства. В общем случае выключение реле будет происходить при одной температуре, а включение при другой, несколько меньшей, чем первая.  Величина гистерезиса подбирается экспериментально, исходя из инерционности всей системы.

Принципиальная схема

Основой термостата выбран популярный микроконтроллер PIC16F676. Его характеристики наиболее оптимально подходят для создания простых измерительных устройств и устройств автоматики. Для тактирования использован внешний кварцевый резонатор на 20 МГц. Индикация температуры производится в динамическом режиме на 3-разрядном светодиодном индикаторе с общим катодом. С целью экономии выводов контроллера, управление сегментами реализовано через микросхему сдвигового регистра 74HC164.

Принципиальная схема терморегулятора
Принципиальная схема терморегулятора

Температура измеряется датчиком с цифровым выходом модели MCP9800.  Его характеристики позволяют отображать результаты измерения с разрешением 0.1 градуса. Точность при этом составляет ±0,5°С. Подключение к микроконтроллеру выполнено по шине I2C, что при необходимости позволяет легко изменить модель датчика на другую.

Управление нагревательным элементом может быть выполнено двумя способами. Один из них реализуется с помощью миниатюрного электромагнитного реле серии RE03. В приведенной схеме используется модель RE032005, срабатывающая от напряжения 5В. Нормально-разомкнутый контакт реле способен коммутировать нагрузку переменного тока с напряжением 230В и током 6А.

Печатная плата терморегулятора Расположение элементов сверху Расположение элементов снизу
Печатная плата терморегулятора Расположение элементов сверху Расположение элементов снизу

Альтернативным вариантом реле может стать использование полупроводникового коммутационного устройства. В этом случае на плату устанавливается опторазвязка серии MOC30хх, позволяющая управлять мощным симистором. Рекомендуется использовать модели MOC306x, так как эти элементы имеют встроенный детектор перехода через 0. Его наличие позволяет избежать сложных коммутационных процессов в электрической цепи и связанных с ними недостатков. При использовании опторазвязки не требуется установка транзистора

Работа термостата

Задание температуры срабатывания реле выполняется с помощью трех кнопок. Кнопка S3 при длительном нажатии переводит управляющую программу в режим установки задания. В этом режиме отображаются мигающие цифры, соответствующие уставке температуры. Кнопки S3 и S2 предназначены для соответственно увеличения и уменьшения уставки. Шаг изменения задания равен разрешению датчика и составляет 0.5 градуса. Диапазон изменения уставки - 0..99.9 градусов. Для выхода из режима задания требуется вновь длительно нажать кнопку S3.

Собранная плата терморегулятора
Собранная плата терморегулятора

К сожалению, малый объем памяти микроконтроллера не позволил реализовать задание гистерезиса, поэтому он задается программно.

Функционирование термостата начинается сразу же после включения, либо после выхода из режима задания. В случае, если текущая измеренная температура ниже уставки с учетом гистерезиса, микроконтроллер включает выходное устройство. При превышении уставки, выход отключается. Значение температуры задания сохраняется в энергонезависимой памяти. При подаче питания на микроконтроллер уставка считывается из памяти и используется для регулирования температуры.

Программа терморегулятора

program ThermoReg;

var i,dig:byte;

    dig1,dig2,dig3:byte;

    mm,ss,rm,rs,s1,s2:byte;

    set_mm,set_ss:byte;

    button_cnt1,button_cnt2,button_cnt3:byte;

    rezim:byte;

    Temp,Temp_set:word;

    Soft_I2C_Scl     : sbit at RA1_bit;

    Soft_I2C_Sda     : sbit at RA0_bit;

    Soft_I2C_Scl_Direction : sbit at TRISA1_bit;

    Soft_I2C_Sda_Direction : sbit at TRISA0_bit;

 

procedure Read_T();   

  begin

    clrwdt;

    Soft_I2C_Start();

    Soft_I2C_Write(0x90);

    Soft_I2C_Write(0x00);

    Soft_I2C_Start();

    Soft_I2C_Write(0x91);

    rm := Soft_I2C_Read(1);

    rs := Soft_I2C_Read(0);

    Soft_I2C_Stop();

  end;

 

procedure Delay1();  

  begin

     clrwdt;

     Delay_ms(300);

     clrwdt;

  end;

 

function m1(num1: byte): byte;     

var i:byte;

tmp:word;

begin

clrwdt;

  tmp:=0;

  for i:=0 to num1 do

  begin

    tmp:=tmp+625;

  end;

  result:= tmp div 1000;

end;

 

function mask(num: byte): byte; 

begin

clrwdt;

  case num of    //bfgacpde

     0 : result:= %11011011;

     1 : result:= %10001000;

     2 : result:= %10110011;

     3 : result:= %10111010;

     4 : result:= %11101000;

     5 : result:= %01111010;

     6 : result:= %01111011;

     7 : result:= %10011000;

     8 : result:= %11111011;

     9 : result:= %11111010;

    10 : result:= %11111010;

   end;

end;

 

procedure Digit_Reg(digit:byte);  

begin

  clrwdt;

  if (dig=2) and (dig2>2) then digit:=digit+4;

  for i:=1 to 8 do

    begin

      clearbit(PortC,0);

      if testbit(digit,0) then setbit(PortC,0);

      Setbit(portC,1);

      Clearbit(portC,1);

      digit:=digit shr 1;

    end;

end;

 

procedure interrupt;  

begin

  clrwdt;

  dig:=dig+1;

  if dig>3 then dig:=1;

  case dig of

    1: begin

      clearbit(portc,3);

      Digit_Reg(dig3);

      setbit(portc,5);

      if testbit(portc,2) then

        begin

          if button_cnt1<200 then

            begin

              button_cnt1:=button_cnt1+1;

              if button_cnt1>=198 then

                begin

                  rezim:= rezim xor 1;

                  if rezim=0 then

                    begin

                      EEPROM_Write(0x02,set_ss);

                      EEPROM_Write(0x03,set_mm);

                    end;

                end;

            end;

        end

        else button_cnt1:=0; 

    end;

    2: begin

      clearbit(portc,5);

      Digit_Reg(dig2);

      setbit(portc,4);

     if (rezim>0) and (testbit(portc,2)=1) then

        begin

          button_cnt2:=button_cnt2+1;

          if button_cnt2=25 then set_ss:=set_ss+10;

          if button_cnt2>120 then button_cnt2:=10;

        end

        else button_cnt2:=0; 

    end;

    3: begin 

      clearbit(portc,4);

      Digit_Reg(dig1);

      setbit(portc,3);

     if (rezim>0) and (testbit(portc,2)=1) then

        begin

          button_cnt3:=button_cnt3+1;

          if button_cnt3=25 then set_ss:=set_ss-10;

          if button_cnt3>120 then button_cnt3:=10;

        end

        else button_cnt3:=0;

    end;

  end;

  INTCON := %10100000;                      

end;

 

function te1(d1,d2:byte):word;

begin

  result:=(d1 shl 4)+(d2 shr 4);

end;

begin

  OPTION_REG  := %00000100;

  ansel       :=0;

  cmcon       :=7;

  INTCON      :=  $A0;

  TRISA       :=    %00000000;

  TRISC       :=    %00000100;

  PORTA       :=    0;

  PORTC       :=    0;

  Setbit(portc,0);

  dig:=1;

  rezim:=0;

  button_cnt1:=0;

  button_cnt2:=0;

  button_cnt3:=0;

  Delay1;

  set_ss:=EEPROM_Read(0x02);

  set_mm:=EEPROM_Read(0x03);

  clrwdt;

    Soft_I2C_Init();

    Soft_I2C_Start();

    Soft_I2C_Write(0x90);

    Soft_I2C_Write(0x01);

    Soft_I2C_Write(%01100000);

    Soft_I2C_Stop();

  clrwdt;

  while 1 do

    begin

     s1:=s1+1;

     if set_ss>200 then  begin set_ss:=90; set_mm:=set_mm-1; end;

     if set_mm>200 then begin set_ss:=0; end;

     if set_mm>99 then set_mm:=0;

     if set_ss>90 then begin set_ss:=0; set_mm:=set_mm+1; end;

     if (rezim>0) then

       begin

         if (testbit(s1,0)=1) then

           begin

             dig1:=mask(set_ss div 10);

             dig2:=mask(set_mm mod 10);

             dig3:=mask(set_mm div 10);

           end

           else                 begin

              dig1:=2;

              dig2:=2;

              dig3:=2;

            end;

       end

       else

       begin

         delay1;

         delay1;

         clearbit(intcon,gie);

         Read_T();

         setbit(intcon,gie);

         s2:=m1(rs shr 4);

         dig1:=mask(s2);

         dig2:=mask(rm mod 10);

         dig3:=mask(rm div 10);

         Temp:=te1(rm,rs);

         Temp_set:=te1(set_mm,set_ss);

         if Temp<(temp_set-2) then setbit(porta,2);

         if Temp>(temp_set+2) then clearbit(porta,2);

       end;

       delay1;

    end;

end.

Файлы проекта