Делюсь кодом. Накатал програмку диммера на ARDUINO. Буду делать выключатели света в квартиру. Осталось приляпать управляющий блок на семисторе. Потом можно и к WiFi подключить. Логика такая: один раз нажал - плавное включение, второй нажал плавное выключение, долго держишь - плавное нарастание яркости до нужной или максимальной, после нажал - плавное выключение с текущей яркости. Нелинейное изменение яркости - логарифмическое, для глаз приятное. Используется библиотека OneButton http://www.mathertel.de/Arduino/OneButtonLibrary.aspx Код (C++): #include "OneButton.h" const int buttonPin = 1; const int ledPin = 9; const byte loga[64] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 22, 25, 28, 29, 30, 33, 36, 39, 42, 46, 49, 53, 56, 60, 64, 68, 72, 77, 81, 86, 90, 95, 100, 105, 110, 116, 121, 127, 132, 138, 144, 150, 156, 163, 169, 176, 182, 189, 196, 203, 210, 218, 225, 233, 240, 248, 255 }; int i = 1; OneButton button(buttonPin, false); int ledState = LOW; int ledLevel = 0; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); button.attachClick(clickedIt); button.attachDuringLongPress(duringLongPressIt); } void loop() { button.tick(); } void clickedIt() { if (ledState == LOW) { for (int i = 0; i < 63; i++) { analogWrite(ledPin, loga[i]); delay(10); } ledState = !ledState; } else { if (ledLevel > 0 ) { for (int i = ledLevel; i >= 0; i--) { analogWrite(ledPin, loga[i]); delay(10); } } else { for (int i = 63; i >= 0; i--) { analogWrite(ledPin, loga[i]); delay(10); } } ledState = !ledState; ledLevel = 0; } } void duringLongPressIt() { analogWrite(ledPin, loga[ledLevel]); ledLevel = ledLevel + 1; if (ledLevel >= 63) { ledLevel = 63; } delay(50); ledState = HIGH; }
Вычисленные значения от 0 до 255 плавного (нелинейного) увеличения яркости. Можно конечно функцию сообразить, вычислять, округлять и приводить к 64 шагам. Но так проще.
А свет в квартире собран на светодиодах? На семисторе загораться будет совсем иначе, если скетч останется тот же. И если на обычных "энергосберегайках" люменисцентных, то совсем не получится плавное включение.
Поправлен алгоритм. Первое включение - максимальная яркость. Последующие включения восстанавливают выбранную яркость. Длинное нажатие - выбор яркости с нуля. Код (C++): #include "OneButton.h" const int buttonPin = 1; const int ledPin = 9; const byte loga[64] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 22, 25, 28, 29, 30, 33, 36, 39, 42, 46, 49, 53, 56, 60, 64, 68, 72, 77, 81, 86, 90, 95, 100, 105, 110, 116, 121, 127, 132, 138, 144, 150, 156, 163, 169, 176, 182, 189, 196, 203, 210, 218, 225, 233, 240, 248, 255 }; int i; OneButton button(buttonPin, false); int ledState = LOW; int ledLevel = 0; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); button.attachClick(clickedIt); button.attachDuringLongPress(duringLongPressIt); } void loop() { button.tick(); } void clickedIt() { if (ledState == LOW) { if (ledLevel > 0 ) { for ( i = 0; i <= ledLevel; i++) { analogWrite(ledPin, loga[i]); delay(10); } } else { for ( i = 0; i <= 63; i++) { analogWrite(ledPin, loga[i]); delay(10); } } ledState = !ledState; } else { if (ledLevel > 0 ) { for ( i = ledLevel; i >= 0; i--) { analogWrite(ledPin, loga[i]); delay(10); } } else { for ( i = 63; i >= 0; i--) { analogWrite(ledPin, loga[i]); delay(10); } } ledState = !ledState; } } void duringLongPressIt() { if (ledState == LOW) { ledLevel = 0; } analogWrite(ledPin, loga[ledLevel]); ledLevel = ledLevel + 1; if (ledLevel >= 63) { ledLevel = 63; } delay(50); ledState = HIGH; }
У Вас не получится управлять симистором при помощи ШИМа, т. к. частота сети (220В) в разы ниже чем частота на ШИМ выходе. Симистор открыть то Вы его откроете, а вот закроется он только когда сетевое напряжение будет проходить через 0.
Электрическая схема будет такая: http://arduino.ru/forum/apparatnye-voprosy/ustroistvo-fiu-na-simistore-dimmer-dlya-arduino . Нужен только ШИМ с ARDUINO. Можно собрать схему на MOC3043 (MOC30*3) и семисторе в них детектор прохождения через ноль.
Скажите, что определяет параметр true/false в кострукторе? Код (C++): OneButton button(buttonPin, false);
В качестве расширения функционала можно добавить: Кратковременное нажатие кнопки при включенном свете приведёт к плавному уменьшению мощности до полного отключения. Во время этого, нажатие на кнопку приведет к фиксации уровня мощности, тем самым реализована функция уменьшения. Скорость выключения при этом придётся замедлить. Двойное (кратковременное) нажатие на кнопку при включенном освещении: активирует задержку отключения на определённое время (мигающий светодиод подсветки). Которое может быть сброшено, еще одним нажатием, свет выключатся. Очень удобно когда спать ложишься, не нужно ломится в темноте. Я такую штучку на ATtiny13 собирал.