Термосигнализатор с батарейным питанием

  • Печать

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

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

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

Схема сигнализатора берет начало от термометра на микроконтроллере PIC12F629. Дополнительные функции сигнализатора потребовали увеличения памяти и количества периферийных линий микроконтроллера. В схеме использован 8-ми разрядный процессор PIC16F684, оснащенный 2К слов памяти программ и имеющий 12 периферийных цепей. Возможности микроконтроллера позволяют легко реализовать опрос датчика, задание, индикацию и сигнализацию температуры. Для уменьшения энергопотребления используется внутренний тактовый генератор и «спящий» режим. Фактическая температура измеряется лишь раз в несколько секунд, с такой же частотой производится и переключение выхода. Конечно, подобное решение не совсем подходит для условий с резкими скачками температуры, но во многих задачах вполне приемлемо.

Основной алгоритм программы примерно соответствует термометру. Главное отличие заключается в необходимости реализации задания температуры срабатывания и гистерезиса. Для перехода в режим задания используется кнопка SB1. Она подключена к входу прерывания INT микроконтроллера, и при ее нажатии процессор выходит из состояния «сна». Учитывая небольшое количество цифр, которые требуется устанавливать, задание температуры производится поразрядно, т.е. отдельно устанавливаются десятые, единицы и десятки температуры. Для гистерезиса оставлены только десятые и единицы. Переключение между разрядами выполняется опять же кнопкой SB1. Разряд, операции с которым производятся работа в текущий момент, подсвечивается миганием.  Кнопка SB2, при нажатии на нее, увеличивает значение в выбранном разряде на единицу.  После задания всех цифр, нажатие на SB1 приведет к переводу программы в обычный режим. Для недопущения нештатных ситуаций, связанных с оставлением программы  в режиме задания, используется дополнительный 16-разрядный таймер TIMER1. Переполнение данного таймера вызывает прерывание примерно 1 раз в секунду. В процедуре обработки прерывания производится подсчет количества таких ситуаций и при превышении определенного значения выполняется возврат в нормальный режим работы. Нажатие на любую кнопку приводит к сбросу данного счетчика. Также TIMER1 дополнительно используется для получения мигания задаваемого разряда.

Принцип работы выходного устройства
Принцип работы выхода

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

 

 Управляющая программа на языке mikroPascal

program TicPic;
var rm,rs,slp:byte;
    port_array: array[3] of Byte;
    din: sbit at portc.2;
    dclc: sbit at portc.1;
    load: sbit at portc.3;
    Soft_I2C_Scl     : sbit at RC4_bit;
    Soft_I2C_Sda     : sbit at RC5_bit;
    Soft_I2C_Scl_Direction : sbit at TRISC4_bit;
    Soft_I2C_Sda_Direction : sbit at TRISC5_bit;
    rezim:byte;
    Tzad0,Tzad1,Tzad2,H1,H2,button1,button2,tim0,inter,tmrout:byte;
    ZadHi,ZadLo,Themperature:word;
 
{Преобразование чисел в код индикатора}
function mask(num: byte): byte;
begin
  num:=num and %00001111;
  case num of    //egfabcdp
     0 : result:= %10111110;
     1 : result:= %00001100;
     2 : result:= %11011010;
     3 : result:= %01011110;
     4 : result:= %01101100;
     5 : result:= %01110110;
     6 : result:= %11110110;
     7 : result:= %00011100;
     8 : result:= %11111110;
     9 : result:= %01111110;
    10 : result:= %01000000;
    11 : result:= %01000000;
    12 : result:= %01000000;
    13 : result:= %01000000;
    14 : result:= %11100100;
    15 : result:= %00000010;
   end; //case end
end;//~mask
 
{Запись цифр в индикатор}
procedure ShowDig(dig:byte);
var i1:byte;
begin
  for i1:=1 to 8 do
    begin
      if dig.0=1 then din:=1 else din:=0;
      dig:=dig shr 1;
      dclc:=1;
      nop;
      dclc:=0;
      din:=0;
    end;
end;   //~ShowDig
 
{Чтение температуры из MCP9800}
procedure Read_T();
  begin
    clrwdt;
    {Чтение температуры}
    Soft_I2C_Start();
    Soft_I2C_Write(0x90);
    Soft_I2C_Write(0x00);     //mcp9800
    Soft_I2C_Start();
    Soft_I2C_Write(0x91);
    rm := Soft_I2C_Read(1);
    rs := Soft_I2C_Read(0);
    Soft_I2C_Stop();
    {Переход в спящий режим}
    Soft_I2C_Start();
    Soft_I2C_Write(0x90);
    Soft_I2C_Write(0x01);           //mcp9800
    Soft_I2C_Write(%01100001);      //mcp9800
    Soft_I2C_Stop();
  end; //~ReadT
 
