Однокнопочный диммер на ARDUINO

Тема в разделе "Глядите, что я сделал", создана пользователем andrus_p, 12 июн 2016.

  1. andrus_p

    andrus_p Нуб

    Делюсь кодом.

    Накатал програмку диммера на 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;
    }
     
     
  2. Максимус-Бог

    Максимус-Бог Убийца матрёшек

    зачем массив Loga?
     
  3. andrus_p

    andrus_p Нуб

    Вычисленные значения от 0 до 255 плавного (нелинейного) увеличения яркости. Можно конечно функцию сообразить, вычислять, округлять и приводить к 64 шагам. Но так проще.
     
    Последнее редактирование: 13 июн 2016
  4. 9xA59kK

    9xA59kK Гик

    А свет в квартире собран на светодиодах? На семисторе загораться будет совсем иначе, если скетч останется тот же. И если на обычных "энергосберегайках" люменисцентных, то совсем не получится плавное включение.
     
  5. andrus_p

    andrus_p Нуб

    Поправлен алгоритм. Первое включение - максимальная яркость. Последующие включения восстанавливают выбранную яркость. Длинное нажатие - выбор яркости с нуля.
    Код (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;
    }
     
     
  6. yul-i-an

    yul-i-an Гик

    У Вас не получится управлять симистором при помощи ШИМа, т. к. частота сети (220В) в разы ниже чем частота на ШИМ выходе. Симистор открыть то Вы его откроете, а вот закроется он только когда сетевое напряжение будет проходить через 0.
     
  7. andrus_p

    andrus_p Нуб

    Последнее редактирование: 14 июн 2016
  8. yul-i-an

    yul-i-an Гик

    Дерзайте, удачи.
     
  9. TRUbuilder

    TRUbuilder Нуб

    Я в этом деле новичок. У меня светодиод тупа горит и не гаснет. Не могли бы вы выложить схему.
     
  10. Karabas

    Karabas Гик

    Скажите, что определяет параметр true/false в кострукторе?
    Код (C++):
    OneButton button(buttonPin, false);
     
  11. VITAL_P

    VITAL_P Нерд

    В качестве расширения функционала можно добавить:
    Кратковременное нажатие кнопки при включенном свете приведёт к плавному уменьшению мощности до полного отключения.
    Во время этого, нажатие на кнопку приведет к фиксации уровня мощности, тем самым реализована функция уменьшения. Скорость выключения при этом придётся замедлить.
    Двойное (кратковременное) нажатие на кнопку при включенном освещении:
    активирует задержку отключения на определённое время (мигающий светодиод подсветки). Которое может быть сброшено, еще одним нажатием, свет выключатся. Очень удобно когда спать ложишься, не нужно ломится в темноте.
    Я такую штучку на ATtiny13 собирал.
     
  12. Arkad_snz

    Arkad_snz Гик

    Я так понял, это протабулированный логарифм, и сразу нормированный под приемлемый диапазон значений.
     
  13. Arkad_snz

    Arkad_snz Гик

    Кто такой "button"? Нигде не определен, и не инициализирован.
     
  14. rkit

    rkit Гуру

    По ссылке какой-то кошмар на советской элементной базе. Погуглите еще, есть схемы попроще.