Pull to refresh

Термостат для теплого пола на ATTiny13

Доброго времени суток, хабрасообщество. У нас есть баня. Пол в бане выстелен керамической плиткой. Ходить по такому полу без подогрева то еще удовольствие. Поэтому под плиткой находится теплый пол. Для его работы был установлен термостат для тёплого пола TermoControl ТСL-01.11SF. Только вот работать нормально он через месяц отказался. Часто он просто не включался, когда ноги к плитке уже начинали примерзать. Дело было зимой и надо срочно было поставить что-то ему на замену, а т.к. живу в глубинке, до ближайшего нужного магазина примерно 150 км, дорог нет — решил сделать термостат на том, что есть в столе — ATTiny13 и прочей рассыпухе.

В качестве датчика температуры было решено использовать широко известный датчик DS18B20. Регулятором выступил переменный резистор из старого термостата. Одним из основных требований было — запихать обратно в тот же корпус, ну и надежная работа.

В результате родилась схема:

Схема

UART тут для отладки, в принципе, сейчас не используется, но убирать я его не стал. При желании его можно использовать для вывода текущей и установленной темпертуры куда-нибудь еще. Для индикации режима работы используется 2 светодиода: красный — нагрев, зелёный — дежурный режим. Нагрузка включается с помощью реле. В качестве источника питания используется готовый блок питания на 12 вольт, тинька запитана через 7805. Плату рисовал в Sprint-Layout:

Плата

Суть такова: потенциометром устанавливаем напряжение от 0 до 5 В, оно считывается с помошью ADC, встроенного в контроллер. Полученное значение пересчитывается в требуемую температуру пола. С датчика DS18B20 считываем текущую температуру и сравниваем с установленной с помощью переменного резистора. Если температура меньше — включаем нагрев, достигли требуемую — выключаем нагрев и уменьшаем установленную на 5 градусов (чтобы срабатывания не были очень частыми). Остыли до требуемой температуры — возвращаем обратно нормальное установленное значение. Т.к. выводов в ATTiny13 мало, то использовал один вывод для управлением светодиодами индикации и реле.

Плату делал ЛУТом:

Плата готовая

С прошивкой пришлось поколдовать, т.к. много в 13-ю тиньку не запихнуть. Проект писал на C в CVAvr. Функции опроса датчика температуры и программный UART мне написать помогли, т.к. сам я не программист.

Исходник
#include <tiny13.h>
#include <delay.h>
#include <1wire.h>
#include <stdlib.h>

#define UART_FREQ 124 //9600Hz F_CPU/TIM0_PRESCALER(8)/BAUD
#define DS_FREQ 9600 //1Hz BAUD/FREQ
#define TX_PIN PORTB.0
#define NAGREV_ON PORTB.2=1
#define NAGREV_OFF PORTB.2=0
#define DELTA 5     //разбег по срабатыванию вкл/выкл

#define ADC_INPUT 2
#define ADC_VREF_TYPE 0x20

unsigned int ds_cnt;
signed char temp; //температура в градусах
unsigned char temp_str[6]; //в строке
signed char temp_ust; //установка температуры
unsigned char p_nagrev;
unsigned char adc_data;
unsigned char tx_bit_cnt;
unsigned char tx_data;

bit temp_convert;
bit start_tx,tx;

signed char ds18b20_temperature(void)
    {
    unsigned char LSB,MSB;
    w1_init();   
    w1_write(0xCC); 
    w1_write(0xBE); 
    LSB=w1_read();    
    MSB=w1_read();
    w1_init();   
    w1_write(0xCC); 
    w1_write(0x44); 
    return ((MSB<<4)&0xf0) | ((LSB>>4)&0x0f);
    }
    
void ds_init(void)
    {
    w1_init();
    w1_write(0x4e);   
    w1_write(0x64);
    w1_write(0xD8);
    w1_write(0x1f);
    w1_write(0x48);
    delay_ms(15);
    }

void putchar(unsigned char data)
    {
    while (tx||start_tx){};
    delay_ms(1);
    tx_data=data;
    start_tx=1;
    }

void puts(char *str)
    {
    char k;
    while (k=*str++) putchar(k);
    }

void putsf(char flash *str)
    {
    char k;
    while (k=*str++) putchar(k);
    }

interrupt [TIM0_COMPA] void timer0_compa_isr(void)
    {
        {
        if (start_tx==1)
            {
            start_tx=0;
            tx=1;
            TX_PIN=0;
            tx_bit_cnt=0;
            goto DS;
            }
        if (tx==1)
            {
            if (tx_bit_cnt<8)
                {                                
                TX_PIN = ((tx_data>>tx_bit_cnt)&0x01) ? 1 : 0;
                tx_bit_cnt++;
                }
            else
                {
                TX_PIN=1;
                tx=0;
                }
            }
        DS:
        ds_cnt++;
        if (ds_cnt>=DS_FREQ)
            {
            temp_convert=1;
            ds_cnt = 0;
            }
        }
    }

interrupt [ADC_INT] void adc_isr(void)
    {
    adc_data=ADCH;
    ADCSRA|=0x40;
    }

void main(void)
    {
    #pragma optsize-
    CLKPR=0x80;
    CLKPR=0x00;
    #ifdef _OPTIMIZE_SIZE_
    #pragma optsize+
    #endif

    PORTB=0x01;
    DDRB=0x0D;

    TCCR0A=0x02;
    TCCR0B=0x02;
    TCNT0=0x00;
    OCR0B=0x00;
    OCR0A=UART_FREQ;

    TIMSK0=0x04;

    ACSR=0x80;
    ADCSRB=0x00;
    DIDR0=0x00;

    DIDR0&=0x03;
    DIDR0|=0x10;
    ADMUX=ADC_INPUT | (ADC_VREF_TYPE & 0xff);
    ADCSRA=0xEF;
    ADCSRB&=0xF8;

    ds_init();

    #asm("sei")
    p_nagrev = 0;
    while (1)
          {
          if (temp_convert==1)
            {
            temp = ds18b20_temperature();
            temp_convert=0;
            itoa(temp,temp_str);
            putsf("Temp= ");
            puts(temp_str);
            putsf(" \xf8C\r\n");
            itoa(temp_ust,temp_str);
            putsf("Set = ");
            puts(temp_str);
            putsf(" \xf8C\r\n");
           }
        
          temp_ust = (p_nagrev == 1)?(adc_data/5-DELTA):(adc_data/5); //вычисляем установку температуры (диапазон от 0 до 51 градуса) 
        
          if (temp < temp_ust){
            NAGREV_ON;
            p_nagrev = 0;
          }
          else{
            NAGREV_OFF;
            p_nagrev = 1;
            };
          }
    }

Внешний вид:

корпус

Нагрев выключен:



Нагрев включен:



За внешний вид не ругайте — стоит в бане, потому немного в саже. Данный девайс работает без перерыва уже год.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.