Продолжение котла с плавным изменением мощности нагрузки.

В процессе эксплуатации электро котла, пришли на ум некоторые мысли для улучшения характеристик конструкции, а именно переосмыслил способ управления изменением мощности. Решил применить фазовое изменение мощности.

То есть будем изменять размер полуволны синусоиды сетевого напряжения. Суть в следующем: микроконтроллер ждет перехода через ноль сетевого напряжения, отсчитывает паузу от 0 до 10 мсек. (в зависимости от необходимой мощности).                                                               В управляющей программе, использованы внешниe прерывания по входу INT0.

Вместо DS18B20, применил терморезистор NTS, он гораздо дешевле, а точность достаточная для данной конструкции. Первая строчка дисплея показывает установленную температуру (устанавливается переменным резистором), вторая строка: измеренная терморезистором температура и примерная мощность подводимая к Электро ТЭНам.  В железе пока не проверял, но думаю проблем не будет. Разработал печатную плату :

Вот так может выглядеть эта печатка если все сделать правильно:

 

Ниже представлен код С для CvAvr.

/*******************************************************

Project : VodynoiKotel
Version : V3
Date : 20.12.2017
Author : Tsimbal
Company : my
Comments:
Chip type : ATmega8
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*******************************************************/

#include <mega8.h>
#include <math.h>
#include <delay.h>
#include <stdio.h>
// Alphanumeric LCD functions
#include <alcd.h>

#define TRIAC1 PORTB.1 //Порт управления Семистором 1
#define TRIAC2 PORTB.2 //Порт управления Семистором 2
#define MAX_CONT 235
#define MIN_CONT 178

#define B 3950 //Коэфициент для расчета температуры термистора
#define SERIAL_R 10000 //Номинал последовательного сопротивления
#define TERMISTOR_R 10000 //Номинал сопротивления термистора
#define NOMINAL_T 25 //Номинальная температура

// Declare your global variables here
char lcd_buffer[33]; //Буффер для вывода на дисплей
float ADC0_ustanovka_temperatury, ADC1_termistor ; //переменные для установленной и измеренной температуры
volatile unsigned int zadergka; //Переменная задержки включения Семистора после перехода через ноль
float Temp=0, Termo_Rez = 0, deltaTemp = 0, P = 0; //Переменные для вычисления измеренной температуры и разницы между
// установленной и измеренной температурой
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void) //Ждем перехода синусоиды сетевого напряжения через НОЛЬ
{
// Place your code here
TRIAC1 = 0; //Семисторы отключены
TRIAC2 = 0;

TCCR0=(1<<CS02) | (0<<CS01) | (1<<CS00); //Запускаем таймер Timer/Counter 0
TCNT0=zadergka; //В регистр таймера записываем величину задержки управляющего импульса
//PORTD.7 =1;
// delay_us(200);
// PORTD.7 =0;
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //Таймер отсчитал время задержки
{
// Reinitialize Timer 0 value
//TCNT0=0xB2;
// Place your code here
TRIAC1 = 1; //Посылаем импульс на управляющие электроды Семисторов
TRIAC2 = 1;
delay_us(200); //Длительностью 100 мксек

TRIAC1 = 0;
TRIAC2 = 0;
TCNT0=0x00; //Обнуляем регистр
TCCR0=(0<<CS02) | (0<<CS01) | (0<<CS00); //Отключаем таймер
}
//****************************************************************
// Запускаем измерение Аналого Цифровым Преобразователем
// Voltage Reference: AREF pin
#define ADC_VREF_TYPE ((0<<REFS1) | (0<<REFS0) | (0<<ADLAR))

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion

ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW;
}
//********************************************************
void put_lcd() //Функция вывода информации на дисплей
{

sprintf(lcd_buffer,»T1=%.1f\xdf» «C»,ADC0_ustanovka_temperatury); // Выводим на дисплей значение установленной температуры
//lcd_clear();
lcd_gotoxy(0, 0);
lcd_puts(lcd_buffer);
delay_ms(5);

sprintf(lcd_buffer,»T2=%.1f\xdf» «C»,Temp);
lcd_gotoxy(0, 1);
lcd_puts(lcd_buffer);
delay_ms(5);

sprintf(lcd_buffer,»P=%.1f»,P);
lcd_gotoxy(10, 1);
lcd_puts(lcd_buffer);
delay_ms(5);

/* sprintf(lcd_buffer,»d=%.1f»,deltaTemp);
lcd_gotoxy(10, 0);
lcd_puts(lcd_buffer);
delay_ms(5); */
}

oid Ustanovka_Temp() //Функция измерения установленной Управляющим Резистором температуры
{
ADC0_ustanovka_temperatury = read_adc(0)/11;
// zadergka = ((int)ADC0_ustanovka_temperatury/5)+125;
}

void Termistr_Temp() //Функция измерения и вычисления температуры Терморезистора
{
ADC1_termistor = read_adc(1);

Termo_Rez = 1023.0 / ADC1_termistor — 1;
Termo_Rez = SERIAL_R/Termo_Rez;

Temp = Termo_Rez / TERMISTOR_R;
Temp = log(Temp);

Temp /= B;
Temp += 1.0 / (NOMINAL_T +273.15);
Temp = 1.0 / Temp;
Temp -= 273.15;
// Temp += 2;
}

void Raschet_zadergki()
{
deltaTemp = ADC0_ustanovka_temperatury — Temp;
zadergka =((int)deltaTemp * 8)+ MIN_CONT;
if(zadergka < MIN_CONT) {zadergka = MIN_CONT;};
if(zadergka > MAX_CONT) {zadergka = MAX_CONT;};
if(Temp > 80) {Temp = MIN_CONT;};

P = (deltaTemp * 561.4035)/1000;

if(P > 4.0) {P = 4.0;};
if(P < 0) {P = 0;};
}

//********************************************************

void main(void)
{
// Declare your local variables here
unsigned int cont; //Переменная для плавного включения
// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=0 Bit1=0 Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) |

(0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization

// Clock source: System Clock
// Clock value: 7,813 kHz
TCCR0=(1<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0xBA;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (1<<TOIE0);

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: Off
GICR|=(0<<INT1) | (1<<INT0);
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
GIFR=(0<<INTF1) | (1<<INTF0);

// ADC initialization
// ADC Clock frequency: 500,000 kHz
// ADC Voltage Reference: AREF pin
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
SFIOR=(0<<ACME);

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS — PORTD Bit 0
// RD — PORTD Bit 1
// EN — PORTD Bit 5
// D4 — PORTB Bit 4
// D5 — PORTB Bit 5
// D6 — PORTB Bit 6  

// D7 — PORTB Bit 7
// Characters/line: 16
lcd_init(16); //Инициализация дисплея
lcd_clear(); //Отчистка дисплея
lcd_gotoxy(0,0); //Выводим курсор в нулевую позицию

lcd_putsf(«TERMOSTAT P=4kW»); //Выводим на дисплей надпись
lcd_gotoxy(3,1);
lcd_putsf(«TSYMBALA»); //Ну, это моя фамилия можно не программировать:)
delay_ms(5000); //пять секунд любуемся на надпись

// Global enable interrupts
#asm(«sei«)

for(cont = 120;cont< 155;cont ++) //Плавно включаем ТЭНы на половину мощности
{
zadergka = cont;

delay_ms(50);
}
lcd_clear(); //Отчистка дисплея
while (1)
{
// Place your code here
Ustanovka_Temp();
Termistr_Temp();
Raschet_zadergki();
put_lcd();
}
}