{Преобразование температуры}
procedure Calc_Temperature(temp1,temp2: byte;);
var i2,temp:byte;
    tmp:word;
begin
  if (temp1 and $80) = 0x80 then
  begin
     temp1 := not temp1 + 1;
     port_array[0]:=%01000000;
     port_array[1]:=mask((temp1 / 10) mod 10);
     port_array[2]:=mask(temp1 mod 10);
  end
  else
  begin
    temp:=temp2 shr 4;
 
    port_array[0]:=mask((temp1 / 10) mod 10);
    port_array[1]:=mask(temp1 mod 10)+1;
    tmp:=0;
    i2:=0;
    while i2 < temp do
      begin
         tmp:=tmp+625;
         i2:=i2+1;
      end;
    port_array[2]:=mask((tmp /1000) mod 10);
    Themperature:=temp1*10+((tmp /1000) mod 10);
 
  end;
end; //~Calc_Temperature
 
{Обработчик прерываний}
procedure interrupt;
begin
  gie_bit:=0;
  clrwdt;
  //Прерывание по входу Int
  if (intf_bit=1) and (inte_bit=1) then
    begin 
      rezim:=5;
      INTE_bit:=0;
      INTF_bit:=0;
      //Запуск таймера 1
      tmr1h:=0;
      tmr1l:=0;
      tmr1on_bit:=1;
      inter:=1;
      tmr1ie_bit:=1;
      tmrout:=0;
    end;
  // прерывание по таймеру 1
  if tmr1if_bit=1 then
    begin
      tmrout:=tmrout+1;
      if tmrout>30 then
        begin
          rezim:=0;       //Сброс режима настройки при переполнении таймера
          tmr1on_bit:=0;
          tmr1ie_bit:=0;
          INTF_bit:=0;
        end;
      tmr1if_bit:=0;
    end;
  gie_bit:=1;
end;
{Вывод информации на дисплей}
procedure ShowDisplay;
  begin
    ShowDig(port_array[2]);
    ShowDig(port_array[1]);
    dclc:=1;
    nop;
    dclc:=0;
    ShowDig(port_array[0]);
    load:=1;
    nop;
    load:=0;
  end;
 
// Процедура задания уставки
procedure settings;
  begin
           while (rezim>0) do
              begin
                clrwdt;
                if rezim>5 then rezim:=0;
                // Обработка кнопки 1 (режим)
                if porta.2=1 then
                  begin
                    delay_ms(50);
                    tmrout:=0;
                      if porta.2=1 then button1:=1;
                  end;
                if (porta.2=0) and (button1=1) then
                  begin
                    button1:=0;
                    if inter=1 Then inter:=0 else rezim:=rezim-1;
                  end;
                 //Обработка кнопки 2 (настройка)
                 if porta.1=1 then
                  begin
                    delay_ms(50);
                    tmrout:=0;
                      if porta.1=1 then button2:=1;
                  end;
                if (porta.1=0) and (button2=1) then
                  begin
                    button2:=2;
                  end;
                clrwdt;
 
                //Работа с десятыми уставки
                if rezim=5 then
                  begin
                    //Настройка отображения цифр
                    port_array[2]:=mask(Tzad2);
                    port_array[1]:=mask(Tzad1)+1;
                    port_array[0]:=mask(Tzad0);
                    if tmr1h.7=1 then port_array[2]:=mask(15);  //мигание по таймеру
                    if button2=2 then                           //установка нужной цифры
                      begin
                        Tzad2:=tzad2+1;
                        if Tzad2>9 then Tzad2:=0;
                        button2:=0;
                      end;
                  end;
                //Работа с единицами уставки
                if rezim=4 then
                  begin
                    port_array[2]:=mask(Tzad2);
                    port_array[1]:=mask(Tzad1)+1;
                    if tmr1h.7=1 then port_array[1]:=mask(15)+1;
                    if button2=2 then
                      begin
                        Tzad1:=tzad1+1;
                        if Tzad1>9 then Tzad1:=0;
                        button2:=0;
                      end;
                  end;
                //Работа с десятками уставки
                if rezim=3 then
                  begin
                    port_array[1]:=mask(Tzad1)+1;
                    port_array[0]:=mask(Tzad0);
                    if tmr1h.7=1 then port_array[0]:=mask(15);
                    if button2=2 then
                      begin
                        Tzad0:=tzad0+1;
                        if Tzad0>9 then Tzad0:=0;
                        button2:=0;
                      end;
                  end;
                clrwdt;
                //Работа с десятыми гистерезиса
                if rezim=2 then
                  begin
                    port_array[0]:=mask(14);
                    port_array[2]:=mask(h2);
                    port_array[1]:=mask(h1)+1;
                    if tmr1h.7=1 then port_array[2]:=mask(15);
                    if button2=2 then
                      begin
                        h2:=h2+1;
                        if h2>9 then h2:=0;
                        button2:=0;
                      end;
                  end;
                //Работа с единицами гистерезиса
                if rezim=1 then
                  begin
                    port_array[2]:=mask(h2);
                    port_array[1]:=mask(h1)+1;
                    if tmr1h.7=1 then port_array[1]:=mask(15)+1;
                    if button2=2 then
                      begin
                        h1:=h1+1;
                        if h1>9 then h1:=0;
                        button2:=0;
                      end;
                  end;
                ShowDisplay;              //Вывод цифр на дисплей
              end;
            slp:=1;
            clrwdt;
            //Запись уставки в EEPROM
            EEPROM_Write(0x02,Tzad2);
            EEPROM_Write(0x03,Tzad1);
            EEPROM_Write(0x04,Tzad0);
            EEPROM_Write(0x05,h2);
            EEPROM_Write(0x06,h1);
            //Вычисление целого уставки
            ZadHi:=(Tzad2+h2)+((Tzad1+h1)*10);
            ZadHi:=ZadHi+(Tzad0*100);
            ZadLo:=Tzad0*100;
            ZadLo:=ZadLo+((Tzad1)*10);
            ZadLo:=ZadLo+Tzad2;
            while (porta.2=1) do delay_ms(20);
            tmr1on_bit:=0;   //Останов таймера 1
            tmr1ie_bit:=0;   //Запрет прерывания таймера 1
            tmr1if_bit:=0;   //Запрет прерывания таймера 1
            INTF_bit:=0;     //Сброс флага прерывания Int
            INTE_bit:=1;     //Разрешение прерывания Int
  end;
 
