Симисторный регулятор мощности для активной нагрузки на Arduino nano

Когда-то очень  очень очень давно был в радиолюбительской практике один очень популярный тиристор и звали его KY202H . Мы тогда лепили на его базе регуляторы мощности учитывая все его недостатки и сложности и делали развязку по напряжению на ферритовых колечках…………….как давно это было……………….и тут : Вашему вниманию предлагается слегка обновленная версия : «симисторный регулятор мощности для активной нагрузки»

Справедливости ради наверное правильно бы было назвать это изделие : «Регулятор мощности активной инертной нагрузки и LED с помощью PWM на Arduino nano» так как по ходу реализации сего устройства я включил и регулировку для такого популярного сейчас светодиодного направления и если использовать только выход ШИМ на полевой ключ то можно считать этот девайс и как регулятор мощности диммер для LED причем с той особенностью, что частота диммирования очень высока и возможно применять и для регулировки яркости приборов при фото видео съемке без так раздражающих в таких случаях полос и мерцаний связанных с биениями управляющей частоты и частоты кадров фотовидеоаппаратуры.

Ну обо всем по порядку:

  • выбор управления и индикации
  • принцип регулировки мощности для инертной нагрузки
  • управление мощностью для LED
  • адаптация шкалы визуализации и управления с регулировкой мощности
  • используемые в программе готовые библиотеки и наработки других авторов
  • возможные направления развития проекта

Ручка управления и шкала индикации

Сейчас очень много китайских блоков с помощью которых можно быстро и недорого смастерить практически любой космический корабль поэтому не вижу смысла изобретать какие-то специфические блоки и заказывать себе печатные платы пока вы не планируете выпускать что-то тиражное. Я исходя из этих соображений остановил свой выбор на управлении энкодером и индикации LCD.

Для включения нагрузки нужно нажать на ручку и одновременно повернуть по часовой стрелке , для выключения нагрузки нужно нажать на ручку и одновременно повернуть против часовой. Для регулировки мощности нужно просто поворачивать по часовой для увеличения мощности и против часовой для уменьшения мощности. Использование микропроцессора в качестве мозга регулятора позволяет обойти проблемы всех аналоговых регуляторов — это так называемые хвосты — то есть крайние положения. На 100% мощности нагрузка будет постоянно включена а на 0% мощности нагрузка будет полностью выключена.

Индикация и отображение состояния деваййса.

Для индикации я взял популярный дисплей LCD 1602 причем даже без экономии выводов и подключения по i2c , у нас хватает ресурса Arduino nano по выводам мк. В верхней строке дисплея выводим красивую надпись которая прямо обозначает назначение устройства, а в конце строки выводим процент мощности от максимальной по нагрузке.

Вторая строка дисплея отдана под линейную шкалу от минимальной мощности и полностью пустой строки до максимальной мощности и полностью закрашенной строки.

В момент включения реализована плавная подсветка экрана LCD 1602 благо ресурсы платы позволяют это легко реализовать как и плавное прощание в момент выключения. Этим занимается отдельный канал PWM Arduino и специальные циклы программного кода.

симисторный регулятор мощности — способ регулировки мощности.

Основное назначение этой тусовки китайских радиокомпонентов  это симисторный регулятор мощности для электроплитки (любой активной нагрузки), поэтому начну рассказ о принципе работы устройства с цикла управления мощностью инертной нагрузки.

В сети у нас 220 вольт и 50 Герц, мы с вами адекватные пользователи, поэтому без лишней на то необходимости не будем сорить и шуметь в сеть. Используем принцип управления нагрузкой когда включать и выключать симисторный регулятор мощности  мы будем на целое количество полупериодов и в момент перехода сетевого напряжения через 0. Сейчас это не сложно реализовать, а развязка по напряжению сети от схемы управления это как минимум правило хорошего тона а как максимум — обязательное условие для своей безопасности и безопасности любого пользователя нашего девайса.

Для управления симистором есть отличная микросхема мос3063

мос3063
Микросхема мос3063

