Доброго времени суток!
Уже год, как эксплуатируется собранный из подручных материалов электрокамин и, думаю, пришло время поделиться как можно его самостоятельно собрать.
Изначально как ориентир для повторения был выбран электрокамин с эффектом живого пламени. Думаю, что не ошибусь, что самые эффектные камины производит Dimplex.
В принципе, как работает такой камин вполне понятно: ультразвуковой парогенератор создает туман, который за счет конвекции от нагретых ламп поднимается вверх создавая эффект пламени и дыма. Также в нём реализована имитация тления углей и озвучка потрескивающих дров.
Самое сложное, на мой взгляд, это сделать правдоподобный очаг. Мне в этом плане повезло, на сервисной базе Dimplex всего за 1000р. нашёлся очаг с работающими встроенными в угли светодиодами и корпусом парогенератора с рабочим пьезоизлучателем (без генератора).
К стати, светодиоды в "поленьях" были подключены по следующей схеме:
В оригинальном исполнении выводы из разных "углей" объединены в несколько групп (несколько "положительных" групп и "отрицательных" групп, причем плюсовые и отрицательные выводы объединяются в группы с разных "углей"), которые в общем меняют яркость плавно и не одновременно. Предположительно, в оригинале на выходы подаются ШИМ "синусы" с разным периодом.
Теперь можно было браться за изготовление остальной электроники.
1. Генератор дыма
Было опробовано несколько схем, но самой эффективной и стабильной оказалась следующая:
Поскольку пар из камеры парогенератора сам не очень-то выходит, из пластика была изготовлена камера с вентилятором. Туда же помещен радиатор, на который крепится КТ805. Собранный генератор помещен на свое штатное место в отсек под излучателем.
2. Лампы подсветки
Лампы для подсветки взяты галогенные на 12В/35Вт с отражателем и светофильтром. Соединены по 2 шт. последовательно, чтобы была возможность питаться от одного с генератором блока питания на 24В.
Изначально планировал реализовать мерцание и для этих ламп, но в итоге отказался, так как наиболее стабильно камин работает после хорошего прогрева, т.е. при максимальной конвекции.
При заказе ламп не угадал с цветом светофильтров (взял желтые и красные), точнее нужного просто не было. Поэтому в итоге использую дополнительный фильтр из оранжевого стекла:
3. Схема управления
Схема управления собрана на модулях Arduino: контроллер Arduino (любой), модуль PCA9685 (расширитель ШИМ), модуль проигрывателя МР3, модуль KY-022 (ИК-приемник), а также использованы три источника питания на 5В (питание контроллера), 12В (питание светодиодов) и 24В (питание ламп и генератора пара), пять ключей на MOSFET с низким напряжением открытия (взяты с материнской платы). Подключение выполнено по следующей схеме:
Расширитель ШИМ изначально взят с перспективой увеличения каналов управления светодиодами, лампами, скоростью вращения вентилятора, в итоге просто прижился. По ИК каналу реализована возможность управления громкостью и выбором файла озвучки камина.
4. Программа
/*
ПРОГРАММА управления электроникой камина
*/
# include <EEPROM.h>
# include <Wire.h>
# include <iarduino_MultiServo.h> // Подключаем библиотеку iarduino_MultiServo
iarduino_MultiServo MSS; // Объявляем объект MSS, для работы с библиотекой
# include <SoftwareSerial.h>
# include <DFPlayer_Mini_Mp3.h>
# include <IRremote.h>
//Описываем переменные и константы
volatile int count = 511;
volatile const int max_A = 4095;
volatile const int min_A = 1500;
volatile int count1 = 0;
volatile int count2 = 0;
volatile int count3 = 0;
volatile int count4 = 0;
volatile byte f = 1; //частота канала 1
volatile byte f1 = 2; //частота канала 2
volatile byte f2 = 3; //частота канала 3
volatile byte f3 = 4; //частота канала 4
volatile int time_T = 100;
volatile int time_T1 = 200;
volatile int time_T2 = 150;
volatile int time_T3 = 300;
volatile byte volume = 30; //громкость (0--30)
volatile byte tembr = 4; //тембр (1--6)
int RECV_PIN = 11; //пин подключения IR приёмника
IRrecv irrecv(RECV_PIN);
decode_results results;
//переменные для мерцания
unsigned long time0;
unsigned long time1;
unsigned long time2;
unsigned long time3;
byte j = 0;
//базовый массив для ШИМ
int shim_A [61] = {};
//настраиваем контроллер
void setup() {
//выключение компаратора
ACSR = 0x80;
TIMSK1 = 0b00000000;//запрещаем прерывание Т1
//настройка регистров управления Т1,режим Fast PWM 9bit (Кдел=511), выходы не инверсные
TCCR1A = 0b00000000 | (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = 0b00000000 | (1 << WGM12) | (1 << CS10) | (1 << CS12); //коэф.деления - 1024 - 16000000/511/1024=30.57Гц
//TCNT1 = koef; //16 бит, настройка частоты прерывания, начальное значение счетного регистра Т1
OCR1A = 0; //9 бит 0-511
pinMode(9, INPUT);//вход датчика воды в испарителе
Serial.begin(9600);
//IR приемник
irrecv.enableIRIn(); // Start the receiver
// заполняем массив ШИМ
byte i = 0;
while (i < 61) {
shim_A[i] = int((max_A + min_A) / 2 + (max_A - min_A) / 2 * sin((3.1415 * i) / 30)) + 1;
i++;
// Serial.println(shim_A[i - 1]);
}
//настройка MP3
mp3_set_serial (Serial);
mp3_set_volume (volume);
mp3_set_EQ (tembr-1);
delay (100);
mp3_play (1);
delay (100);
randomSeed(analogRead(0)); //генерируем псевдослучайную последовательность
//Настройка расширителя ШИМ
MSS.invert(0);
MSS.outdrv(1); // указывая адрес MultiServoShield на шине I2C: 0x40 (по умолчанию 0x40)
MSS.begin(0x40, 1000); // Инициируем работу с MultiServoShield (адрес,частота)
time0 = millis();
time1= millis();
time2= millis();
time3= millis();
//разрешаем прерывания
TIMSK1 = 0b00000100; //включаем прерывание таймера Т1 по переполнению
}
/************ЦИКЛ ОСНОВНОЙ ПРОГРАММЫ**********/
void loop() {
vent();
//формирование мерцания
if (millis() - time0 > time_T) {
f = random(0, 5);
count1 = random(15, 48);
time_T = random(200, 999);
time0 = millis();
}
if (millis() - time1 > time_T1) {
f1 = random(0, 5);
count2 = random(15, 48);
time_T1 = random(180, 600);
time1 = millis();
}
if (millis() - time2 > time_T2) {
f2 = random(0, 5);
count3 = random(15, 48);
time_T2 = random(110, 600);
time2 = millis();
}
if (millis() - time3 > time_T3) {
f3 = random(1, 5);
count4 = random(15, 40);
time_T3 = random(300, 800);
time3 = millis();
}
//датчик воды
if (digitalRead(9)==HIGH) {
MSS.analogWrite(4, 255);
}
if (digitalRead(9)==LOW) {
MSS.analogWrite(4, 0);
}
// MP3
if (irrecv.decode(&results))
{
//Serial.println(results.value);
if (results.value==16736925)
{
volume++;
if (volume>30) {volume=30;}
mp3_set_volume(volume);
}
if (results.value==16754775)
{
volume--;
if (volume<1) {volume=1;}
mp3_set_volume(volume);
}
if (results.value==16738455) { mp3_play (1); }
if (results.value==16750695) { mp3_play (2); }
if (results.value==16756815) { mp3_play (3); }
if (results.value==16724175) { mp3_play (4); }
if (results.value==16724175) { mp3_play (5); }
if (results.value==16724175) { mp3_play (6); }
if (results.value==16724175) { mp3_play (7); }
if (results.value==16724175) { mp3_play (8); }
if (results.value==16724175) { mp3_play (9); }
if (results.value==16712445)
{
//записать в память установленный уровень громкости и тембра
}
if (results.value==16720605)
{
//установка тембра --
tembr--;
if (tembr<1) {tembr=1;}
mp3_set_EQ (tembr-1);
}
if (results.value==16761405)
{
//установка тембра ++
tembr++;
if (tembr>6) {tembr=6;}
mp3_set_EQ (tembr-1);
}
//Serial.println(volume);
// Serial.println(results.value);
irrecv.resume(); // Receive the next value
}
}
/********************************************/
//подпрограмма управления мерцанием
void vent()
{
TIMSK1 = 0b00000000;//запрещаем прерывание Т1
MSS.analogWrite(0, shim_A[count1]);
MSS.analogWrite(1, shim_A[count2]);
MSS.analogWrite(2, shim_A[count3]);
MSS.analogWrite(3, shim_A[count4]);
TIMSK1 = 0b00000100;
}
//***************************************************//
//функция прерывания таймера Т1 по переполнению
ISR(TIMER1_COMPB_vect)
{
TIMSK1 = 0b00000000;//запрещаем прерывание Т1
//задаем параметры ШИМ Т1
OCR1A = 10+ 1 * f; //shim_A[500]; //9 бит 0-511 - канал 1 вых.9
count1 = count1 + 1 * f; //увеличиваем счетчик на 1
count2 = count2 + 1 * f1;
count3 = count3 + 1 * f2;
count4 = count4 + 1 * f3;
if (count1 > 60) { //если импульс не сформирован до конца, то продолжаем менять параметр ШИМ
count1 = 0;
OCR1A = 0;
}
if (count2 > 60) { //если импульс не сформирован до конца, то продолжаем менять параметр ШИМ
count2 = 0;
OCR1A = 0;
}
if (count3 > 60) { //если импульс не сформирован до конца, то продолжаем менять параметр ШИМ
count3 = 0;
OCR1A = 0;
}
if (count4 > 60) { //если импульс не сформирован до конца, то продолжаем менять параметр ШИМ
count4 = 0;
OCR1A = 0;
}
TIMSK1 = 0b00000100;
}
5. Итог
В целом результат оказался неплохим. Из относительно неудобства - сразу не реализовано управление скоростью вращения вентилятора для выдува пара, а теперь не сильно хочется переделывать. Результат работы можно посмотреть на видео по ссылкам здесь и здесь. Отдельно мерцание углей можно посмотреть здесь.