begin   { Main program }
 //Инициализация регистров
  CMCON0:=0x07;
  ANSEL:=0;
  TRISC:=0;
  TRISA:=%00000110;
 
  PORTA:=0;
  PORTC:=0;
  intcon:=%11010000;        //Настройка прерываний
  button1:=0;
  button2:=0;
  tim0:=0;
 
  option_reg:=%01001111;   //Подключение предделителя к WDT
  t1con:=%00110100;
  rezim:=0;
  Themperature:=0;
  //Чтение задания из EEPROM
  Tzad2:=EEPROM_Read(0x02);
  Tzad1:=EEPROM_Read(0x03);
  Tzad0:=EEPROM_Read(0x04);
  H2:=EEPROM_Read(0x05);
  H1:=EEPROM_Read(0x06);
  //Вычисление задания
  ZadHi:=(Tzad2+h2)+((Tzad1+h1)*10);
  ZadHi:=ZadHi+(Tzad0*100);
  ZadLo:=Tzad0*100;
  ZadLo:=ZadLo+((Tzad1)*10);
  ZadLo:=ZadLo+Tzad2;
  //Инициализация датчика MCP9800
  clrwdt;
  Soft_I2C_Init();
  Soft_I2C_Start();
  Soft_I2C_Write(0x90);
  Soft_I2C_Write(0x01);           //mcp9800
  Soft_I2C_Write(%01100001);      //mcp9800
  Soft_I2C_Stop();
  //Основной цикл
  while 1 do
    begin
        clrwdt;
        Read_T();                 //Чтение температуры
        Calc_Temperature(rm,rs);  //Вычисление температуры
        ShowDisplay;              //Вывод цифр на дисплей
        if Themperature > ZadHi then setbit(Portc,0); //Установка выхода при превышении уставки
        if Themperature < ZadLo then clearbit(Portc,0); //Сброс выхода при если t меньше уставки
        //Цикл спящего режима
        slp:=5;       //Количество пробуждений до выхода из спящего режима
        while slp>0 do
          begin
            if slp=1 then
              begin
                clrwdt;
                // Запуск однократного измерения температуры
                Soft_I2C_Start();
                Soft_I2C_Write(0x90);
                Soft_I2C_Write(0x01);
                Soft_I2C_Write(%11100001);
                Soft_I2C_Stop();
              end;
            sleep;  //Переход в спящий режим
            nop;
            //Старт настройки
            if rezim>0 then settings;
            slp:=slp-1;
          end;
    end;
end.