├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── examples ├── dimBresMultiTest │ └── dimBresMultiTest.ino ├── dimBresTest │ └── dimBresTest.ino ├── dimFewTestHard │ └── dimMultiTestHard.ino ├── dimFewTestSoft │ └── dimMultiTestSoft.ino ├── dimTestHard │ └── dimTestHard.ino └── dimTestSoft │ └── dimTestSoft.ino ├── keywords.txt ├── library.properties └── src └── GyverDimmer.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![latest](https://img.shields.io/github/v/release/GyverLibs/GyverDimmer.svg?color=brightgreen)](https://github.com/GyverLibs/GyverDimmer/releases/latest/download/GyverDimmer.zip) 2 | [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/GyverDimmer.svg)](https://registry.platformio.org/libraries/gyverlibs/GyverDimmer) 3 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 4 | [![Foo](https://img.shields.io/badge/%E2%82%BD%24%E2%82%AC%20%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%82%D1%8C-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/GyverDimmer?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | [![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs) 8 | 9 | # GyverDimmer 10 | Библиотека для управления симисторным диммером с Arduino 11 | - Одноканальный и многоканальный диммер по алгоритму Брезенхема 12 | - Одноканальный и многоканальный фазовый диммер 13 | 14 | ### Совместимость 15 | Совместима со всеми Arduino платформами (используются Arduino-функции) 16 | 17 | ## Содержание 18 | - [Установка](#install) 19 | - [Инициализация](#init) 20 | - [Использование](#usage) 21 | - [Пример](#example) 22 | - [Версии](#versions) 23 | - [Баги и обратная связь](#feedback) 24 | 25 | 26 | ## Установка 27 | - Библиотеку можно найти по названию **GyverDimmer** и установить через менеджер библиотек в: 28 | - Arduino IDE 29 | - Arduino IDE v2 30 | - PlatformIO 31 | - [Скачать библиотеку](https://github.com/GyverLibs/GyverDimmer/archive/refs/heads/main.zip) .zip архивом для ручной установки: 32 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 33 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 34 | - Распаковать и положить в *Документы/Arduino/libraries/* 35 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 36 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 37 | ### Обновление 38 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи 39 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить" 40 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам! 41 | 42 | 43 | 44 | ## Инициализация 45 | ```cpp 46 | DimmerBres<пин> dim; // диммер по Брезенхему 47 | DimmerBresMulti<количество> dim; // многоканальный диммер по Брезенхему 48 | Dimmer<пин> dim; // фазовый диммер 49 | DimmerMulti<количество> dim; // многоканальный фазовый диммер 50 | ``` 51 | 52 | 53 | ## Использование 54 | ```cpp 55 | // ====== DimmerBres ====== 56 | void write(uint8_t dim); // установить величину диммирования 0-255 57 | void tick(); // вызывать в прерывании детектора нуля 58 | 59 | // ====== DimmerBresMulti ====== 60 | void attach(uint8_t num, uint8_t pin); // подключить канал под номером num на пин pin 61 | void write(uint8_t ch, uint8_t dim); // установить величину диммирования 0-255 на канал ch 62 | void tick(); // вызывать в прерывании детектора нуля 63 | 64 | // ====== Dimmer ====== 65 | void write(uint8_t dim); // установить величину диммирования 0-255 66 | bool tickZero(); // вызывать в прерывании детектора нуля 67 | void tickTimer(); // вызывать в прерывании таймера 68 | int getPeriod(); // получить период для таймера 69 | 70 | // ====== DimmerMulti ====== 71 | void attach(uint8_t num, uint8_t pin); // подключить канал под номером num на пин pin 72 | void write(uint8_t ch, uint8_t dim); // установить величину диммирования 0-255 на канал ch 73 | bool tickZero(); // вызывать в прерывании детектора нуля 74 | void tickTimer(); // вызывать в прерывании таймера 75 | int getPeriod(); // получить период для таймера 76 | ``` 77 | 78 | 79 | ## Пример 80 | Остальные примеры смотри в **examples**! 81 | ```cpp 82 | // тест одного канала по Брезенхему 83 | 84 | #define D_PIN 5 85 | // zero cross на D2 86 | 87 | #include 88 | DimmerBres dim; // указать пин диммера 89 | 90 | void setup() { 91 | // завести прерывание на детектор нуля 92 | attachInterrupt(0, isr, RISING); // D2 == 0 93 | } 94 | 95 | void isr() { 96 | dim.tick(); // вызывать тик в прерывании детектора нуля 97 | } 98 | 99 | void loop() { 100 | // принимает 0-255 101 | dim.write(analogRead(A0) / 4); 102 | delay(100); 103 | } 104 | ``` 105 | 106 | 107 | ## Версии 108 | - v1.0 109 | - v1.1 - переделан FastIO 110 | - v1.1.1 - убран FastIO 111 | - v1.2 - исправил баг в DimmerBres и DimmerBresMulti 112 | 113 | 114 | ## Баги и обратная связь 115 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 116 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 117 | 118 | 119 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать: 120 | - Версия библиотеки 121 | - Какой используется МК 122 | - Версия SDK (для ESP) 123 | - Версия Arduino IDE 124 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде 125 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности 126 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код 127 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # GyverDimmer 4 | Triac dimmer control library with Arduino 5 | - Single and multi-channel Bresenham dimmer 6 | - Single and multi-channel phase dimmer 7 | 8 | ### Compatibility 9 | Compatible with all Arduino platforms (using Arduino functions) 10 | 11 | ## Content 12 | - [Install](#install) 13 | - [Initialization](#init) 14 | - [Usage](#usage) 15 | - [Example](#example) 16 | - [Versions](#versions) 17 | - [Bugs and feedback](#feedback) 18 | 19 | 20 | ## Installation 21 | - The library can be found by the name **GyverDimmer** and installed via the library manager in: 22 | - Arduino IDE 23 | - Arduino IDE v2 24 | - PlatformIO 25 | - [Download library](https://github.com/GyverLibs/GyverDimmer/archive/refs/heads/main.zip) .zip archive for manual installation: 26 | - Unzip and put in *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 27 | - Unzip and put in *C:\Program Files\Arduino\libraries* (Windows x32) 28 | - Unpack and put in *Documents/Arduino/libraries/* 29 | - (Arduino IDE) automatic installation from .zip: *Sketch/Include library/Add .ZIP library…* and specify the downloaded archive 30 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE% D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 31 | 32 | 33 | ## Initialization 34 | ```cpp 35 | DimmerBres dim;// Bresenham dimmer 36 | DimmerBresMulti dim; // Bresenham multi-channel dimmer 37 | Dimmer dim; // phase dimmer 38 | DimmerMulti dim; // multi-channel phase dimmer 39 | ``` 40 | 41 | 42 | ## Usage 43 | ```cpp 44 | // ====== DimmerBres ====== 45 | void write(uint8_t dim); // set dimming amount 0-255 46 | void tick(); // call in zero detector interrupt 47 | 48 | // ====== DimmerBresMulti ====== 49 | void attach(uint8_t num, uint8_t pin); // connect channel number num to pin pin 50 | void write(uint8_t ch, uint8_t dim); // set dimming amount 0-255 per channel ch 51 | void tick(); // call in zero detector interrupt 52 | 53 | // ====== Dimmer ====== 54 | void write(uint8_t dim); // set dimming amount 0-255 55 | bool tickZero(); // call in zero detector interrupt 56 | void tickTimer(); // call in a timer interrupt 57 | int getPeriod(); // get period for timer 58 | 59 | // ====== DimmerMulti ====== 60 | void attach(uint8_t num, uint8_t pin); // connect channel number num to pin pin 61 | void write(uint8_t ch, uint8_t dim); // set dimming amount 0-255 per channel ch 62 | bool tickZero(); // call in zero detector interrupt 63 | void tickTimer(); // call in a timer interrupt 64 | int getPeriod(); // get period for timer 65 | ``` 66 | 67 | 68 | ## Example 69 | See **examples** for other examples! 70 | ```cpp 71 | // test of one channel according to Bresenham 72 | 73 | #define D_PIN 5 74 | // zero cross on D2 75 | 76 | #include 77 | DimmerBres dim; // specify dimmer pin 78 | 79 | void setup() { 80 | // start an interrupt on the zero detector 81 | attachInterrupt(0, isr, RISING); // D2 == 0 82 | } 83 | 84 | void isr() { 85 | dim.tick(); // call tick in null detector interrupt 86 | } 87 | 88 | void loop() { 89 | // takes 0-255 90 | dim.write(analogRead(A0) / 4); 91 | delay(100); 92 | } 93 | ``` 94 | 95 | 96 | ## Versions 97 | - v1.0 98 | - v1.1 - redesigned FastIO 99 | - v1.1.1 - yBran FastIO 100 | - v1.2 - fixed bug in DimmerBres and DimmerBresMulti 101 | 102 | 103 | ## Bugs and feedback 104 | When you find bugs, create an **Issue**, or better, immediately write to the mail [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 105 | The library is open for revision and your **Pull Request**'s! -------------------------------------------------------------------------------- /examples/dimBresMultiTest/dimBresMultiTest.ino: -------------------------------------------------------------------------------- 1 | // тест нескольких диммеров по Брезенхему 2 | // zero cross на D2 3 | 4 | #include 5 | DimmerBresMulti<2> dim; // указать количество диммеров 6 | 7 | void setup() { 8 | // завести общее прерывание на детектор нуля 9 | attachInterrupt(0, isr, RISING); // D2 == 0 10 | 11 | // подключить пины 12 | dim.attach(0, 4); // канал 0, пин 4 13 | dim.attach(1, 5); // канал 1, пин 5 14 | } 15 | 16 | void isr() { 17 | dim.tick(); // вызывать тик в прерывании детектора нуля 18 | } 19 | 20 | void loop() { 21 | byte val = analogRead(A0) / 4; 22 | // врубаем, принимает 0-255 23 | dim.write(0, val); // канал 0 24 | dim.write(1, 255 - val); // канал 1 25 | delay(100); 26 | } 27 | -------------------------------------------------------------------------------- /examples/dimBresTest/dimBresTest.ino: -------------------------------------------------------------------------------- 1 | // тест одного канала по Брезенхему 2 | 3 | #define D_PIN 5 4 | // zero cross на D2 5 | 6 | #include 7 | DimmerBres dim; // указать пин диммера 8 | 9 | void setup() { 10 | // завести прерывание на детектор нуля 11 | attachInterrupt(0, isr, RISING); // D2 == 0 12 | } 13 | 14 | void isr() { 15 | dim.tick(); // вызывать тик в прерывании детектора нуля 16 | } 17 | 18 | void loop() { 19 | // принимает 0-255 20 | dim.write(analogRead(A0) / 4); 21 | delay(100); 22 | } 23 | -------------------------------------------------------------------------------- /examples/dimFewTestHard/dimMultiTestHard.ino: -------------------------------------------------------------------------------- 1 | // тест многоканального диммера 2 | // библиотека универсальная, поэтому требуется свой таймер 3 | // в этом примере делаем на аппаратном таймере 4 | #include // библиотека таймера 5 | 6 | // zero cross на D2 7 | 8 | #include 9 | DimmerMulti<2> dim; // указать количество диммеров 10 | //DimmerMulti<2> dim(60); // можно указать 60 Гц (умолч 50) 11 | 12 | void setup() { 13 | // завести прерывание на детектор нуля 14 | attachInterrupt(0, isr, RISING); // D2 == 0 15 | 16 | // разрешаем прерывания по таймеру 17 | Timer2.enableISR(); 18 | 19 | // настроить таймер на период в мкс (37 us для 50 гц сети) 20 | Timer2.setPeriod(dim.getPeriod()); 21 | 22 | // подключить пины 23 | dim.attach(0, 4); // канал 0, пин 4 24 | dim.attach(1, 5); // канал 1, пин 5 25 | } 26 | 27 | // прерывание детектора нуля 28 | void isr() { 29 | // вызывать в прерывании детектора нуля 30 | dim.tickZero(); 31 | Timer2.restart(); 32 | } 33 | 34 | // прерывание таймера 35 | ISR(TIMER2_A) { 36 | dim.tickTimer(); // вызвать tickTimer() 37 | } 38 | 39 | void loop() { 40 | byte val = analogRead(A0) / 4; 41 | // врубаем, принимает 0-255 42 | dim.write(0, val); // канал 0 43 | dim.write(1, 255 - val); // канал 1 44 | delay(100); 45 | } 46 | -------------------------------------------------------------------------------- /examples/dimFewTestSoft/dimMultiTestSoft.ino: -------------------------------------------------------------------------------- 1 | // тест многоканального диммера 2 | // библиотека универсальная, поэтому требуется свой таймер 3 | // в этом примере делаем на микросе! 4 | 5 | class TimerUs { 6 | public: 7 | bool ready() { 8 | if (state && micros() - tmr >= prd) { 9 | tmr = micros(); 10 | return true; 11 | } 12 | return false; 13 | } 14 | void stop() { 15 | state = false; 16 | } 17 | void restart() { 18 | tmr = micros(); 19 | state = true; 20 | } 21 | void setPeriod(uint32_t period) { 22 | restart(); 23 | prd = period; 24 | if (prd == 0) prd++; 25 | } 26 | 27 | private: 28 | bool state = 0; 29 | uint32_t tmr = 0, prd = 0; 30 | }; 31 | TimerUs timer; 32 | 33 | // zero cross на D2 34 | 35 | #include 36 | DimmerMulti<2> dim; // указать количество диммеров 37 | //DimmerMulti<2> dim(60); // можно указать 60 Гц (умолч 50) 38 | 39 | void setup() { 40 | // завести прерывание на детектор нуля 41 | attachInterrupt(0, isr, RISING); // D2 == 0 42 | 43 | // настроить таймер на период в мкс (37 us для 50 гц сети) 44 | timer.setPeriod(dim.getPeriod()); 45 | 46 | // подключить пины 47 | dim.attach(0, 4); // канал 0, пин 4 48 | dim.attach(1, 5); // канал 1, пин 5 49 | } 50 | 51 | void isr() { 52 | // вызывать в прерывании детектора нуля 53 | dim.tickZero(); 54 | timer.restart(); 55 | } 56 | 57 | void loop() { 58 | byte val = analogRead(A0) / 4; 59 | // врубаем, принимает 0-255 60 | dim.write(0, val); // канал 0 61 | dim.write(1, 255 - val); // канал 1 62 | delay(100); 63 | } 64 | 65 | void yield() { 66 | // в "прерывании" таймера 67 | if (timer.ready()) dim.tickTimer(); // вызвать tickTimer() 68 | } 69 | -------------------------------------------------------------------------------- /examples/dimTestHard/dimTestHard.ino: -------------------------------------------------------------------------------- 1 | // тест одного канала 2 | // библиотека универсальная, поэтому требуется свой таймер 3 | // в этом примере делаем на аппаратном таймере 4 | #include // библиотека таймера 5 | 6 | #define D_PIN 5 7 | // zero cross на D2 8 | 9 | #include 10 | Dimmer dim; // указать пин диммера 11 | //Dimmer dim(60); // можно указать 60 Гц (умолч 50) 12 | 13 | void setup() { 14 | // завести прерывание на детектор нуля 15 | attachInterrupt(0, isr, RISING); // D2 == 0 16 | 17 | // разрешаем прерывания по таймеру 18 | Timer2.enableISR(); 19 | } 20 | 21 | // прерывание детектора нуля 22 | void isr() { 23 | // вызывать в прерывании детектора нуля 24 | // если tickZero() - true - нужно перезапустить таймер с периодом getPeriod() 25 | if (dim.tickZero()) Timer2.setPeriod(dim.getPeriod()); 26 | else Timer2.restart(); 27 | // иначе перезапустить со старым 28 | } 29 | 30 | // прерывание таймера 31 | ISR(TIMER2_A) { 32 | dim.tickTimer(); // вызвать tickTimer() 33 | Timer2.stop(); // останавливаем таймер 34 | } 35 | 36 | void loop() { 37 | dim.write(analogRead(A0) / 4); // принимает 0-255 38 | delay(100); 39 | } 40 | -------------------------------------------------------------------------------- /examples/dimTestSoft/dimTestSoft.ino: -------------------------------------------------------------------------------- 1 | // тест одноканального диммера 2 | // библиотека универсальная, поэтому требуется свой таймер 3 | // в этом примере делаем на микросе! 4 | 5 | class TimerUs { 6 | public: 7 | bool ready() { 8 | if (state && micros() - tmr >= prd) { 9 | tmr = micros(); 10 | return true; 11 | } 12 | return false; 13 | } 14 | void stop() { 15 | state = false; 16 | } 17 | void restart() { 18 | tmr = micros(); 19 | state = true; 20 | } 21 | void setPeriod(uint32_t period) { 22 | restart(); 23 | prd = period; 24 | if (prd == 0) prd++; 25 | } 26 | 27 | private: 28 | bool state = 0; 29 | uint32_t tmr = 0, prd = 0; 30 | }; 31 | TimerUs timer; 32 | 33 | // zero cross на D2 34 | 35 | #include 36 | Dimmer dim; // указать пин диммера 37 | //Dimmer dim(60); // можно указать 60 Гц (умолч 50) 38 | 39 | void setup() { 40 | // завести прерывание на детектор нуля 41 | attachInterrupt(0, isr, RISING); // D2 == 0 42 | } 43 | 44 | void isr() { 45 | // вызывать в прерывании детектора нуля 46 | // если tickZero() - true - нужно перезапустить таймер с периодом getPeriod() 47 | if (dim.tickZero()) timer.setPeriod(dim.getPeriod()); 48 | else timer.restart(); 49 | // иначе перезапустить со старым 50 | } 51 | 52 | void loop() { 53 | // в "прерывании" таймера 54 | if (timer.ready()) { 55 | dim.tickTimer(); // вызвать tickTimer() 56 | timer.stop(); // остановить таймер 57 | } 58 | dim.write(analogRead(A0) / 4); // принимает 0-255 59 | } 60 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For GyverDimmer 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | GyverDimmer KEYWORD1 10 | DimmerBres KEYWORD1 11 | DimmerBresMulti KEYWORD1 12 | Dimmer KEYWORD1 13 | DimmerMulti KEYWORD1 14 | 15 | ####################################### 16 | # Methods and Functions (KEYWORD2) 17 | ####################################### 18 | 19 | attach KEYWORD2 20 | write KEYWORD2 21 | tickZero KEYWORD2 22 | tickTimer KEYWORD2 23 | tick KEYWORD2 24 | getPeriod KEYWORD2 25 | 26 | ####################################### 27 | # Constants (LITERAL1) 28 | ####################################### 29 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=GyverDimmer 2 | version=1.2.1 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Phase and Bresenham algorithm for AC triac dimmer 6 | paragraph=Phase and Bresenham algorithm for AC triac dimmer 7 | category=Device Control 8 | url=https://github.com/GyverLibs/GyverDimmer 9 | architectures=* 10 | depends=GyverIO -------------------------------------------------------------------------------- /src/GyverDimmer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Библиотека для управления симисторным диммером с Arduino 3 | Документация: 4 | GitHub: https://github.com/GyverLibs/GyverDimmer 5 | Возможности: 6 | - Одноканальный и многоканальный диммер по алгоритму Брезенхема 7 | - Одноканальный и многоканальный фазовый диммер 8 | 9 | AlexGyver, alex@alexgyver.ru 10 | https://alexgyver.ru/ 11 | MIT License 12 | 13 | Версии: 14 | v1.0 - релиз 15 | v1.1 - переделан FastIO 16 | v1.1.1 - убран FastIO 17 | v1.2 - исправил баг в DimmerBres и DimmerBresMulti 18 | */ 19 | 20 | #ifndef GyverDimmer_h 21 | #define GyverDimmer_h 22 | #include 23 | #include 24 | 25 | // брезенхем одноканальный 26 | template 27 | class DimmerBres { 28 | public: 29 | DimmerBres() { 30 | gio::init(_D_PIN, OUTPUT); 31 | gio::write(_D_PIN, LOW); 32 | } 33 | 34 | void write(uint8_t dim) { 35 | dimmer = dim; 36 | } 37 | 38 | void tick() { 39 | uint16_t val = ((uint16_t)++count * dimmer) >> 8; 40 | if (lastVal != (val != last)) gio::write(_D_PIN, val != last); 41 | lastVal = (val != last); 42 | last = val; 43 | } 44 | 45 | private: 46 | uint8_t count = 0, last = 0, lastVal = 0, dimmer = 0; 47 | }; 48 | 49 | // брезенхем многоканальный 50 | template 51 | class DimmerBresMulti { 52 | public: 53 | void attach(uint8_t num, uint8_t pin) { 54 | dimPins[num] = pin; 55 | gio::init(pin, OUTPUT); 56 | } 57 | 58 | void write(uint8_t ch, uint8_t dim) { 59 | dimmer[ch] = dim; 60 | } 61 | 62 | void tick() { 63 | count++; 64 | for (uint8_t i = 0; i < _D_AMOUNT; i++) { 65 | uint16_t val = ((uint16_t)count * dimmer[i]) >> 8; 66 | if (lastState[i] != (val != last[i])) gio::write(dimPins[i], val != last[i]); 67 | lastState[i] = (val != last[i]); 68 | last[i] = val; 69 | } 70 | } 71 | 72 | private: 73 | uint8_t count, last[_D_AMOUNT], lastState[_D_AMOUNT], dimmer[_D_AMOUNT], dimPins[_D_AMOUNT]; 74 | }; 75 | 76 | // плавный диммер одноканальный 77 | template 78 | class Dimmer { 79 | public: 80 | Dimmer(uint8_t freq = 50) { 81 | gio::init(_D_PIN, OUTPUT); 82 | gio::write(_D_PIN, LOW); 83 | maxVal = (freq == 50) ? 9300 : 7600; 84 | } 85 | 86 | void write(uint8_t dim) { 87 | dimmer = map(dim, 0, 255, maxVal, 500); 88 | } 89 | 90 | bool tickZero() { 91 | gio::write(_D_PIN, LOW); 92 | if (lastDim != dimmer) { 93 | lastDim = dimmer; 94 | return true; 95 | } 96 | return false; 97 | } 98 | 99 | void tickTimer() { 100 | gio::write(_D_PIN, HIGH); 101 | } 102 | 103 | uint16_t getPeriod() { 104 | return dimmer; 105 | } 106 | 107 | private: 108 | uint16_t dimmer = 0, lastDim = 0, maxVal = 0; 109 | }; 110 | 111 | // плавный диммер многоканальный 112 | template 113 | class DimmerMulti { 114 | public: 115 | DimmerMulti(uint8_t freq = 50) { 116 | maxVal = (freq == 50) ? 9300 : 7600; 117 | } 118 | 119 | void attach(uint8_t num, uint8_t pin) { 120 | gio::init(pin, OUTPUT); 121 | dimPins[num] = pin; 122 | } 123 | 124 | void write(uint8_t ch, uint8_t dim) { 125 | dimmer[ch] = dim; 126 | } 127 | 128 | void tickZero() { 129 | counter = 255; 130 | } 131 | 132 | void tickTimer() { 133 | for (uint8_t i = 0; i < _D_AMOUNT; i++) { 134 | if (counter == dimmer[i]) gio::write(dimPins[i], 1); // на текущем тике включаем 135 | else if (counter == dimmer[i] - 1) gio::write(dimPins[i], 0); // на следующем выключаем 136 | } 137 | counter--; 138 | } 139 | 140 | uint16_t getPeriod() { 141 | return (maxVal == 9300) ? 37 : 31; // us 142 | } 143 | 144 | private: 145 | uint8_t dimmer[_D_AMOUNT], dimPins[_D_AMOUNT]; 146 | uint16_t maxVal = 0; 147 | volatile uint16_t counter = 0; 148 | }; 149 | 150 | #endif 151 | --------------------------------------------------------------------------------