с минимальной обвязкой рассыпухой она позволит сделать опторазвязку с напряжением сети и проконтролирует момент включения нашего тиристора при переходе сетевого напряжения через ноль. Для управления будет достаточно тока и напряжения с выхода ардуинки. Добавляем в комплект наших деталей мощный симистор например BTA41600 и получаем готовую выходную часть для активной инертной нагрузки как то электроплитка или водонагреватель или утюг или радиатор масляный — все что греется ТЕНом может быть запитано посредством этого симисторного регулятора мощности для электроплитки на Arduino nano.

Для трехфазной нагрузки достаточно будет сделать симисторный регулятор мощности в количестве трех штук , точнее , нужно сделать три выходных канала и подключить в разрыв фазы каждого канала 220V , управляя всего одной ардуиной и получить регулятор для нагрузки большей мощности. Схема подключения к Ардуино

симисторный регулятор мощности
Подключение тиристора к выходу микроконтроллера Ардуино

Для непосредственного подключения оптрона тиристора используется 13 пин Ардуины, для возможного реализации исполнительного устройства на базе транзисторного ключа либо твердотельного реле можно использовать 12 pin Arduino Nano в скетче эта функция уже присутствует при этом выходной каскад может визуально быть похожим на подключение обычного реле, к примеру возьмем твердотельное реле SSR-40DA благо выбор  реле сейчас достаточно широкий и цена плюс минус приемлемая напряжение срабатывания  4V ток нагрузки 40А и напряжение коммутации позволяет непосредственно подключать к сети 220V.

Твердотельное реле
Твердотельное реле SSR-40DA

И есть встроенная схема контроля перехода сетевого напряжения через ноль что автоматически уменьшает помехи как и в случае рассыпухи мы делали. Так с выходным каскадом разобрались, можно вернуться чуть к теории к формулам и математике.

Выбор периода с учетом особенностей питающей сети и инертности нагрузки шим регулятора.

В питающей сети 220V переменный ток имеет форму синусоиды с частотой 50 Герц, я привязал включение и выключение нагрузки к целому числу полуволн сетевого напряжения, соответственно минимально я могу включить нагрузку на один полупериод сети — то есть на 0,01 с или на 10ms. Дальше следует выбрать шаг градации мощности при приближении к максимальной и определить для себя на сколько ступеней мы будем регулировать мощность в нагрузке. Постановка задачи :

  • минимальное время включения нагрузки 10ms
  • количество ступеней регулировки мощности от 50 до 100
  • растягивание шкалы при приближении к максимальной мощности
  • мощность в нагрузке P=U²/R
  • сжатие шкалы на минимальной мощности нагрузки
  • адаптация регулировки мощности применительно к LED нагрузке
  • правила хорошего тона или гоу в прерывания

Сложнее всего сделать выбор по количеству ступеней регулировки — ведь микропроцессор позволяет реализовать практически любое значение. Компромисс выбираем исходя из здравого смысла — например ограничиться десятком ступеней регулировки мощности как по мне маловато да и не так сложно изменить мощность на 10% одним поворотом энкодера, выбирать количество ступеней больше ста думаю тоже излишне — для того чтобы включить на полную мощность придется делать много оборотов энкодером — вот в районе 50-60 ступеней самое оно. Не буду слишком растягивать описание — результат эмпирически получилось 65 ступеней регулировки мощности где 65 ступень это 100% мощности а 1 это 0% мощности.

Плотнее всего шкала возле 100% мощности потому что мощность это квадрат напряжения а мы можем пропускать в нагрузку целые полупериоды с ограниченным периодом, ведь если период будет больше минуты будут возможные ограничения применения и этот мощный шим регулятор окажется бесполезной игрушкой из-за недостаточной инертности нагревательной системы.

По простому регулятор мощности для тэна управляет ТЕНом, например для поддержания минимального кипения в той же схеме ректификации, а из-за периода в несколько минут может получиться что в момент включения тиристора жидкость кипит а в момент выключения перестает, снова же эмпирически период около 10-15 секунд думаю устроит практически любое применение.

Рассмотрим шкалу регулировки мощности активной инертной нагрузки

