Код ардуино для модуляции пропуска импульсов (PSM)
Я недавно купил этот диммер, и только когда я получил его, я заметил, что он работает с PSM (модуляцией пропуска импульсов), а не с PWD (широтно-импульсной модуляцией).
Кто-нибудь знает, как написать код Arduino и выполнить подключение для этого диммера? Кажется, я не могу найти рабочий пример.
Спасибо@Guy Sopher, 👍3
Обсуждение3 ответа
Лучший ответ:
Я предполагаю, что вы используете этот модуль.
PSM часто используется из-за его более высокой эффективности при небольших нагрузках. Это также лучше для нагрузок переменного тока, так как они должны получать полное переменное напряжение, а не постоянное напряжение (когда вы сокращаете половину волны).
Модуль, который у вас есть, создан для того, чтобы помочь вам правильно внедрить PSM. Он имеет функцию обнаружения пересечения нуля, которая подает сигнал на вывод Z-C каждый раз, когда синусоидальная волна переменного тока пересекает нулевое напряжение (что является наилучшим временем для переключения). Вы можете ощутить сигнал с помощью прерывания в вашем Arduino. На веб-сайте не объясняется точно, что выводится выводом Z-C при пересечении нуля, но вы можете легко проверить это самостоятельно, контролируя как переменное, так и Z-C напряжение при работе. Скорее всего, вам придется использовать либо прерывание ПАДЕНИЯ
, либо прерывание ИЗМЕНЕНИЯ.
PSM работает с модуляцией количества импульсов (в данном случае полных периодов синусоидальной волны), передаваемых на нагрузку. Представьте, что вы хотите приглушить свет в 10 различных значениях.
- Для полной мощности вы всегда устанавливаете вывод, помеченный PWM, на высокий, когда начинается полная синусоидальная волна (это происходит при каждом втором пересечении нуля). Это означает, что вывод ШИМ всегда находится на высоком уровне.
- Для получения половинной мощности вы включаете вывод PWM на максимум на 5 полных периодов, а затем выключаете его еще на 5 периодов.
- На 10% (значение 1) вы включаете вывод PWM на максимум на 1 полный период, а затем выключаете на 9 периодов.
Недостатком этого метода является то, что вы можете увидеть мерцание света при низких значениях.
При реализации этого вы можете использовать функцию attachInterrupt()
с выводом Z-C. В функции обратного вызова вы переключаете глобальную (изменчивую!) логическую переменную, чтобы указать, начинается ли новый полный период или сигнал пересечения нуля указывает только на начало отрицательной части синусоидальной волны. Также используйте глобальную (изменчивую!) переменную счетчика, которая подсчитывает (увеличивает каждый полный период) заданное вами значение (здесь что-то между 0 и 10). Когда переменная счетчика равна 0 (а желаемое значение больше 0), вы записываете значение HIGH на вывод PWM вашего модуля. Когда счетчик достигает желаемого значения, вы записываете значение LOW на вывод PWM. Когда счетчик достигает максимального значения, вы сбрасываете его на 0.
В коде что-то вроде этого:
volatile byte counter=0;
volatile boolean new_period = true;
volatile byte value=5;
#define MAX_VALUE 10
void setup(){
// установите pinModes для правильных контактов
// активное прерывание. Обратите внимание, что вам, возможно, придется изменить падение на значение, соответствующее выходным данным модуля (см. Объяснение выше).
attachInterrupt(digitalPinToInterrupt(Z_C_pin), zero_crossing, FALLING);
}
void zero_crossing(){
if(new_period){
if(counter==0 && value>0) digitalWrite(PWM_pin,HIGH);
if(counter==value) digitalWrite(PWM_pin,LOW);
counter++;
if(counter > MAX_VALUE) counter=0;
}
new_period=!new_period;
}
Примечание: Особенно при наличии большого диапазона возможных значений, некоторые из значений могут быть заменены лучшим поведением, что предотвратит небольшое мерцание. Например, если вы используете 100 различных ступеней затемнения и хотите уменьшить яркость до 50%, вы можете либо (как показано выше) включить свет на 50 периодов, а затем выключить его еще на 50 периодов. Или вы можете включаться во время каждого второго урока. Хотя это не поможет вам с действительно маленькими значениями. Поэтому я опустил это для простоты.
Удивительный ответ. Отлично работает..., @Guy Sopher
@chrisl Привет, пока я пробую Mega 2560 с attachInterrupt (0, zero_crosss_int, RISING); или attachInterrupt(digitalPinToInterrupt(interruptPin), zero_crosss_int, RISING); я получаю статус выхода 1 Ошибка компиляции для платы Arduino/Genuino Mega или Mega 2560. ошибка. Как это решить?, @Alper
Полный код ошибки:
WInterrupts.co (символ из плагина): В функции attachInterrupt':
(.text+0x0): множественное определение
__vector_5'
библиотеки\RBDdimmer\RBDdimmer.cpp.o (символ из плагина):(.text+0x0): впервые определено здесь
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/5.4.0/../../../../avr/bin/ld. exe: Отключение релаксации: это не будет работать с несколькими определениями
collect2.exe: ошибка: ld вернул 1 статус выхода
статус выхода 1
Ошибка компиляции для платы Arduino/Genuino Mega или Mega 2560., @Alper
Библиотека RBDdimmer, по-видимому, также определяет соответствующий ISR, что невозможно сделать дважды. Пробовали ли вы другие пины? Mega 2560, похоже, имеет 8 внешних прерываний, а библиотека RBDdimmer заблокирована для D2 на странице github., @chrisl
Все порты (2, 3, 18, 19, 20, 21) приводят к одной и той же ошибке., @Alper
Ммм, может быть, вам следует задать новый вопрос с этим и сослаться на этот вопрос в нем, @chrisl
Просто добавляю к ответу Крисла, так как я тоже купил этот модуль.
На веб-сайте производителя этого модуля есть простой пример, который, похоже, не реализует PSM очевидным способом:
/*
Подключите диммер переменного тока RobotDyn следующим образом:
Кинтакт диммера - контакт Arduino
VCC - 5 В
GND - GND
Z-C - D2
ШИМ - D3
Скетч свечения для диммера переменного напряжения с нулевым перекрестным обнаружением
По мотивам скетча Чарит Фернанадо
Адаптировано RobotDyn: http://www.robotdyn.com
Лицензия: Лицензия Creative Commons Attribution Share-Alike 3.0.
Присоедините нулевой перекрестный вывод модуля к внешнему контакту прерывания Arduino
Выберите правильный номер прерывания из приведенной ниже таблицы (номера контактов являются цифровыми контактами, а НЕ физическими контактами: цифровой контакт 2 [INT0] = физический контакт 4 и цифровой контакт 3 [INT1] = физический контакт 5).
Pin | Interrrupt # | Arduino Platform
---------------------------------------
2 | 0 | All
3 | 1 | All
18 | 5 | Arduino Mega Only
19 | 4 | Arduino Mega Only
20 | 3 | Arduino Mega Only
21 | 2 | Arduino Mega Only
In the program pin 2 is chosen
*/
int AC_LOAD = 3; // Вывод на вывод оптического симистора
int dimming = 128; // Уровень затемнения (0-128) 0 = ВКЛ., 128 = ВЫКЛ.
void setup()
{
pinMode(AC_LOAD, OUTPUT);// Установить вывод нагрузки переменного тока в качестве вывода
attachInterrupt(0, zero_crosss_int, RISING); // Выберите нулевое перекрестное прерывание # из приведенной выше таблицы
}
// функция прерывания не должна принимать никаких параметров и ничего не возвращать
void zero_crosss_int() // функция, которая запускается при пересечении нуля, чтобы приглушить свет
{
// Расчет угла обстрела: 1 полная волна 50 Гц = 1/50 = 20 мс
// Каждое пересечение нулей таким образом: (50 Гц) -> 10 мс (1/2 цикла) для 60 Гц => 8,33 мс (10000 / 120)
// 10 мс = 10000 мкс
// (10000 - 10us) / 128 = 75 (приблизительно) Для 60 Гц => 65
int dimtime = (75*dimming); // Для 60 Гц =>65
delayMicroseconds(dimtime); // Выключение цикла
digitalWrite(AC_LOAD, HIGH); // задержка запуска симистора
delayMicroseconds(10); // задержка включения симистора (для 60 Гц используйте 8.33)
digitalWrite(AC_LOAD, LOW); // симистор выключен
}
void loop() {
for (int i=5; i <= 120; i++){ // Мы используем 120 как самую низкую и 5 как самую высокую настройку яркости. Может регулироваться в зависимости от используемой лампы.
dimming=i;
delay(20);
}
for (int i=120; i >= 5; i--){ // То же, что и выше
dimming=i;
delay(20);
}
}
Они используют прерывание, как предложил крисл. При низких значениях яркости мерцания нет (при использовании лампы накаливания). Смотрите это видео для получения аналогичной платы с оригинальной версией приведенного выше скетча.
Примечание: Если вы хотите интегрировать свой собственный код в этот пример, он, скорее всего, не будет работать должным образом, потому что Arduino большую часть времени занят delayMicroseconds()
РЕДАКТИРОВАТЬ: производитель этого модуля только что выпустил библиотеку. Проверьте это на их github
Этот модуль позволяет реализовать модуляцию с пропуском импульсов, а также управление фазовым углом. Код, который reins.ch на самом деле это последнее.
- Установите частоту ШИМ на 25 кГц.
- Какова частота PWM-выхода на Arduino
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как устранить шум от вентилятора 12 В с ШИМ-управлением на низкой скорости
- Генерация частоты ШИМ выше 125 кГц с помощью Arduino Uno
- Увеличить разрядность PWM
- Как вывести истинное аналоговое напряжение на выходной контакт
- PWM-вывод Arduino Nano не функционирует
Модуль представляет собой симистор с некоторыми вспомогательными компонентами. Таким образом, вместо PSM вы можете выполнять фазовую резку (резку переднего края). Здесь вы включаете симистор где-то во время синусоиды. Как только симистор включен, он остается включенным до следующего перехода через ноль. Таким образом, вы используете сигнал пересечения нуля, чтобы узнать, когда начнется следующий цикл, а затем включаете симистор где-то в цикле. Просто обратите внимание, что, поскольку вы нарезаете синусоиду, результирующая яркость не будет линейно пропорциональна проценту времени, в течение которого она включена., @Gerben
Кроме того, сетевые светодиодные фонари, которые поддерживают диммирование, делают это путем измерения входящей формы волны и расчета значения ШИМ на основе этого. Поскольку основной частью светодиода является мостовой выпрямитель и сглаживающий конденсатор. Использование обычной светодиодной лампы на диммере будет иметь очень небольшой эффект, пока диммер почти полностью не выключится., @Gerben
Я кстати тоже недавно купил такой же диммер. Есть ли способ изменить интенсивность с помощью более высокой и низкой интенсивности? Есть ли способ, скажем, на 25-30 ярче или тусклее? Я хотел установить на нем какой-то счетчик, чтобы в течение примерно минуты он мог уменьшаться от полной яркости до полностью выключенного. Также вывод Z_C должен быть выводом PWM на Arduino? Спасибо за помощь!, @timshine