CO2 зависимая вентиляция

Тема в разделе "Arduino & Shields", создана пользователем Towardstohumanity, 19 авг 2018.

  1. Добрый вечер,
    Помогите, пожалуйста, проверить корректность кода.
    Решил сделать автоматическую вентиляцию в квартире. Система должна раз в 10 минут измерять концентрацию СО2 в воздухе и включать вентилятор со скоростью пропроциональной концентрации СО2 на 10 минут до следующего замера уровня углекислого газа. Также в системе управления предусмотрен ручной режим управления (сенсорная кнопка тройка-модуль) при включении которой вентиллятор запускается на максимальную мощность.
    Для реализации управления скоростью вентилятора взял пример кода для диммера переменного тока от https://github.com/AlexGyver/AC_Dimmer. Пример управления сенсором СО2 на сайте Амперка.
    У меня остались сомнения, будет ли система нормально работать если в диммере используются аппаратные прерывания.
    Выкладываю схему и код. Буду очень благодарен за советы.
    Код (C++):
    /*
       Проект CO2 Dependent Ventillation предополагает включение принудительной виентиляции в случае превышения допустимого уровня
       концентрации СО2 в помещении. Для эффективного проветривания необходимо предусмотреть источник свежего воздуха - причтоную
       часть вентиляции, например оконный клапан. Проект выполнен с использованием примеров со следующих сайтов:
       https://raw.githubusercontent.com/amperka/TroykaMQ/master/examples/mq135/mq135Heater/mq135Heater.ino
       https://raw.githubusercontent.com/AlexGyver/AC_Dimmer/master/Sketches/dimmer_timer/dimmer_timer.ino
       Дополнительную информацию сайтах: https://alexgyver.ru/ и http://amperka.ru/
       Описание функционала.
       Система имеет канальный вентилятор установленный в воздуховод помещения и вентиляционную решетку через которую происходит
       выведение загрязненногом воздуха. Ардуино уно/нано обеспечивает контроль концентрации в воздухе СО2 один раз в 10 минут и
       в зависимости от состояния включает вентилятор на масштабированную в зависимости от концентрации СО2 скорость на 10 минут
       до следующего измерения. Сенсорная кнопка позволяет осуществить её скрытый/малозаметный монтаж в помещении и предназначена
       для включения системы в принудительном режиме на максимальной скорости. Поскольку предполагается, что желание отказаться от
       автоматической регулировки вызвано наличием неприятных примесей в воздухе и необходимостью их скорейшего удаления.
     
       Информация о компонентах приведена в файле ReadMe
    */


    #define dimPin 4
    #define zeroPin 2
    #include <CyberLib.h> // шустрая библиотека для таймера
    volatile int tic, Dimmer;

    // ----------------установки для сенсора-----------------------
    // библиотека для работы с датчиками MQ (Troyka-модуль)
    #include <TroykaMQ.h>

    // имя для пина, к которому подключен датчик
    #define PIN_MQ135         A0
    // имя для пина, к которому подключен нагреватель датчика
    #define PIN_MQ135_HEATER  11

    // создаём объект для работы с датчиком
    // и передаём ему номер пина выходного сигнала и нагревателя
    MQ135 mq135(PIN_MQ135, PIN_MQ135_HEATER);

    //-------------------установки для вентилятора------------------------
    long previousMillis = 0;        // храним время последнего включения вентиллятора
    long interval = 600000;         // интервал между включением/выключением вентилятора
    int fanSpeed = 0;               // создаем переменную для контроля скорости вентилятора
    #define VENT_POWER_PIN 8        // определяем пин для управлением питания вентилятора
    #define MANUAL_MANAGE_PIN 7     // определяем пин контроля ручного режима

    void setup() {
      // ----------------настройки для диммера-------------------------------
      Serial.begin(9600);
      pinMode(dimPin, OUTPUT);
      digitalWrite(dimPin, 0);
      pinMode(zeroPin, INPUT);                 // настраиваем порт на вход для отслеживания прохождения сигнала через ноль
      attachInterrupt(0, detect_up, FALLING);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень

      StartTimer1(timer_interrupt, 40);        // время для одного разряда ШИМ
      StopTimer1();                            // остановить таймер

      Serial.println("Start");
     
      //--------------настройки для вентилятора-----------------------------------
      pinMode(VENT_POWER_PIN, OUTPUT); // устанавливаем пин управления питанием вентилятора как выход
      pinMode(MANUAL_MANAGE_PIN, INPUT); // устанавливаем пин управления ручным режимом как вход
    }

    void loop() {
    //-----------------цикл для диммера--------------------------------

     
      // выставляем зависиомсть скорости вентиллятора от концентрации СО2
      Dimmer = map(fanSpeed, 350, 1000, 250, 0);
     
      // определяем режим работы вентилятора
      if (MANUAL_MANAGE_PIN == LOW && mq135.readCO2() <= 350) { // выключаем вентилятор если концентрации СО2 ниже 350 ppm
       digitalWrite(VENT_POWER_PIN, LOW);
      }
      if (MANUAL_MANAGE_PIN == LOW && mq135.readCO2() > 350) { // устанавливаем скорость работы вентилятора в зависимости от концентрации СО2
       digitalWrite(VENT_POWER_PIN, HIGH);
      }
      if (MANUAL_MANAGE_PIN !=LOW) { // устанавливаем ручной режим работы вентилятора на максимальной скорости
        digitalWrite(VENT_POWER_PIN, HIGH);
        fanSpeed = 1000;
      }
    //----------------цикл для сенсора---------------------------------
      unsigned long currentMillis = millis();
     
      //проверяем не прошел ли нужный интервал, если прошел то
      if(currentMillis - previousMillis > interval && MANUAL_MANAGE_PIN == LOW) {
        // сохраняем время последнего переключения
        previousMillis = currentMillis;
      // включаем нагреватель
       mq135.heaterPwrHigh();
       Serial.println("Heated sensor");
      // если прошёл интервал нагрева датчика
      // и калибровка не была совершена
      if (!mq135.isCalibrated() && mq135.heatingCompleted())
        // выполняем калибровку датчика на чистом воздухе
        mq135.calibrate();
        // при знании сопративления датчика на чистом воздухе
        // можно его указать вручную, допустим 160
        // mq135.calibrate(160);
        // выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
        Serial.print("Ro = ");
        Serial.println(mq135.getRo());
      }
      // если прошёл интевал нагрева датчика
      // и калибровка была совершена
      if (mq135.isCalibrated() && mq135.heatingCompleted()) {
        // выводим отношения текущего сопротивление датчика
        // к сопротивлению датчика в чистом воздухе (Rs/Ro)
        Serial.print("Ratio: ");
        Serial.print(mq135.readRatio());
        // выводим значения газов в ppm
        Serial.print("\tCO2: ");
        Serial.print(mq135.readCO2());
        Serial.println(" ppm");
        fanSpeed = mq135.readCO2(); // устанавливаем значение концентрации СО2 в переменную контроля скорости
        mq135.heaterPwrLow(); // выключаем нагреватель
        delay(100);
      }

    }

    //----------------------ОБРАБОТЧИКИ ПРЕРЫВАНИЙ--------------------------
    void timer_interrupt() {       // прерывания таймера срабатывают каждые 40 мкс
      tic++;                       // счетчик
      if (tic > Dimmer)            // если настало время включать ток
        digitalWrite(dimPin, 1);   // врубить ток
    }

    void  detect_up() {    // обработка внешнего прерывания на пересекание нуля снизу
      tic = 0;                                  // обнулить счетчик
      ResumeTimer1();                           // перезапустить таймер
      attachInterrupt(0, detect_down, RISING);  // перенастроить прерывание
    }

    void  detect_down() {  // обработка внешнего прерывания на пересекание нуля сверху
      tic = 0;                                  // обнулить счетчик
      StopTimer1();                             // остановить таймер
      digitalWrite(dimPin, 0);                  // вырубить ток
      attachInterrupt(0, detect_up, FALLING);   // перенастроить прерывание
    }
    //----------------------ОБРАБОТЧИКИ ПРЕРЫВАНИЙ--------------------------
     

    Вложения:

  2. parovoZZ

    parovoZZ Гуру

    Сам-то понимаешь что в коде?
    Нарисуй алгоритм работы диммера и я тебе укажу на ошибки.
    Диммером можно управлять коллекторным двигателем. Асинхронным низзя - сгорит.
     
  3. Работа диммера переменного тока интересно показана его создателем и доступна по ссылке

    . Постараюсь не исказить информацию и кратко опишу принцип работы в тексте.
    Основным регулирующим элементом диммера является симистор, который может пропускать ток в обоих направлениях и в тоже время выполнять роль ключа - закрывая и открывая канал для переменного тока. В сети имеется переменный ток, который меняет свою полярность с частотой 50 Гц. Следовательно в момент перехода напряжения через "ноль" можно перекрыть канал симистором на небольшое время и затем открыть, тем самым регулируя продолжительность наличия напряжения и высоту волны в одном полупериоде и в другом полупериоде при переходе через "ноль" в обратную сторону. Открывает и закрывает симмистор в данной схеме оптопара с симисторным выходом. Использование оптопар здесь и далее необходимо для гальванической развязки части схемы с высоковольтной составляющей.
    Теперь необходимо точно определить тот самый момент перехода через ноль и сообщить ардуино, что пора засекать время для задержки. Для этого используем транзисторную оптопару и подаем с нее сигнал на Пин 2 аппаратного прерывания ардуины. Используя этот сигнал, контроллер фиксирует, например, восходящий фронт и перенастраивает режим обработки прерывания на противоположный. Внутреннее
    прерывание по таймеру срабатывает каждые 40 мкс и сравнивает количество таких прерываний с переменной Dimmer - время диммирования. Если достигли необходимого количества, открываем симистор.
    Таким образом, как только обнаруживается переход через "ноль" снизу, таймер запускается на время диммирования и прерывание перенастраивается на переход сверху и как только таймер срабатывает открывается симистор. Далее прерывание замечает переход через "ноль" сверху таймер останавливается и прерывание перенастраивается на переход снизу и закрывается симистор. И это все повторяется 50 раз в секунду. Время диммирования определяется переменной Dimmer и должно быть от 0 до 255.
    Переживаю больше за часть кода которая отвечает за работу сенсора СО2 по следующим причинам:
    1. Команды из раздела Setup примера амперки, я перенес в основной цикл и не уверен можно ли так делать.
    2. Постоянное прерывание контроллера на регулировку диммера будет его отвлекать от работы с сенсором. Предположил, что эти прерывания занимают мкс и не внесут помех в работу датчика, если конечно там не будет конфликта в командах библиотек.
    3. Добавил реле отключения нагрузки от сети, если значения сенсора СО2 в нормальных пределах и это также позволит устранить сигнал прерывания пока диммирования не нужно и отдать приоритет для основной программы.
    Регулируемый вентилятор - "ВЕНТС 100 -ВКО". На сайте к нему предлагают Вентс РС-1-300, который является полупроводниковым (симисторным, тиристорным) прибором для регулировки скорости вращения бытовых и промышленных вентиляторов с однофазным напряжением питания - 220 В.
    Предположил, что принцип диммирования в них одинаковый и можно частоту его оборотов регулировать вышеописанным способом.
     
  4. Алгоритм диммера описал выше. Благодарю за готовность помочь.
     
  5. parovoZZ

    parovoZZ Гуру

    Это не алгоритм, а просто описание, которое известно абсолютно всем.
    Алгоритмы вот:
    https://yandex.ru/images/search?text=блоки алгоритма&stype=image&lr=2&source=wiz

    Т.е. нарисовал блок-схему алгоритма и говоришь - вот это условие у меня реализовано вот в этой строчке или функции. И если хочешь составить рабочую программу, то работать надо только так. Сперва алгоритм и только потом программа по этому алгоритму.
     
  6. Алгоритм работы диммера.png
    По моим представлениям, алгоритм работы диммера может выглядеть примерно так. Как можно понять из рисунка программирование не является моей основной профессией, но я очень благодарен за наставничество, поскольку знания не имеют специализации, в отличие от людей. Заранее прошу прощения за возможные ошибки. Посмотреть вложение 13406
     

    Вложения:

  7. parovoZZ

    parovoZZ Гуру

    а здесь нет профессионалов - одни любители. Так что стесняться нечего. Хочешь чтобы помогли - надо предоставить полную картину происходящего. Рисовать в голове алгоритм работы по строчкам кода мало у кого возникает желания. А реализаций алгоритма диммера - море.
     
  8. Здравствуйте,
    Если кому-то интересно, привожу результаты.
    1. Схема работает нормально, прерывания не влияют на конечный результат (тестирую дома уже 2 месяца). Если что-то жарить на кухне, то включится, потом выключиться.
    Из недостатков - сложность калибровки (после некоторого времени показания ползут в сторону увеличения и приходится подправлять калибровочные значения, что он там измеряет неизвестно) и сенсорная кнопка периодически включается самостоятельно (если поставить переключатель механический, то проблем не будет).
    2. Указанный выше двигатель вентилятора работает с диммером нормально, но диммирование меньше чем на половину (100 из 255) не делал. На мультиметре напряжение 150 В показывает.
    3. Все помещается в небольшой распаечной коробке.
    4. Функциональные элементы системы:
    - блок питания AC-DC 5 вольт,
    - ардуино нано,
    - датчик газа MQ135 с выходами А и D,
    - сенсорная кнопка,
    - тактовая кнопка,
    - датчик освещенности на базе фоторезистора и еще одного резистора на 10К,
    - диммер переменного тока как описан выше,
    - подстроечный резистор 10К,
    - красный светодиод,
    - двухцветный светодиод с общим катодом (или подправить код) или от RGB не все ноги можно взять,
    - распаечная коробка,
    - вентилятор ВЕНТС 100 -ВКО или любой, чтобы не жалко было экспериментировать на нем.


    Ниже описываю функционал и схему подключения (рисовать дольше чем все сделать) и прошивку.
    1. Функционал системы:
    - Вентиляция работает в двух режимах - ручном и автоматическом (переключение между режимами тактовой кнопкой);
    - В каждом режиме возможно принудительное включение вытяжки на полную мощность с помощью переключателя или сенсорной кнопки (в моем случае);
    - Датчик освещения корректирует мощность включения вытяжки только в автоматическом режиме (ночью половина, чтобы не шумел, днем - максимум);
    - Датчик газов используется только в автоматическом режиме и для определения концентрации газов и включения вытяжки;
    - Двухцветный (можно два отдельных) светодиод демонстрирует режим работы (зел- авт; син - ручн);
    - Контроль напряжения на нагревательном элементе датчика газа с целью проверки его работоспособности;
    - Красный светодиод для индикации поломки датчика газа (если напряжение выше заданого порога).

    2. Схема подключения
    D4 - управление диммированием;
    D2 - детектор нуля;
    А1 - аналоговый выход датчика газа MQ135;
    А2 - переключатель принудительного включения вентиляции (у меня сенсорная с фиксацией состояния HIGH - LOW);
    А3 - определение напряжения на нагревательном элементе датчика газа (необходимо подпаять провод к выводу датчика газа со стороны отрицательного провода);
    А4 - подключаем к фоторезистору по классической схеме;
    D6 - подключаем к красному светодиоду индикации ошибки работы нагревательного элемента;
    D12 - подключаем к зеленому аноду (у меня с общим катодом) светодиода индикации автоматического режима работы системы ;
    D9 - подключаем к синему аноду (у меня с общим катодом) светодиода индикации ручного режима работы системы;
    А5 - тактовая кнопка смены режима работы ручной-автоматический (при нажатии подаем "ноль", подтягивающий резистор не нужен, настроена внутренняя подтяжка);
    А0 - подключаем к подстроечному резистору для корректировки напряжения для ночного режима.
     
  9. 3. Прошивка
    Код (C++):
    /*
       Диммер переменки на Arduino. Симистор через оптопару
       подключен к 4 пину, детектор нуля ко 2 пину.
       Переменная Dimmer - величина диммирования, от 0 до 255
       В этом коде на пин А0 подключен потенциометр для управления яркостью
    */

    // -----------------БИБЛИОТЕКИ-И КОНСТАНТЫ---------------------------------------------//
    // шустрая библиотека для таймера диммера
    #include <CyberLib.h>
    // библиотека для работы с датчиками MQ (Troyka-модуль)
    #include <TroykaMQ.h>
    #define PERIOD_1 30000    // период проверки показаний датчика газа
    #define GAS_DANGER 750  // показания датчика газа, при которых необходимо включать вентилляцию
    #define NIGHT 150 // УРОВЕНЬ ОСВЕЩЕННОСТИ ДЛЯ НОЧНОГО РЕЖИМА
    #define GAS_VOLTAGE 100 // напряжение на нагревательном элементе в норме
    #define PERIOD_2 500    // период мигания диода ошибки
    #define DEBOUNCE 100  // таймаут антидребезга, миллисекунды
    //----------------ПИНЫ---------------------------------------------------------//
    // имя пина, который управляет диммированием
    #define dimPin 4
    // имя пина, который определяет переход через ноль
    #define zeroPin 2
    // имя для пина, к которому подключен датчик газа
    #define PIN_MQ135  A1
    // имя пина, к которому подключена кнопка принудительного включения вентилляции
    #define buttonPin A2
    // имя пина, который управляет вкючением реле мотора
    // #define powerPin 5
    // имя пина, который определеяет проверяет напряжение на нагревательном элементе датчика газа
    #define gasCheckPin A3
    // имя пина, который следит за освещенностью в комнате
    #define lightPin A4
    // имя пина, который моргает светодиодом при выходе из строя нагревательного элемента датчика газа
    #define errorPin 6
    // имя пина, который показывает автоматический режим работы (зеленый)
    #define autoSetPin  12
    // имя пина, который показывает ручной режим работы (синий)
    #define manualSetPin  9
    // имя пина, к которому подключена кнопка смены режима автоматический-ручной
    #define setBTN  A5
    // -----------------------------ПЕРЕМЕННЫЕ--------------------------------------------//
    // создаём объект для работы с датчиком и передаём ему номер пина
    MQ135 mq135(PIN_MQ135);
    volatile int tic, Dimmer;
    boolean buttonState;
    int ppm;
    unsigned long timer_1; // переменная для таймера периодичности проверки показателей датчика газа
    unsigned long timer_2; // переменная для таймера периодичности мигания диода поломки нагревательного элемента
    int lightLevel = 0; // переменная для получения уровня освещенности
    int gasCheckState; // переменная для определения напряжения на нагревательном элементе датчика газа
    boolean errorState = LOW; // переменная для управления индикатором поломки нагревательного элемента
    boolean btnState, btnFlag; // переменные для управления режимом (ручной/автоматический)работы
    unsigned long debounceTimer;
    boolean setRgimen = LOW;

    void setup() {
      Serial.begin(9600);
      // pinMode(powerPin, OUTPUT);
      pinMode(errorPin, OUTPUT);
      pinMode(dimPin, OUTPUT);
      pinMode (PIN_MQ135, INPUT);
      pinMode (gasCheckPin, INPUT);
      pinMode (lightPin, INPUT);
      pinMode (buttonPin, INPUT);
      pinMode(zeroPin, INPUT);                 // настраиваем порт на вход для отслеживания прохождения сигнала через ноль
      pinMode(autoSetPin, OUTPUT);
      pinMode(manualSetPin, OUTPUT);
      pinMode(setBTN, INPUT_PULLUP);
      digitalWrite(dimPin, 0);
      attachInterrupt(0, detect_up, FALLING);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
      digitalWrite(errorPin, 0);
      digitalWrite(autoSetPin, 0);
      digitalWrite(manualSetPin, 1);

      StartTimer1(timer_interrupt, 40);        // время для одного разряда ШИМ
      StopTimer1();                            // остановить таймер
      mq135.calibrate(450); // после калибровки датчика на чистом воздухе вписать полученноезначение например, mq135.calibrate(160);
      Serial.println("Start");
    }

    void loop() {

      buttonState = digitalRead (buttonPin);
      lightLevel = analogRead (lightPin); // записываем уровень освещенности
      gasCheckState = analogRead (gasCheckPin); // получаем напряжение на нагревательном элементе датчика газа
      digitalWrite(errorPin, errorState); // сигнализируем об ошибке, если обнаружена
      digitalWrite(autoSetPin, setRgimen);
      digitalWrite(manualSetPin, !setRgimen);

      // -------------------------РАБОТА КНОПКИ ПЕРЕКЛЮЧЕНИЯ РЕЖИМА--------------------//
      btnState = !digitalRead(setBTN);  // читаем состояние кнопки с инверсией. 1 - нажата, 0 - нет
      // если нажата и была отпущена (btnFlag 0) и прошло не менее DEBOUNCE времени
      if (btnState && !btnFlag && (millis() - debounceTimer > DEBOUNCE)) {
        setRgimen = !setRgimen; // меняем режим по нажатию кнопки
        btnFlag = true;              // запомнили что нажата включаем автоматический режим
        debounceTimer = millis();    // запомнили время нажатия
        Serial.println("press");
      }
      if (!btnState && btnFlag) {    // если отпущена и была нажата (btnFlag 1) включаем ручной режим
        btnFlag = false;             // запомнили что отпущена
        debounceTimer = millis();    // запомнили время отпускания
        Serial.println("release");
      }

      // --------------------------------- УПРАВЛЕНИЕ ВЕНТИЛЛЯЦИЕЙ---------------//
          //---------------------ЧИТАЕМ ПОКАЗАНИЯ ДАТЧИКА ГАЗА------------------------//
      if (millis() - timer_1 > PERIOD_1) {        // условие таймера
        ppm = mq135.readCO2();                 // выполняем проверку показаний датчика каждые PERIOD_1 миллисекунд
        //Serial.print("buttonState =");
        // Serial.print(buttonState);                   // проверяем работу датчика газа
        // Serial.print("\t");
        Serial.print("ppm=");
        Serial.print(ppm);                   // проверяем работу датчика газа
        Serial.print("\t");
        Serial.print("light=");
        Serial.print(lightLevel);          // проверяем работу датчика освещения
        Serial.print("\t");
        Serial.print("dimmer=");
        Serial.print(Dimmer);              // проверяем работу переменной диммирования
        Serial.print("\t");
        Serial.print("gasVoltage=");
        Serial.println(gasCheckState);       // проверяем напряжение на нагревательном элементе
        timer_1 = millis();                   // сброс таймера
      }
    //---------------------------ВКЛЮЧАЕМ ВЕНТИЛЛЯЦИЮ САМОСТОЯТЕЛЬНО-----------------------//
      if  (buttonState == HIGH) { // если кнопка ручного управления включена подаем напряжение на вентиллятор и устанавливаем диммер на максимум
        // digitalWrite (powerPin, HIGH);
        Dimmer = 0;
      } else if (buttonState == LOW && setRgimen == HIGH) {
        Dimmer = 255;
      }
    //-------------------------------УПРАВЛЯЕМ В АВТОМАТИЧЕСКОМ РЕЖИМЕ-------------------//
      if (ppm < GAS_DANGER && buttonState == LOW && setRgimen == LOW) { // выключаем если датчик показывает низкие значения
        Dimmer = 255;
      }
      if (ppm > GAS_DANGER && buttonState == LOW && setRgimen == LOW) {
        if (lightLevel < NIGHT) {
          Dimmer = map(analogRead(0), 0, 1023, 100, 0); // необходимо подобрать оптимальное напряжение (вместо цифр 100, 0) где 255 будет равно напряжению 0 В, а 0 буде равен напряжению 220 В  
        }
        if (lightLevel >= NIGHT) {
          Dimmer = 0;
        }
      }
    // -------------------------------ПРОВЕРЯЕМ РАБОТОСПОСОБНОСТЬ ДАТЧИКА ГАЗА----------------------------//
      if (gasCheckState < GAS_VOLTAGE && setRgimen == LOW) { // если напряжение упало, значит нагревательный элемент перегорел
        if (millis() - timer_2 > PERIOD_2) {        // мигаем раз в секунду если находимся в автоматическом режиме
          errorState = !errorState; // инвертируем состояния для мигания диодом сигнализирующим об ошибке
          timer_2 = millis();                   // сброс таймера
        }
      } else {
        errorState = LOW;
      }
    }

    //----------------------ОБРАБОТЧИКИ ПРЕРЫВАНИЙ--------------------------
    void timer_interrupt() {       // прерывания таймера срабатывают каждые 40 мкс
      tic++;                       // счетчик
      if (tic > Dimmer)            // если настало время включать ток
        digitalWrite(dimPin, 1);   // врубить ток
    }

    void  detect_up() {    // обработка внешнего прерывания на пересекание нуля снизу
      tic = 0;                                  // обнулить счетчик
      ResumeTimer1();                           // перезапустить таймер
      attachInterrupt(0, detect_down, RISING);  // перенастроить прерывание
    }

    void  detect_down() {  // обработка внешнего прерывания на пересекание нуля сверху
      tic = 0;                                  // обнулить счетчик
      StopTimer1();                             // остановить таймер
      digitalWrite(dimPin, 0);                  // вырубить ток
      attachInterrupt(0, detect_up, FALLING);   // перенастроить прерывание
    }
    //----------------------ОБРАБОТЧИКИ ПРЕРЫВАНИЙ--------------------------