Упустим изначальные вычисления и на примере максимума и минимума объясню принцип адаптации шкалы регулировки мощности. Период 10,2 секунды — это 1020 полуволн сетевого напряжения шкала из 65 делений — то есть почти  16 полуволн отвечают за один шаг шкалы.

  • то есть между 65 и 60 шагом 1020 и 1004 полуволн напряжения сети или  в пересчете на соотношение по мощности это (940/1020)²•100%=85%
  • в то же время между 65 и 60 шагом по шкале индикации % получается (100%/65)•5=92%
  • соответственно между 1 и 6 шагом внизу шкалы 8% по шкале индикации и по мощности соответственно ((5•16)/1020)²•100%=0,6%

То есть два несоответствия на 60 шаге условной шкалы по равномерной градации получаем отображение 92% а на самом деле в нагрузке 85% мощности на начальном этапе шкалы на 6 положении соответственно должно быть 8% а на самом деле всего 0,6% мощности. Поэтому для эргономики и соответствия визуальной шкалы и периода ШИМ вводим в скетч массив заранее просчитанных значений периода и например возьмем тот же шестой элемент как самый показательный (71/255)²•100% = 7,7% мощности для 60 элемента (243/255)²•100% = 90,8% мощности. Отображаем 8% — в нагрузке 7,7% и отображаем 92% — в нагрузке 90,8% в таком же ключе пересчитаны все остальные элементы массива мощности. Это очень удобно и эргономично.

Рассмотрим шкалу регулировки мощности LED нагрузки.

Ни для кого не секрет то, что LED это на сегодня широко распространенные источники как освещения так и подсветки, в том числе и для фото и видео. Было бы неправильно обойти вниманием возможность регулировки яркости этих источников света, но было бы совсем скучно если бы было все так просто. Зависимость яркости освещения от линейной шкалы естественно нелинейна!

Зависимость освещенности от яркости источника света
Зависимость восприятия освещенности человеком от яркости источника света

Не сложно заметить, что для уменьшения освещенности в два раза источник света должен уменьшить свою яркость примерно до 12%! Для уменьшения освещенности в четыре раза нужно уменьшить яркость источника вплоть до 3%!!! Яркость LED зависит от мощности выделяемой на кристалле , а так как LED прибор токовый, то и мощность будем считать по току.

В качестве нагрузки в большинстве распространенных LED лент подсветки последовательно с кристалом или с тройкой LED кристаллов включается токоограниивающий резистор , а так как регулировка будет посредством ШИМ , то можно приравнять управление по напряжению к управлению током, проходящим в цепи. То есть для 50% освещенности скважность ШИМ должен быть    и для 25% скважность ШИМ должна быть

Тут важен принцип формирования массива значений. Аналогично с пересчетом шкалы по активной нагрузке массив

отвечает за шкалу яркости которая в свою очередь корелируется с током через токоограничительный резистор. То есть яркость пропорциональна мощности выделяющейся на резисторе P=I²R ток в свою очередь можно рассчитать для белых линеек по три диода по формуле I=(12-9,6)/R так например яркая лента из 5630 кристаллов на линейку кушает около 80mA и резистор 33 ома то регулировать будем ток на этом резисторе за вычетом постоянной составляющей напряжения 9,6 вольт. Аналогично для 10 элемента шкалы ((8/255)*12-9,6)²

Итого :

  1. Период ШИМ 10 секунд
  2. Шкала регулировки мощности разбита на 65 делений
  3. В минимальном положении регулятор полностью выключен а в максимальном полностью включен
  4. Шкала визуализации коррелируется с мощностью в нагрузке
  5. Регулировка яркости LED коррелируется с током через кристаллы
  6. Частота PWM для LED 62.5 КГц

 

// Регулятор мощности активной нагрузки с периодом 17 секунд и LED 62.5 кГц с помощью PWM модуляции 
// include the library code:
#include <avr/interrupt.h>                                      // для ассемблерного прерывания
#include <avr/io.h>                                             // для ассемблерного прерывания
#include <LiquidCrystal.h>
#include "GyverEncoder.h"
#define CLK A2                                                  // initialize the library with the numbers of the interface pins
#define DT A1
#define SW A0
//  Определяем массив элементы которого будут хранить различную информацию в зависимости от режима
const int powerWATT[65] = {0,32,45,55,64,71,78,84,90,95,100,105,110,114,119,123,127,131,135,
                          139,142,146,149,152,156,159,162,165,168,171,174,177,180,183,185,
                          188,190,193,196,198,201,203,206,208,211,213,215,218,220,222,225,
                          227,229,231,233,235,237,239,241,243,245,247,249,252,255};               // powerWATT массив приведения мощности к длительности цыкла ШИМ диапазон от 0 до 64 что соответствует от 0% до 100% мощности
