Умный светильник для «богатых» своими «ленивыми» руками, это же «просто» и удобно
Введение
Сделал на кухне «современную» подсветку для мойки, плиты и разделочного столика на базе светодиодной ленты под управлением ардуино (пусть называется светильник 1). Эта конструкция проработала 2 года, пока силовая часть «мозгов» не испортилась. Это отличный повод снова изобрести велосипед из «подручного хлама» (светильник 2). Правда в этот раз «хлам» будет дорогим и совместимым с умным домом Z-wave. Далее рассказ о замене ардуино на ZUNo (ардуино совместимый модуль для создания Z-wave устройства) c максимальным сохранением кода и пояснением необходимых изменений.
Что было до моего появления там
Давным-давно, чтобы помыть посуду или приготовить пищу нужно было включить светильник над мойкой. Это была переделанная настольная лампа.
Мне не нравилось нажимать маленький выключатель мокрыми руками, потому что он коммутировал 220 вольт на лампу накаливания.
Также свет от лампы падал преимущественно на мойку, а хотелось лучше освещать стол для готовки и плиту.
Цели:
— Сделать включение/выключение света на кухне бесконтактным;
— Равномерно освещать мойку, стол для готовки и плиту;
— Экономить электроэнергию, за счёт замены лампы накаливания на светодиоды.
Собрал светильник 1. Он состоял из 2-х метрового алюминиевого короба с рассеивателем для RGB ленты и блока управления. Короб и рассеиватель купил готовые в магазине, лента была, а блок управления давно лежал в углу и ждал своего часа.
Корпус взял промышленный (пыле, влагозащищённый). Поскольку лента на 12 вольт, то в блоке разместился блок питания с 220 В на 12 В, плата гальванической развязки для управления лентой на базе TLP250 (оптопара) и управляла всем этим ардуино в компактном исполнении.
Плата гальванической развязки у меня осталась от старого проекта. Когда-то делал подсветку для минибара у себя в тумбочке. При открывании двери сенсорная площадка фиксировала изменение ёмкости и включала мягко переливающийся свет. То есть, плата хорошо подходила для текущего проекта, оставалось только обрезать всё лишнее. На плате стоял линейный преобразователь на 5 вольт, с него запитал ZUNo.
Включать светильник планировалось подносом руки к ультразвуковому измерителю расстояния. Его вмонтировал в крышку, а в коробку влезли все остальные части. Всё «надёжно» закрепил термоклеем. На время тестирования сделал рядом кнопку подачи питания в блок управления из выключателя света для внешнего монтажа.
Включать свет стало удобнее и безопаснее. Он крепился вверх «ногами» к дну кухонного шкафчика и воде с мокрых рук попасть внутрь было тяжелее.
Выводы по предыдущему блоку управления
Освещение рабочей зоны кухни стало равномернее и приятнее, из-за неестественной цветопередачи моей светодиодной ленты у некоторых продуктов менялся цвет. Например: морковка казалась гораздо аппетитнее из-за более яркой окраски. Но сильно это не мешало и большого вреда, буду надеяться, не нанесло.
С бесконтактным включением/отключением всё оказалось хуже. Оно работало. Но после 5 минут в отключенном состоянии начинались всполохи на светодиодной ленте. Переделывать схему на оптопарах не стал и оставил всё как есть. Только для включения и выключения стали пользоваться новым выключателем. Его местоположение и форма всем понравились.
За два года использования на корпусе и внутри него скопился жир и прочие соединения выделяемые во время приготовления пищи. Данный налёт частично проник и в корпус через отверстия для ввода проводов. Но из-за глянцевой поверхности корпуса это вещество сконденсировалось в желатиноподобную массу. На ощупь приятную, без запаха и… (на вкус пробовать не стал). Сделал несколько фотографий пятна в виде зародыша дракона.
На стенах же данное вещество превращается в ужасный налёт, который не просто отмывается.
Что стало
Порывшись в закромах нашёл недоделанный модуль расширения для ZUNo. ZUNo — это ардуино подобная плата для конструирования собственного устройства, совместимого с умным домом Z-Wave. Программируется из среды ардуино.
- 28 kB Flash memory for your sketches
- 2 kB RAM available
- Z-Wave RF transmitter at 9.6/40/100 kbps
- 26 GPIO (overlaps with special hardware controllers)
- 4 ADC
- 5 PWM
- 2 UART
- 1 USB (serial port)
- 16 kB EEPROM
- 1 SPI (master or slave)
- 4 IR controllers, 1 IR learn capability
- 1 TRIAC/ZEROX to control dimmer
- 3 Interrupts
- 1 Timer 4 MHz
- I2C (software)
- 1-Wire (software)
- 8×6 Keypad Scanner (software)
- 2 service LED, 1 service button
- 1 user test LED
Модуль расширения делает из ZUNo полноценную отладочную плату, которую после отладки прототипа можно использовать как законченное устройство.
- One 0–10 V analog output — control industrial dimmers
- Up to four PWM or switch outputs (up to 5 A per channel) — control contactors, switches, halogen bulbs or LED strips
- Up to eight digital 0/3 V inputs or outputs — connect various low voltage digital senors and actors
- Up to four digital 0/3, 0/5 or 0/12 V digital or analog inputs — connect industrial 10 V sensors or any Arduino-compatible sensor
- RS485 or UART — for industial meters
- OneWire — for DS18B20 or other sensors
Для своего проекта мне нужно 3 мощных транзистора для коммутации 12 вольт на светодиодную ленту и преобразователь с 12 вольт на 5 вольт, для питания ZUNo. Остальная периферия модуля расширения не напаяна или не протестирована.
В этой части схемы не хватает диода на питание, для защиты от «переполюсовки» и резисторы на затворах силовых полевых транзисторов надо было подключать на затвор, а не перед ограничивающим резистором. Об этом ещё напишу в выводах.
Поставляется данный модуль расширения в корпусе от Gainta. Мой предыдущий блок управления тоже был в корпусе от этой фирмы, но другого размера. К сожалению крепления на модуле не подошли к старому корпусу, а сверлить новый не хотелось, оставил старый корпус. Плату «посадил» на термоклей.
Немного о программировании Arduino и ZUNo
Z-wave устройства обязательно имеют некоторое количество классов. Классы описывают функции устройства и интерфейс взаимодействия. Например, мой светильник управляет светодиодной лентой, состоящей из трёх цветов (красный, зелёный, голубой). Эти функции выполняет класс Switch multilevel. Если мы добавим его в скетч, то сможем удалённо менять яркость одного из цветов. Чтобы управлять тремя цветами, нужно сделать три экземпляра этого класса. Более подробно и детально говорить об этом не буду. Потому что рутинные манипуляции с классами скрыты для пользователей ZUNo понятием «канал». Например, мне нужны три класса Switch multilevel, значит в коде должно появиться 3 канала Switch multilevel и несколько функций callback’ов для управления по радио. Как же это сделать? Ещё нужно добавить класс Switch basic, чтобы включать и выключать светильник по нажатию одной кнопки (из интерфейса контроллера сети), а не настраивать 3 канала каждый раз.
Нужно зайти на сайт разработчиков, где выложены примеры z-uno.z-wave.me/Reference/ZUNO_SWITCH_MULTILEVEL. К каждому классу, поддерживаемому ZUNo есть описание и пример. Далее копируем и вставляем в свой скетч предлагаемые функции. Теперь в скетче есть три канала switch multilevel и 6 функций callback для реакции на команды по радио. Я не сильно искушён в классах Z-Wave, поэтому моё предыдущее устройство со светодиодной лентой работало с этим набором классов.
Объявлялись каналы так:
ZUNO_SETUP_CHANNELS(
ZUNO_SWITCH_MULTILEVEL(getRed, setRed),
ZUNO_SWITCH_MULTILEVEL(getGreen, setGreen),
ZUNO_SWITCH_MULTILEVEL(getBlue, setBlue),
ZUNO_SWITCH_BINARY(switch_getter, switch_setter)
);
Это приводило к генерации следующих виджетов в контроллере после добавления в сеть:
Для настройки цвета приходилось в меню контроллера открывать и настраивать каждый цвет отдельно. Это не удобно и медленно. Однако, мне повезло. оказалось я не одинок. О нас подумали и сделали канал z-uno.z-wave.me/Reference/ZUNO_SWITCH_COLOR. Теперь в скетче только один канал и две callback функции. В меню контроллера настройка цветов выполняется как отдельно по каждому цвету, так сразу всех, путём выбора из палитры.
ZUNO_SETUP_CHANNELS(ZUNO_SWITCH_COLOR(SWITCH_COLOR_FLAGS_RED|SWITCH_COLOR_FLAGS_GREEN|SWITCH_COLOR_FLAGS_BLUE, getterFunction, setterFunction));
А в меню контроллера это выглядит так:
Следующая функция отвечает на запросы по радио. Придти может запрос на чтение состояние одного из каналов цветов.
BYTE getterFunction(BYTE component) {
switch(component)
{
case SWITCH_COLOR_COMPONENT_RED:
return pwmR;
break;
case SWITCH_COLOR_COMPONENT_GREEN:
return pwmG;
break;
case SWITCH_COLOR_COMPONENT_BLUE:
return pwmB;
break;
}
return 3;
}
А это функция для задания цвета из интерфейса контроллера.
void setterFunction(BYTE component, BYTE newValue)
{
switch(component)
{
case SWITCH_COLOR_COMPONENT_RED:
pwmR = newValue;
break;
case SWITCH_COLOR_COMPONENT_GREEN:
pwmG = newValue;
break;
case SWITCH_COLOR_COMPONENT_BLUE:
pwmB = newValue;
break;
}
radio_action = 1;
}
Вот и весь код, который нужно добавить, чтобы превратить скетч arduino в скетч для ZUNo.
Заключение
После сборки и установки все заявленные задачи были выполнены. Однако, привычка включать свет выключателем осталась (очень уж удобно получилось). Бесконтактный выриант включения тоже работает. Из недостатков хочу отметить мерцание светодиодной лампы в течение секунды после подачи питания на блок управления. Это вызвано долгой инициализацией периферии ZUNo. В этот момент на ножках непредсказуемое состояние. Думаю подтягивающий резистор на затворе транзистора исправит ситуацию если его поставить после ограничивающего резистора. Если же код инициализации настраивает ножки на выход и меняет логические уровни целенаправленно, можно поэкспериментировать с RC-фильтром, который не будет пропускать короткие импульсы. Пока не делал, и возможно, не сделаю никогда!
Выводы
ZUNo и модуль расширения к ней сильно упрощают «домашнее техническое творчество». Однако, считаю эти продукты очень дорогими и если бы я работал в другом месте и вокруг меня не валялось бы «недоиспорченное» оборудование Z-Wave, то делал бы всё на ESP8266. Во время разработки узнал новый «стандарт» маркировки проводов от блока питания.
Теперь чёрной полосой помечается не только земля, но как и в моём случае «положительный» провод. Для модуля расширения это оказалось важно. Вышел из строя преобразователь на 5 вольт LM2594 (Цена в Чип и Дип около 200 рублей). Надеюсь, в следующей версии модуля расширения будет стоять защитный диод от «переполюсовки». А я буду проверять полярности питающих проводов. Ещё недостаток связан с корпусом. Корпус выглядит хорошо, но подключить провода без пинцета к клеммникам у меня не получилось. Надеюсь, что будет версия с другими клеммниками (для подключения проводов сверху, или под углом).
Я не люблю хранить фотографии на облачных сервисах и часто делать резервные копии. Поэтому большая часть фотографий связанная с процессом конструирования и светильника 1 безвозвратно испорчены.
Это всё, что осталось от процесса сборки и отладки.
А так выглядит пущенная в эксплуатацию подсветка, если немного пригнуться. Если выпрямиться, то коробку и выключатель не видно.
#include "EEPROM.h"
#include "EEPR.h"
int readPin = 9;
int triggerPin = 10;
byte controlState = 0;
word lastValue;
#define REDPIN PWM1 // pin connection R
#define GREENPIN PWM2 // pin connection G
#define BLUEPIN PWM3 // pin connection B
ZUNO_SETUP_CHANNELS(ZUNO_SWITCH_COLOR(SWITCH_COLOR_FLAGS_RED|SWITCH_COLOR_FLAGS_GREEN|SWITCH_COLOR_FLAGS_BLUE, getterFunction, setterFunction));
#define ON 1
#define OFF 0
uint8_t switch_=OFF;
uint8_t pwmR=0;
uint8_t pwmG=0;
uint8_t pwmB=0;
uint8_t b_pwmR=0;
uint8_t b_pwmG=0;
uint8_t b_pwmB=0;
enum
{
DEF_R = 255,
DEF_G = 255,
DEF_B = 255
};
uint8_t radio_action = 0;
void setup()
{
init_EEPROM();
Serial.begin();
pinMode(readPin, INPUT);
pinMode(triggerPin, OUTPUT);
digitalWrite(triggerPin, LOW);
pinMode(REDPIN, OUTPUT);
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
analogWrite(REDPIN, pwmR & 0xff);
analogWrite(GREENPIN, pwmG & 0xff);
analogWrite(BLUEPIN, pwmB & 0xff);
}
int act=1;
int actf = 0;
int cnt=57;
void loop()
{
int tmp;
// trigger measurement
digitalWrite(triggerPin, LOW);
delayMicroseconds(10);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// read pulse width
tmp = pulseIn(readPin, HIGH, 100000);
lastValue = tmp / 58;
Serial.print(" cm= ");
Serial.println(lastValue);
if (lastValue < 30)
{
cnt++;
}
else
{
cnt--;
}
if (cnt > 55)
{
act=1;
}
if (cnt > 60)
cnt= 60;
if (cnt < 50)
{
act=0;
actf=0;
}
if (cnt < 45 )
cnt = 45;
if ((act == 1) && (actf == 0))
{
actf = 1;
if (switch_ == OFF)
{
switch_=ON;
b_pwmG = pwmG;
b_pwmB = pwmB;
b_pwmR = pwmR;
}
else
{
switch_=OFF;
b_pwmR=0;
b_pwmG=0;
b_pwmB=0;
}
analogWrite(REDPIN, b_pwmR & 0xff);
analogWrite(GREENPIN, b_pwmG & 0xff);
analogWrite(BLUEPIN, b_pwmB & 0xff);
}
Serial.print("cnt = ");
Serial.print(cnt);
Serial.print(" || ");
Serial.print(pwmR);
Serial.print(" ");
Serial.print(pwmG);
Serial.print(" ");
Serial.print(pwmB);
Serial.print(" ");
Serial.println("");
// delay(10);
if(radio_action)
{
radio_action = 0;
eepr_save_col();
analogWrite(REDPIN, pwmR & 0xff);
analogWrite(GREENPIN, pwmG & 0xff);
analogWrite(BLUEPIN, pwmB & 0xff);
}
}
BYTE getterFunction(BYTE component) {
switch(component)
{
case SWITCH_COLOR_COMPONENT_RED:
return pwmR;
break;
case SWITCH_COLOR_COMPONENT_GREEN:
return pwmG;
break;
case SWITCH_COLOR_COMPONENT_BLUE:
return pwmB;
break;
}
return 3;
}
void setterFunction(BYTE component, BYTE newValue)
{
switch(component)
{
case SWITCH_COLOR_COMPONENT_RED:
pwmR = newValue;
break;
case SWITCH_COLOR_COMPONENT_GREEN:
pwmG = newValue;
break;
case SWITCH_COLOR_COMPONENT_BLUE:
pwmB = newValue;
break;
}
radio_action = 1;
}