Код Arduino для модуляции импульсного пропускания (PSM)

Недавно я купил этот световой диммер, и только когда я его получил, я заметил, что он работает с PSM (модуляцией импульсного пропускания), а не PWD (широтно-импульсная модуляция).

Кто-нибудь знает, как написать код Arduino и сделать проводку для этого диммера? Кажется, я не могу найти рабочий пример.

Спасибо

 RobotDyn PSM Light Dimmer введите описание изображения здесь

pwm
1 голос | спросил Guy Sopher 15 PMpSun, 15 Apr 2018 14:34:43 +030034Sunday 2018, 14:34:43

2 ответа


1

Я предполагаю, что вы используете этот модуль .

PSM часто используется из-за более высокой эффективности при легких нагрузках. Это также лучше для нагрузки переменного тока, так как они должны получить полное напряжение переменного тока, а не постоянное напряжение (когда вы разрезаете половину волны).

Модуль, который у вас есть, создан для правильной поддержки PSM. Он имеет обнаружение с нулевым пересечением, которое дает сигнал на выводе Z-C каждый раз, когда синусоидальная переменная переменного тока пересекает нулевое напряжение (что является лучшим временем переключения). Вы можете ощутить сигнал с прерыванием в Arduino. Веб-сайт не объясняет точно, что выдает вывод Z-C при пересечении нуля, но вы можете легко это проверить самостоятельно, контролируя как напряжение переменного тока, так и напряжение Z-C. Скорее всего, вам придется использовать либо FALLING, либо CHANGE.

PSM работает с модулированием количества импульсов (в данном случае полных периодов синусоидальной волны), передаваемых на нагрузку. Представьте, что вы хотите уменьшить свет в 10 различных значениях.

  • Для полной мощности вы всегда устанавливаете штырь, обозначенный PWM, на высокий, когда начинается полная синусоидальная волна (это происходит при каждом втором пересечении нуля). Это означает, что вывод PWM всегда высок.
  • Для половины мощности вы поворачиваете штырь PWM на 5 полных периодов, а затем выключаете его на 5 периодов.
  • Для 10% (значение 1) вы поворачиваете штырь PWM высоко в течение 1 полного периода, а затем выкл. в течение 9 периодов.

Недостатком этого метода является то, что вы можете видеть мерцание света при низких значениях.

При реализации этой функции вы можете использовать функцию attachInterrupt() с выводом Z-C. В функции обратного вызова вы переключаете глобальную (volatile!) Логическую переменную, чтобы указать, если начинается новый полный период, или если сигнал пересечения нуля указывает только на начало отрицательной части синусоидальной волны. Также используйте глобальную переменную (volatile!), Которая подсчитывает (увеличивает каждый полный период) до значения, которое вы задаете (здесь что-то между 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(){
  // set pinModes for the correct pins

  // active interrupt. Note, that you may have to change FALLING to a value fitting the output of the module (see explanation above)
  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 периодов. Или вы можете включить каждый второй период. Хотя это не поможет вам с очень маленькими ценностями. Поэтому я оставил его для простоты.

ответил chrisl 15 PMpSun, 15 Apr 2018 18:07:57 +030007Sunday 2018, 18:07:57
2

Просто добавив к ответ chrisl , так как я тоже купил этот модуль.

Существует простой пример на сайт производителей этого модуля , который, похоже, не реализует PSM очевидным образом:

/*
Connect RobotDyn AC Light Dimmer as follows:
Dimmer pin  --  Arduino pin
    VCC     --    5V
    GND     --    GND
    Z-C     --    D2
    PWM     --    D3

Glow sketch for AC Voltage dimmer with Zero cross detection
Based on the sketch by Charith Fernanado 
Adapted by RobotDyn: http://www.robotdyn.com
License: Creative Commons Attribution Share-Alike 3.0 License.
Attach the Zero cross pin of the module to Arduino External Interrupt pin
Select the correct Interrupt # from the below table (the Pin numbers are digital pins, NOT physical pins: digital pin 2 [INT0]=physical pin 4 and digital pin 3 [INT1]= physical pin 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;    // Output to Opto Triac pin
int dimming = 128;  // Dimming level (0-128)  0 = ON, 128 = OFF

void setup()
{
  pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output
  attachInterrupt(0, zero_crosss_int, RISING);  // Choose the zero cross interrupt # from the table above
}

// the interrupt function must take no parameters and return nothing
void zero_crosss_int()  // function to be fired at the zero crossing to dim the light
{
  // Firing angle calculation : 1 full 50Hz wave =1/50=20ms 
  // Every zerocrossing thus: (50Hz)-> 10ms (1/2 Cycle) For 60Hz => 8.33ms (10.000/120)
  // 10ms=10000us
  // (10000us - 10us) / 128 = 75 (Approx) For 60Hz =>65

  int dimtime = (75*dimming);    // For 60Hz =>65    
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(AC_LOAD, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay (for 60Hz use 8.33)
  digitalWrite(AC_LOAD, LOW);    // triac Off
}

void loop()  {
  for (int i=5; i <= 120; i++){  // We use 120 as the lowest and 5 as the highest brightness setting. May be adjusted depending on the lamp used.
    dimming=i;
    delay(20);
   }
  for (int i=120; i >= 5; i--){  // Same as above
    dimming=i;
    delay(20);
   }
}

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

Примечание. . Если вы хотите интегрировать свой собственный код в этот пример, он, скорее всего, не будет работать так, как предполагалось, потому что Arduino занят delayMicroseconds() большую часть времени


Я, вероятно, вернусь, как только проведу больше времени с модулем.

ответил reins.ch 25 +03002018-10-25T17:57:38+03:00312018bEurope/MoscowThu, 25 Oct 2018 17:57:38 +0300 2018, 17:57:38

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132