После установки натяжного потолка в одной из комнат нам пришлось распрощаться с 5-рожковой люстрой 5x100 Вт и диммером "Сапфир" c плавным управлением яркостью с любого пульта ДУ. Лампы накаливания сильно греются и потолку от них нехорошо, поэтому мы начали искать замещающее решение с использованием светодиодных ламп. Света в сумме хотелось не меньше, такого же лампово-теплого по спектру и по-прежнему подвластного пульту.
Оставлю за кадром решения, которые мы рассматривали, но в итоге направления осталось два:
Оставлю за кадром решения, которые мы рассматривали, но в итоге направления осталось два:
- диммер для светодиодных ламп и использование недешевых диммируемых ламп
- некий китайский контроллер, монтируемый в люстру и позволяющий последовательно зажигать до 3 каналов, повторным нажатием выключателя. Главный его недостаток - он не помнит установленным последним уровень освешенности. Достоинство решения - использование любых светодиодных ламп.
Параллельно с этим руки зачесались спаять что-нибудь самодельно-кустарное, получив все желаемые функции быстро и уже начать пользоваться люстрой, продолжая поиск более красивого и функционального аналога.
Итак, для очередного проекта выходного дня нам понадобились:
- 4 настенных светильника для ванной комнаты. Для самоделки удобны тем, что будучи соединенными попарно винтами образуют корпуса для электроники между подставками
- 4 светодиодные лампы с патроном e27 на 5, 10, 20 и 20 Вт
- алюминиевая трубка, алюминиевая полоса, винты и гайки м4
- клеммы винтовые 2,5мм, провода
- зарядка от телефона USB, которую мы лишили корпуса
- arduino nano
- 4 реле модуля, управляемых 5В логикой
- ИК-приемник VS1838B
- микродинамик
Собранная люстра обладает следующими функциями:
- включение-выключение обычным клавишным выключателем - вся электроника "нормально-разомкнута"
- управление с любого пульта ДУ (используется 2 кнопки - прибавить яркость, убавить яркость)
- 11 уровней яркости: 5Вт, 10Вт, 15Вт(5+10), 20Вт, 25Вт(20+5), 30 Вт(20+10), 35Вт(20+10+5), 40Вт(20+20), 45Вт(20+20+5), 50Вт(20+20+10), 55Вт(20+20+10+5)
- "плавный старт" - если в люстре в последний раз были включены, например, 3 лампы, то при повторном включении они будут последовательно включены с интервалом в 2 секунды - по нарастанию их мощности - чтобы не ослепить входящего в комнату человека
- обучение под любой пульт ДУ - троекратное нажатие последовательности любых трех кнопок на любом пульте вводит люстру в режим обучения - издается звуковой сигнал. В режиме обучения ожидается нажатие любых двух кнопок - они будут запомнены как новые кнопки управления яркостью
- запоминание установленного уровня яркости в энергонезависимой памяти через 30 сек после последней регулировки
- автовыключение света через 6 часов
- звуковое подтверждение всех операций по регулировке, обучению, сохранении настроек
Код программы выглядит так:
#include <IRremote.h>
#include <EEPROM.h>
int relay1 = 5; // 5W
int relay2 = 6; // 10W
int relay3 = 7; // 20W
int relay4 = 8; // 20W
int buzzer = 9; // speaker or led
unsigned long history[9];
unsigned long power_up = 0xFFA05F;
unsigned long power_down = 0xFF20DF;
unsigned long timer = millis();
boolean not_rec = false;
int receiverPin = 11;
IRrecv irrecv(receiverPin);
decode_results results;
byte power;
int mem_addr = 0;
long EEPROMReadlong(long address) {
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
void EEPROMWritelong(int address, long value) {
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}
void set_power(int p) {
timer = millis();
not_rec = true;
Serial.print("Power: ");
Serial.println(p);
boolean r1, r2, r3, r4;
if (p >= 40) {r4 = LOW; p -= 20;} else r4 = HIGH;
if (p >= 20) {r3 = LOW; p -= 20;} else r3 = HIGH;
if (p >= 10) {r2 = LOW; p -= 10;} else r2 = HIGH;
if (p >= 5) {r1 = LOW; p -= 5;} else r1 = HIGH;
digitalWrite(relay1, r1);
digitalWrite(relay2, r2);
digitalWrite(relay3, r3);
digitalWrite(relay4, r4);
Serial.print("Relay 5W: ");
Serial.println(!r1);
Serial.print("Relay 10W: ");
Serial.println(!r2);
Serial.print("Relay 20W: ");
Serial.println(!r3);
Serial.print("Relay 20W: ");
Serial.println(!r4);
}
void init_power(int p) {
int init_delay = 2000;
Serial.print("Init power: ");
Serial.println(p);
boolean r1, r2, r3, r4;
if (p >= 40) {r4 = LOW; p -= 20;} else r4 = HIGH;
if (p >= 20) {r3 = LOW; p -= 20;} else r3 = HIGH;
if (p >= 10) {r2 = LOW; p -= 10;} else r2 = HIGH;
if (p >= 5) {r1 = LOW; p -= 5;} else r1 = HIGH;
boolean light = false;
digitalWrite(relay1, r1);
if (!r1) light = true;
Serial.print("Relay 5W: ");
Serial.println(!r1);
if (light && !r2) delay(init_delay);
digitalWrite(relay2, r2);
if (!r2) light = true;
Serial.print("Relay 10W: ");
Serial.println(!r2);
if (light && !r3) delay(init_delay);
digitalWrite(relay3, r3);
if (!r3) light = true;
Serial.print("Relay 20W: ");
Serial.println(!r3);
if (light && !r4) delay(init_delay);
digitalWrite(relay4, r4);
Serial.print("Relay 20W: ");
Serial.println(!r4);
}
void learn (unsigned long code) {
delay(100);
for (int i=0; i<8; i++) history[i] = history[i+1];
history[8] = code;
if (history[0] == history[3] && history[0] == history[6] &&
history[1] == history[4] && history[1] == history[7] &&
history[2] == history[5] && history[2] == history[8] &&
history[0] != history[1] && history[1] != history[2]) {
Serial.println("Learn mode enabled");
tone(buzzer, 880, 200);
delay(1000);
irrecv.resume();
while (!irrecv.decode(&results));
tone(buzzer, 523, 200);
power_up = results.value;
delay(100);
irrecv.resume();
delay(1000);
while (!irrecv.decode(&results));
tone(buzzer, 440, 200);
power_down = results.value;
delay(100);
irrecv.resume();
EEPROMWritelong(mem_addr+1,power_up);
EEPROMWritelong(mem_addr+5,power_down);
}
}
void setup() {
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
digitalWrite(relay1, HIGH);
digitalWrite(relay2, HIGH);
digitalWrite(relay3, HIGH);
digitalWrite(relay4, HIGH);
pinMode(buzzer, OUTPUT);
tone(buzzer, 659, 500);
Serial.begin(9600);
power = EEPROM.read(mem_addr);
init_power(int(power));
irrecv.enableIRIn();
for (int i=0; i<9; i++) history[i] = i;
power_up = EEPROMReadlong(mem_addr+1);
power_down = EEPROMReadlong(mem_addr+5);
}
void loop() {
if (irrecv.decode(&results)) {
if(results.value == power_up){
if (power < 55) {
tone(buzzer, 523, 200);
power += 5;
set_power(int(power));
}
else {
tone(buzzer, 329, 200);
}
}
if(results.value == power_down){
if (power > 5) {
tone(buzzer, 440, 200);
power -= 5;
set_power(int(power));
}
else {
tone(buzzer, 329, 200);
}
}
learn (results.value);
irrecv.resume();
}
if (not_rec && millis()-timer > 30000) {
tone(buzzer, 262, 100);
EEPROM.write(mem_addr, power);
Serial.println("Save to EEPROM: ");
Serial.println(power);
timer = millis();
not_rec = false;
}
if (millis()-timer > 6*60*60*1000) {
power = 0;
set_power(int(power));
tone(buzzer, 659, 1000);
delay(1000);
tone(buzzer, 440, 1000);
delay(1000);
}
}
Комментариев нет:
Отправить комментарий