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

в 23:39, , рубрики: Песочница, метки: , , ,

Доброго времени суток, читатели.

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

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

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

Схема

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

Плата

Делал ЛУТом:

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

С прошивкой пришлось поколдовать, т.к. много в 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(" xf8Crn");
            itoa(temp_ust,temp_str);
            putsf("Set = ");
            puts(temp_str);
            putsf(" xf8Crn");
           }
        
          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;
            };
          }
    }

Внешний вид:

корпус

За внешний вид не ругайте — стоит в бане, потому немного в саже.

Данный девайс работает без перерыва уже год.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js