const int powerLED[32] = {0,2,3,5,8,12,17,22,27,33,40,48,57,66,76,86,96,105,125,135,145,155,165,175,185,197,213,230,240,245,250,255};
Encoder enc1(CLK, DT, SW);
LiquidCrystal  lcd(7, 6,  5, 4, 8, 2);                          // Подключение LCD к цыфровым выходам
int Pwleng;                                                     // переменная Pwleng для аппаратного ШИМ диапазон от 0 до 128 что соответствует от 0% до 100%
volatile int PwWidth;                                           // Переменная PwWidth для программного ШИМ по прерываниям от таймера 1 диапазон от 0 до 64 что соответствует от 0% до 100% мощности
volatile int powerQ;                                            // переменная периода для программного ШИМ по прерываниям от таймера 1 диапазон от 0 до 64
boolean timer_power_On;                                         // при 1 выдаем ШИМ по прерываниям от таймера 1 на выход 12
int power;
int lcdin;
boolean powerON;
int ij;
volatile int buttonState = 0;                                  // переменная для чтения состояния кнопки
void setup() {
      lcd.begin(16, 2);
      powerON = false;                                        // Пины D3 и D11 - 62.5 кГц аппаратный ШИМ
      TCCR2B = 0b00000001;                                    // x1 настройка таймера прерываний на аппаратный ШИМ
      TCCR2A = 0b00000011;                                    // fast настройка таймера прерываний на аппаратный ШИМ
      TCCR1A = 0b00000011;                                    // 10bit настройка таймера прерываний на программный ШИМ 15 Гц
      TCCR1B = 0b00001101;                                    // x1024 настройка таймера прерываний на программный ШИМ
      TIMSK1 |= 1<<TOIE1;                                     // бит TOIE1 у регистра TIMSK1 разрешаю прерывание по переполнению  
      pinMode(12, OUTPUT);                                    // шим выход на тиристор с привязкой к полуволнам сети период 10,2 секунды
      pinMode(13, OUTPUT);                                    // шим инверсный выход на тиристор с привязкой к полуволнам сети период 10,2 секунды
      pinMode(11, OUTPUT);                                    // шим выход на МОП транзистор 62,5 КГц
      pinMode(3, OUTPUT);                                     // Управление светодиодом подсветки LCD
      Serial.begin(9600);                                     // Инициализация последовательного интерфейса
      attachInterrupt(0, isr, CHANGE);                        // прерывание на 2 пине! CLK у NANO
      digitalWrite(9,LOW);
      digitalWrite(11,LOW);
      digitalWrite(12,LOW);
      digitalWrite(13,HIGH);
}     
ISR(TIMER1_OVF_vect)                                          // подпрограмма обработки прерывания от переполнения TIMER1 период 66мс
     {
          powerQ++;                                           // инкремент переменной счетчика цыкла по каждому 40 прерыванию тамера то есть раз в 0.04 с
          TIFR1 |= 0<<TOV1; // Timer1 INT Flag Reg: Сброс флага прерывания Timer Overflow Flag } void isr() { // подпрограмма обработки прерывания для энкодера enc1.tick(); // отработка в прерывании } void loop() { digitalWrite(3,!powerON); // подсветка экрана включена только когда подаем питание на нагрузку enc1.tick(); // отработка энкодера if (enc1.isRight()) { // если был поворот вправо уменьшим скважность ШИМ Pwleng ++ ; if (Pwleng > 128) Pwleng = 128;
      }     
  if (enc1.isLeft()) 
       {
          Pwleng -- ;                                              // если был поворот влево увеличим скважность ШИМ
        if (Pwleng < 0) Pwleng = 0; // не будем забывать о границах и отработаем возможные ошибки при работе программы if (Pwleng > 128) Pwleng = 0;
        }
  if (enc1.isRightH())                                             // если было удержание + поворот вправо включаем устройство
         {
               lcd.clear();                                        // очистим дисплей
               lcd.print(" PWM 2020 Farik");                       // экран приветствия верхняя строка
               lcd.setCursor(0, 1);                                // переводим курсор на нижнюю строку
               lcd.print(" 0%-100% AC&DC");                        // тип устройства и модель
                    for (int ij = 255; ij > 0; ij--)               // плавное включение экрана
                        {
                                 analogWrite(3,ij);  //
                          delay(12);
                        }
               lcd.clear();
               powerON = 1;
         }
  if (enc1.isLeftH())                                               
          {
               lcd.clear();
               lcd.print(" power off ");
               lcd.setCursor(0, 1);
               lcd.print(" good  bye");
                    for (int ij = 0; ij <= 255; ij++)
                        {
                                 analogWrite(3,ij);
                          delay(25);
                        }
               lcd.clear();
             powerON = 0;
          }
      lcd.setCursor(0, 0);                                          // нарисуем красиво на дисплее установка курсора в верхней строке слева в начале строки
      lcd.print("Power on");                                        // стартовая надпись вклюенного регуляятора
      power = map(Pwleng, 0,128, 0,100);                            // преобразуем диапазон управляющей переменной в привычный для нас диапазон 0-100%
      lcd.setCursor(12, 0);                                         // установим курсор в конце верхней строки под вывод процентов
      if (power < 10) lcd.print(" ");                               // строка нормализации положения вне зависимости от колиества знаков
      if (power < 100) lcd.print(" ");                              // та же функция для двузначного числа
      lcd.print(power);                                             // вывод числа процентов на экран
      lcd.setCursor(15, 0);                                         // установим курсор под вывод знака процентов
      lcd.write(byte(37));                                          // знак процента
      lcdin = map (Pwleng,0,128,0,16);                               // преобразуем нашу переменную под вывод линейной шкалы из 16 знаков
      lcd.setCursor(0, 1);                                          // установим курсор в левом нижнем углу дисплея
      for (int i = 0; i < 16; i++)                                  // организуем цыкл для вывода шкалы
        {                                                           //
          if (i < lcdin) lcd.write(byte(255)); // вывод одного элемента шкалы полностью закрашенного сегмента else lcd.print(" "); // остальные знакоместа заполняем пробелом } // PwWidth = powerWATT[ map (Pwleng,0,128,0,64)]; // задаем длительность периода ШИМ по прерываниям от таймера 2 из массива в соответствии с переменной мощности if (powerQ > 255) powerQ = 0;                                // организуем цыкл периода ШИМ по таймеру с периодом 256
         if (PwWidth >= powerQ && PwWidth) timer_power_On = true ;  // длительность высокого уровня сигнала на выходе ШИМ по таймеру исключим ситуацию 0%
         else timer_power_On = false;                               // длительность низкого уровня сигнала на выходе ШИМ по таймеру
                                                                    // вывод ШИМ на пины выходов для нагревателя и тиристорного регулятора
                                                            
      if (powerON)                                                  // Если устройство включено то выводим активные сигналы
        { 
              analogWrite(11,powerLED[map(Pwleng, 0,128, 0,31)]);   // Выход с высокой частотой  для LED нагрузки и транзисторного управления
              if (timer_power_On)
                  {
                   digitalWrite(12,HIGH);                            // Если ШИМ по таймеру должен быть включен выводим сигнал на 12 пин
                   digitalWrite(13,LOW);
                  }
              else 
                   { 
                    digitalWrite(12,LOW);                           // Если ШИМ по таймеру должен быть выключен выводим 0 на 12 пин
                    digitalWrite(13,HIGH);
                   }
        }
       else                                                         // Если устройство выключено то выводим сигналы выключения нв все выходы
          {
              digitalWrite(9,LOW);
              digitalWrite(11,LOW);
              digitalWrite(12,LOW);
              digitalWrite(13,HIGH);
          } 
}