Диммер переменного тока (AC Dimmer RBDDimmer)

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Здравствуйте. Возникла необходимость диммировать насос, подключающийся в 220В/50Гц, для этих целей купил RBDDimmer, способный, как я понял из описания, диммировать, как срезая часть синусоиды, так и пропуская полупериод (мне как раз надо диммировать пропуская период).

Скачал, подключил RBDdimmer.h, полез в документацию и с удивлением обнаружил, что для диммирования есть одна функция:

dimmer.setPower(n); // где n принимает значения от 0 до 100
Но эта функция именно срезает часть синусоиды, мне же необходимо часть пропускать.
Как это реализовать на  RBDdimmer.h?
 
 
P.S. Пока писал, придумал костылик с включением и отключением самого модуля:
dimmer.setPower(100);//синусоида не срезается
dimmer.setState(ON);//включаю устройство
delay(50);//жду 1 период
dimmer.setState(OFF);//выключаю устройство
delay(50);//жду 1 период

Вот таким способом я снизил мощность насоса на 50%, но это именно костыль. Как сделать по уму?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

andreykrasnodar пишет:

Здравствуйте. Возникла необходимость диммировать насос, подключающийся в 220В/50Гц, для этих целей купил RBDDimmer, способный, как я понял из описания, диммировать, как срезая часть синусоиды, так и пропуская полупериод (мне как раз надо диммировать пропуская период).

Заклинит насос. Не надо так. 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Для равномерного распределения пропущенных периодов надо использовать алгоритм Брезинхема

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

andreykrasnodar пишет:

dimmer.setPower(100);//синусоида не срезается
dimmer.setState(ON);//включаю устройство
delay(50);//жду 1 период
dimmer.setState(OFF);//выключаю устройство
delay(50);//жду 1 период

Или у меня с утра что-то клинит, или период сети ~220в все-таки - 20 мсек. Тогда откуда взялся  "delay(50);//жду 1 период" ?

Кроме того, в реальной сети далеко не "точно-точно" 50 Гц. Этот параметр немного, но гуляет. И что мы получим, когда ошибка накопится? Вывод: ищем на сайте (тут есть точно!) реализацию Брезенхема и детектор перехода напряжения через ноль. Объединяем и получаем искомый результат.

rkit
Онлайн
Зарегистрирован: 23.11.2016

Sonologist пишет:

реализацию Брезенхема

Этот бред вы от какого умника подхватили?

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

rkit пишет:

Этот бред вы от какого умника подхватили?

Ну непонятно, в чем бред? Надо бы раскрыть вопрос. Уточню, что с двигателями не работал, а вот ТЭН на 4500вт у меня отличным образом именно Брезенхемом (пропуском полупериодов) регулируется. Программную часть надыбал именно на нашем форуме. Детектор нуля - кажется тоже здесь кто-то выкладывал. 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

DetSimen пишет:

Заклинит насос. Не надо так. 

 

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

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Sonologist пишет:

Или у меня с утра что-то клинит, или период сети ~220в все-таки - 20 мсек. Тогда откуда взялся  "delay(50);//жду 1 период" ?

Кроме того, в реальной сети далеко не "точно-точно" 50 Гц. Этот параметр немного, но гуляет. И что мы получим, когда ошибка накопится? 

У вас с утра, а делал-то я всё ночью, когда дети уснули - тут немудрено было перепутать частоту со временем.

Не суть, 50 мсек насос работает, 50 отдыхает (это слышно по звуку, а если использовать штатный dimmer.setPower(50); , срезаной синусоиды не хватает, чтобы насос качнул хотя бы раз - он просто гудит), в библиотеке и в самом модуле уже есть детекция нуля, так что насос на 50% мощности работает. Но не суть - меня интересует как штатным способом (библиотека к модулю же прилагается не просто так) снизить мощность не срезая полупериоды.

Если накопится ошибка, то на 99 циклов работы насоса получим 101 цикл простоя, то есть, реальная мощность составит не 50%, а 49.5% - не критично.

Sonologist пишет:

Вывод: ищем на сайте (тут есть точно!) реализацию Брезенхема и детектор перехода напряжения через ноль. Объединяем и получаем искомый результат.

 

Реализацию Брезенхема нашёл - алгоритм простейший, но сам я бы не догадался до такого.

Если найду детектор перехода напряжения через ноль, то и библиотека RBDDimmer.h не нужна будет?

P.S. Я так понимаю, когда кто-то производит устройство (диммер) и пишет для него библиотеку, в этой библиотеке должно быть всё реализовано - это же логично.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Sonologist пишет:

rkit пишет:

Этот бред вы от какого умника подхватили?

Ну непонятно, в чем бред? 

Да это ж rkit, не обращайте на него внимания.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

andreykrasnodar пишет:

Реализацию Брезенхема нашёл - алгоритм простейший, но сам я бы не догадался до такого.

Если найду детектор перехода напряжения через ноль, то и библиотека RBDDimmer.h не нужна будет?

Да библиотка будет не нужна. Кстати глянул в ее код... Ну, скажем, далека она от совершенства. Лучше выкинте.

А детектор перехода через 0 это просто сделать на внешнем прерывании. У вас какая ардуина?

rkit
Онлайн
Зарегистрирован: 23.11.2016

Sonologist пишет:

rkit пишет:

Этот бред вы от какого умника подхватили?

Ну непонятно, в чем бред? Надо бы раскрыть вопрос. Уточню, что с двигателями не работал, а вот ТЭН на 4500вт у меня отличным образом именно Брезенхемом (пропуском полупериодов) регулируется. Программную часть надыбал именно на нашем форуме. Детектор нуля - кажется тоже здесь кто-то выкладывал. 

Алгоритм для оптимизации производительности, совершенно не играющей роли в данной задаче. Пустая трата времени программиста. Из пушки по воробьям.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

rkit пишет:

Алгоритм для оптимизации производительности, совершенно не играющей роли в данной задаче.

Ну, вообще, это алгоритм рисования линии по пикселам изначально.

Цитата:
Пустая трата времени программиста. Из пушки по воробьям.

Ну и как же надо?

rkit
Онлайн
Зарегистрирован: 23.11.2016

Алгоритм ОПТИМИЗИРОВАННОГО рисования линии. Читай википедию до конца, раз уж начал. В случае с диммером достаточно деления с округлением. У тебя 16 миллионов тактов в секунду есть.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

asam пишет:

Да библиотка будет не нужна. Кстати глянул в ее код... Ну, скажем, далека она от совершенства. Лучше выкинте.

А детектор перехода через 0 это просто сделать на внешнем прерывании. У вас какая ардуина?

Никогда не имел дело с написанием своего серьёзного на ардуино, только подключал библиотеки, брал нужную функцию и выводил на экран/в порт/мигал лампочками. А тут прям своя детекция нуля...

У меня arduino nano v3, аппаратное прерывание на 2 пине.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

rkit пишет:

Алгоритм ОПТИМИЗИРОВАННОГО рисования линии. Читай википедию до конца, раз уж начал. В случае с диммером достаточно деления с округлением. У тебя 16 миллионов тактов в секунду есть.

Ну,  приведи код, или изложи алгоритм,  хотя бы. 

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

andreykrasnodar пишет:

А тут прям своя детекция нуля...

Тоже ничего странного и сложного. Если есть желание - киньте письмо (хоть пустое) на bma280156@mail. Пришлю схемы и скетчи. Всё нормально работает (по крайней мере, на моих ТЭНах). Хотя вообще-то  для регулирования работы движка в Вашем случае (мне так представляется) достаточно ему давать периодически пинка. То есть, при здравом рассуждении и привязываться к переходу через ноль не очень-то надо. Действительно, можно с нужной периодичности открывать управляющий симистор. Тут и диммер-то, как таковой, ни к чему: ардуина, мос3041 (или 3061), симистор соответствующей мощности и снабберная цепь из резистора и конденсатора. И всё. Другой вопрос, что параметры этой периодичности надо подобрать, чтоб двигатель трезвон не выдавал, но это вопрос второй (кстати, программный).  Щас меня запинают, но "я художник, мне так видится". :)

Гриша
Offline
Зарегистрирован: 27.04.2014

andreykrasnodar пишет:

Скачал, подключил RBDdimmer.h, полез в документацию и с удивлением обнаружил, что для диммирования есть одна функция:

dimmer.setPower(n); // где n принимает значения от 0 до 100
Но эта функция именно срезает часть синусоиды, мне же необходимо часть пропускать.
Как это реализовать на  RBDdimmer.h?
 

Вот таким способом я снизил мощность насоса на 50%, но это именно костыль. Как сделать по уму?

если ответить только на выделенный фрагмент... так же как я на коврике :) 

т.е. ставим потенциометр, делаем ему:

int val = analogRead(0);

  val = map(val, 0, 1023, 0, 100);

а потом извращаемся с (MOC3061-M MOC3062-M MOC3063-M MOC3162-M MOC3163-M) 

 и оно будет убирать полупериоды (т.к. есть детектор нуля). Если синхронизоваться - достаточно точно, а если нет то +- полупериод. 

есть 2 варианта открывать МОС: импульсами (правильно но думать нужно, фазировать) или тупо как светодиодом (не правильно) но работает и ничего с ней не случится. 

Это просто вариант, я не настаиваю или не правильно понял задачу.

 

а исчЁ есть 555й тамер, подбираем частоту, а управляем скважностью (где-то попадались готовые платки) и это на МОСхххх с детектором нуля и ардуинку на синюю изоленту :))) но это не интересно. 

Sonologist пишет:

Хотя вообще-то  для регулирования работы движка в Вашем случае (мне так представляется) достаточно ему давать периодически пинка. 

чего я там выше писал - это для лягушки!!!! 

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

Гриша пишет:

Это просто вариант, я не настаиваю или не правильно понял задачу.

 

Мне тоже так показалось. Один вопрос: ежели движок достаточно мощный, то возможно мигание лампочек на его фазе из-за просадки.

Гриша
Offline
Зарегистрирован: 27.04.2014

Sonologist пишет:

Мне тоже так показалось. Один вопрос: ежели движок достаточно мощный, то возможно мигание лампочек на его фазе из-за просадки.

я про вибрациаонный -писал, для мотора с конденсатором я отдавал в перемотку движок на 3 фазы (220) его переобвязали + купил китайский частотник

 

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

andreykrasnodar пишет:

электродвигатель тянет поршень вверх, затем пружина возвращает поршень обратно. Не суть - главное пропускать периоды для уменьшения мощности.

Миль пардон (пропустил). Это что, насос "Малыш"? Тогда нафик все эти диммеры. Как уже сказано, периодически включать и выключать его. И всё, только подобрать периодичность включения.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Товарищи, у меня уже есть диммер https://aliexpress.ru/item/32802025086.html , который, судя по описанию, может:

Димминг может быть достигнут путём модуляции по скачкам импульсов (англ. PSM). С PSM:

  • Способ 1. Один или более циклов (синусоидального сигналапередаются на нагрузкуа передача последующих одного или нескольких циклов блокируется.
  • Способ 2. Частичная передача синусоиды каждой волны на нагрузку.

 

Гриша
Offline
Зарегистрирован: 27.04.2014

вот и не парьте мозг, если это не мотор, а электромагнитный - самое оно. 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Sonologist пишет:

Миль пардон (пропустил). Это что, насос "Малыш"? Тогда нафик все эти диммеры. Как уже сказано, периодически включать и выключать его. И всё, только подобрать периодичность включения.

Де нада. Это Ulka EX-5 (EP-5), качающая воду до 15 бар. Мощность 48 Вт.

Вопрос и был - как используя именно RBDDimmer.h включать/выключать, обеспечив снижение количества тактов в секунду с 50 до 49,48, ... 2,1 в секунду. Может, параметр какой есть. И пока я додумался лишь до

dimmer.setState(ON);//включаю устройство
delay(20);//жду 1 период
dimmer.setState(OFF);//выключаю устройство
delay(20);//жду 1 период

для снижения потока воды в 2 раза.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Ну как и ожидалось, кроме раскидывания польцев rkit не способен.

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



//Zerro crossing подключен к D2
#define TRIAC_PIN 5  // Dimmer
#define AC_DELAY 13
#define REG_MAX (100)   //количество уровней регулировки (2-127)
volatile uint8_t gACdelay_cnt;
volatile signed short gRegError = REG_MAX / 2;
volatile unsigned short gPowerPercent=0;    //текущий уровень мощности  0- REG_MAX
/*
   Установка уровня мощности
    Level - 0- REG_MAX
*/
void  SetNewPLevel(uint8_t Level)
{
  if (Level>REG_MAX) Level = REG_MAX;
  cli();
  gRegError = REG_MAX / 2;
  gPowerPercent = Level;
  sei();
}

void do_bresenham()
{
  gRegError = gRegError - gPowerPercent;
  if (gRegError <= 0)
  {
    gRegError = gRegError + REG_MAX;
    digitalWrite(TRIAC_PIN, HIGH); //SwitchOn();
  }
  else
  {
    digitalWrite(TRIAC_PIN, LOW); //SwitchOff();
  }
}
uint8_t inline readACpin()
{
  return PIND & _BV(PD2);
}

ISR(INT0_vect)
{
  for (uint8_t cnt = 0; cnt < 5; ++cnt)
  {
    if (readACpin()) return; //не реагируем на помехи
  }
  gACdelay_cnt = 0; //disable AC interrupts for AC_DELAY ms
  EIMSK &= ~_BV(INT0);//DisableAC_Int();
  do_bresenham();
}
// 1 mSec interrupts
ISR(TIMER0_COMPA_vect)
{
  gACdelay_cnt++;
  if (gACdelay_cnt >= AC_DELAY)
  {
    EIMSK |= _BV(INT0);//EnableAC_Int();
  }
  //   do_encoder();
  //  if (gStartKeyScan) do_button();           //check and de-bounce button
}

void setup() {

  pinMode(TRIAC_PIN, OUTPUT);
  pinMode(2, INPUT);
  EICRA = 2;  //Falling endge interrupt
  EIMSK |= _BV(INT0);//EnableAC_Int();
  OCR0A = 0xAF;  //1ms прерыания
  TIMSK0 |= _BV(OCIE0A);
}

uint8_t i;
void loop() {
  i++;
  if(i>REG_MAX) i=0;
  SetNewPLevel(i);
  delay(3000);

}

 

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

Судя по просмотру ссылки на Ulka EX-5 (бегло, по диагонали) - это вибрационный насос. "Малыш" из той же породы. То есть, обычный соленоид, а что он дергает (плунжер, шторку, шток...) - не суть важно. В смысле насоса его можно и Вашим диммером руководить и более простыми устройствами, выполняющими ту же функцию. Результат (подача жидкости) будет один и тот же. Так что, выбираем наиболее простой (для Вас) вариант и применяем. При этом совсем необязательно привязываться именно к 1 периоду. Мощность никакая, влиять на сеть не будет. Значит можно вообще для 50% производительности включать и выключать его хоть раз в секунду, хоть в две. При этом даже точность повысится :)

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

asam пишет:

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

Во, у меня практически полная аналогия. Так что, курочим под себя этот код и пользуем.

PS: Пардон, строчка кода какого-то впихнулась, а убрать не могу.

b707
Offline
Зарегистрирован: 26.05.2017

Sonologist пишет:

строчка кода какого-то впихнулась. убрать не могу...

Самая левая кнопка в редакторе сообщения - "Источник" - позволяет непосредственно редактировать HTML-код сообщения.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Всем спасибо за участие. Возник у меня другой вопрос:

а если не использовать библиотеку вообще, могу ли я (я не могу, поэтому подскажите как) получить сигнал zero-cross на 2м пине и просто на управляющий пин отправлять один сигнал высокого уровня, 49 - низкого (2 высокого, 48 низкого и т.д.) и тем самым получать на выходе устройства 1, 2, 3... синусоиды в секунду вместо 50?

То есть,

power - значение от 0 до 100

low = 50 - power/2; //тут число пропусков (ноль, низкий сигнал)

high = power/2;  //тут число подач высокого сигнала

Ну будет регулировка с шагом в 2 процента - да и ладно.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020
void loop() {
  val=analogRead(reg); //читаю значение с потенциометра с пина reg
  DimmerPower = map(val,0,1023,0,100);
  DimmerPower = constrain(DimmerPower,0,100);  //получил мощность от 0 до 100
 
  if (DimmerPower > 0){
  dimmer.setPower(100);  
  dimmer.setState(ON);
  delay(20*DimmerPower);
  dimmer.setState(OFF);
  delay(2000-20*DimmerPower);
  } else {

  dimmer.setPower(0);  

  dimmer.setState(OFF);  
  }
}
 
Это костыль или нормальная реализация?
asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

andreykrasnodar пишет:

Всем спасибо за участие. Возник у меня другой вопрос:

а если не использовать библиотеку вообще, могу ли я (я не могу, поэтому подскажите как) получить сигнал zero-cross на 2м пине и просто на управляющий пин отправлять один сигнал высокого уровня, 49 - низкого (2 высокого, 48 низкого и т.д.) и тем самым получать на выходе устройства 1, 2, 3... синусоиды в секунду вместо 50?

 

так я же привел код который это делает. Причем распределяет пропуски равномерно по интервалу. Что не устраивает?

 

rkit
Онлайн
Зарегистрирован: 23.11.2016

asam пишет:

Ну,  приведи код, или изложи алгоритм,  хотя бы.

Серьезно?

пропуск_периода[n] = (n % (1 / скважность)) < 1

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

asam пишет:

//Zerro crossing подключен к D2
#define TRIAC_PIN 5  // Dimmer
#define AC_DELAY 13
#define REG_MAX (100)   //количество уровней регулировки (2-127)
volatile uint8_t gACdelay_cnt;
volatile signed short gRegError = REG_MAX / 2;
volatile unsigned short gPowerPercent=0;    //текущий уровень мощности  0- REG_MAX
/*
   Установка уровня мощности
    Level - 0- REG_MAX
*/
void  SetNewPLevel(uint8_t Level)
{
  if (Level>REG_MAX) Level = REG_MAX;
  cli();
  gRegError = REG_MAX / 2;
  gPowerPercent = Level;
  sei();
}

void do_bresenham()
{
  gRegError = gRegError - gPowerPercent;
  if (gRegError <= 0)
  {
    gRegError = gRegError + REG_MAX;
    digitalWrite(TRIAC_PIN, HIGH); //SwitchOn();
  }
  else
  {
    digitalWrite(TRIAC_PIN, LOW); //SwitchOff();
  }
}
uint8_t inline readACpin()
{
  return PIND & _BV(PD2);
}

ISR(INT0_vect)
{
  for (uint8_t cnt = 0; cnt < 5; ++cnt)
  {
    if (readACpin()) return; //не реагируем на помехи
  }
  gACdelay_cnt = 0; //disable AC interrupts for AC_DELAY ms
  EIMSK &= ~_BV(INT0);//DisableAC_Int();
  do_bresenham();
}
// 1 mSec interrupts
ISR(TIMER0_COMPA_vect)
{
  gACdelay_cnt++;
  if (gACdelay_cnt >= AC_DELAY)
  {
    EIMSK |= _BV(INT0);//EnableAC_Int();
  }
  //   do_encoder();
  //  if (gStartKeyScan) do_button();           //check and de-bounce button
}

void setup() {

  pinMode(TRIAC_PIN, OUTPUT);
  pinMode(2, INPUT);
  EICRA = 2;  //Falling endge interrupt
  EIMSK |= _BV(INT0);//EnableAC_Int();
  OCR0A = 0xAF;  //1ms прерыания
  TIMSK0 |= _BV(OCIE0A);
}

uint8_t i;
void loop() {
  i++;
  if(i>REG_MAX) i=0;
  SetNewPLevel(i);
  delay(3000);

}

 

Дело в том, что такой сложный код мне вообще непонятен. Скажите, например, где здесь получение сигнала о пересечении нуля?

Komandir
Offline
Зарегистрирован: 18.08.2018

В прерывании ...

Гриша
Offline
Зарегистрирован: 27.04.2014

Komandir пишет:

В прерывании ...

ТС же сказал - сложно...

ответ в строке 1 кода или 64... 

b707
Offline
Зарегистрирован: 26.05.2017

andreykrasnodar пишет:

Скажите, например, где здесь получение сигнала о пересечении нуля?

строки 39-48

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

rkit пишет:

 

Серьезно?

пропуск_периода[n] = (n % (1 / скважность)) < 1

И что это за бред? Скважность может быть от 1 до бесконечности. Т.е при любой скважности больше 1 выражение 1/скважность в целочисленной арифметике дает 0 и в (n % (1 / скважность)) мы получаем деление на 0. А для плавучки оператор % не применим.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

andreykrasnodar пишет:

 

Дело в том, что такой сложный код мне вообще непонятен. Скажите, например, где здесь получение сигнала о пересечении нуля?

Ну непонятен и ладно. Просто бери и пользуйся. Пин к которому подключен диммер (симистр) определяется в строке 2, а выход детектора нуля (ZC) должен быть подключен к D2

функция SetNewPLevel() задает процент мощности.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Скетч выше компилируется, загружается в Arduino ... и ничего не происходит.

Pni Z-C оставил вторым, переназначил только TRIAC_PIN на 4 и в void loop() { прописал SetNewPLevel(50);

Не работает... Видимо, какая-то команда для моего диммера пропущена... Например, в оригинальной библиотеке была инициализация портов, таймера и внешнего прерывания от zero-cross:

dimmer.begin(NORMAL_MODE, OFF);

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

в зависимости от схемы модуля может потребоваться поменять строки (обе сразу)

36 на return !(PIND & _BV(PD2)); 
65 на  EICRA = 3;

 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

asam пишет:

в зависимости от схемы модуля может потребоваться поменять строки (обе сразу)

36 на return !(PIND & _BV(PD2)); 
65 на  EICRA = 3;

 

 

Спасибо. Поменял, но полная тишина.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Удивительно вот что: через секунд так 30 после включения без наличия фазы и нуля на диммере, его индикатор включается как при 100% мощности и так дальше горит.

При наличии 220 вольт на входе в плату диммера, он так и не заводится.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

andreykrasnodar пишет:

Удивительно вот что: через секунд так 30 после включения без наличия фазы и нуля на диммере, его индикатор включается как при 100% мощности и так дальше горит.

При наличии 220 вольт на входе в плату диммера, он так и не заводится.

А схема диммера есть?

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

asam пишет:

А схема диммера есть?

Схемы не нашёл, есть только фото с компонентами, схема расположения компонентов с размерами и фото печатной платы.

https://forum.arduino.ua/img/members/538/RobotRyn.png

http://m1.is.jc9.ru/static/kn1/3236/products/description/a4/22/a422f2175...

https://fastnvr.ru/image/cache/data/a93/Mod-Dimmer-5A-1L-3-600x600.jpg

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Почему я пишу, что код не понимаю, а не тупо использую то, что непонятно?

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

Пробую разобрать почти построчно:

 

#define TRIAC_PIN 5  // Определяем 5й пин как TRIAC_PIN, дальше будем использовать значение TRIAC_PIN
#define AC_DELAY 13  // AC_DELAY значение 13 (зачем - большой вопрос, т.к. 13 мсек по-моему вникуда) 
#define REG_MAX (100)   // REG_MAX 100 (зачем в скобках - непонятно, но просто примем значение 100)
volatile uint8_t gACdelay_cnt;  // необычная переменная типа byte - она в ОЗУ и может быть чем-либо другим изменена
volatile signed short gRegError = REG_MAX / 2; //тоже в ОЗУ, что за тип signed short, я не знаю.
volatile unsigned short gPowerPercent=0;    // ещё переменная, объявляем её равной нулю
/*
   Установка уровня мощности
    Level - 0- REG_MAX
*/
void  SetNewPLevel(uint8_t Level)  //Функция установки мощности Level
{
  if (Level>REG_MAX) Level = REG_MAX;  //если Level > 100, то Level = 100
  cli();    //наверное, запрет всех прерываний
  gRegError = REG_MAX / 2;    // это 2 строчки - обычные математические
  gPowerPercent = Level;     // выражения...
  sei();  // я так онимаю, прерывания разрешаем.
}

void do_bresenham()
// процедура Брезенхема, особо расписывать не буду, работает по известному алгоритму
// распределяя так логические 0 и 1 на TRIAC_PIN, чтобы двигатель тарахтел более равномерно
// одного не пойму в этой процедуре - а где же задержка? Буду надеяться, она встретится в цикле при вызове процедуры
{
  gRegError = gRegError - gPowerPercent;
  if (gRegError <= 0)
  {
    gRegError = gRegError + REG_MAX;
    digitalWrite(TRIAC_PIN, HIGH); //SwitchOn();
  }
  else
  {
    digitalWrite(TRIAC_PIN, LOW); //SwitchOff();
  }
}

// а эти 2 строчки мне вообще непонятны...
uint8_t inline readACpin()
{
  return PIND & _BV(PD2);
}
//в прерываниях я полный ноль, что здесь написано, зачем цикл от 0 до 4,
//и как этот код защищает от помех,
//мне непонятно...
ISR(INT0_vect)
{
  for (uint8_t cnt = 0; cnt < 5; ++cnt)
  {
    if (readACpin()) return; //не реагируем на помехи
  }
  gACdelay_cnt = 0; //disable AC interrupts for AC_DELAY ms
  EIMSK &= ~_BV(INT0);//DisableAC_Int();
  do_bresenham();
}
// код ниже, судя по всему, это своеобразный таймер на 1 секунду,
// который не "вешает" процессор
ISR(TIMER0_COMPA_vect)
{
  gACdelay_cnt++;  //инкремент
  if (gACdelay_cnt >= AC_DELAY) // наверное, проверка, прошла ли 1 милисекунда
  {
    EIMSK |= _BV(INT0);//EnableAC_Int(); // этот код за гранью моего понимания
  }
  //   do_encoder();
  //  if (gStartKeyScan) do_button();           //check and de-bounce button
}

void setup() {  //установки программы
  pinMode(TRIAC_PIN, OUTPUT);  //TRIAC_PIN (5й пин) будет выходным
  pinMode(2, INPUT);  // а 2й - входным, ардуино нано на нем сможет читать информацию о пересечении нуля
  EICRA = 2;  //мне непонятно, зачем
  EIMSK |= _BV(INT0);//EnableAC_Int();  //аналогично
  OCR0A = 0xAF;  //1ms прерыания - так сказано в комментарии
  TIMSK0 |= _BV(OCIE0A);  // набор букв какой-то
}

uint8_t i;   //я так понимаю, тут просто объявили переменную. Почему здесь - не понимаю.
void loop() { //основной бесконечный цикл
  i++;   //инкремент
  if(i>REG_MAX) i=0;  //если i превысит 100, сброс i
  SetNewPLevel(i);  // есть процедура в самом начале - установить мощность. Сначала 1, потом 2, 3, 4...99,100,0,1
  delay(3000);  //задержка

}
Pyotr
Offline
Зарегистрирован: 12.03.2014

Мож пропустил... какая цель димировать или снижать мощность насоса?

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Снизить поток воды, в конечном итоге контролировать давление (там из-за "несжимаемости" воды не так всё просто, как кажется: нет линейных зависимостей и при работе насоса давление может долго держаться на отметке в 1 бар и за секунду резко подняться до 9)

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

andreykrasnodar пишет:

Почему я пишу, что код не понимаю, а не тупо использую то, что непонятно?

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

Пробую разобрать почти построчно:

Что бы понять срабатывает ли переход через 0 надо настроить сериал на 115200, а после строки 40 поместить

Serial.print("i");


#define AC_DELAY 13  // AC_DELAY значение 13 (зачем - большой вопрос, т.к. 13 мсек по-моему вникуда) 
когда мы решили пропускать или нет данный период, до следующего можно не дергаться
При 50Гц период 20мс, при 60Гц - 16.3 

volatile signed short gRegError = REG_MAX / 2; //тоже в ОЗУ, что за тип signed short, я не знаю.
то же самое чт int8_t  -128:+127


  cli();    //наверное, запрет всех прерываний
да

  sei();  // я так онимаю, прерывания разрешаем.
да
}


//в прерываниях я полный ноль, что здесь написано, зачем цикл от 0 до 4,
//и как этот код защищает от помех,
//мне непонятно...
помехи, обычно, короткие, вот и читаем несколько раз, чтобы убедиться что не короткие

ISR(INT0_vect)
{
  for (uint8_t cnt = 0; cnt < 5; ++cnt)
  {
    if (readACpin()) return; //не реагируем на помехи
  }

// код ниже, судя по всему, это своеобразный таймер на 1 секунду,
на 1 милисекунду
// который не "вешает" процессор
ISR(TIMER0_COMPA_vect)
{
  gACdelay_cnt++;  //инкремент
  if (gACdelay_cnt >= AC_DELAY) // наверное, проверка, прошла ли 1 милисекунда
нет, проверяем не прошло ли 13 миллисекунд с прошлого пересечения 0, если нет, то ничего не делаем
  {
    EIMSK |= _BV(INT0);//EnableAC_Int(); // этот код за гранью моего понимания
разрешение прерываний от пина 2
  }

}

void setup() {  //установки программы
  pinMode(TRIAC_PIN, OUTPUT);  //TRIAC_PIN (5й пин) будет выходным
  pinMode(2, INPUT);  // а 2й - входным, ардуино нано на нем сможет читать информацию о пересечении нуля
  EICRA = 2;  //мне непонятно, зачем 
  EIMSK |= _BV(INT0);//EnableAC_Int();  //аналогично
настройка  прерываний от пина 2 (см даташит для деталей)
  OCR0A = 0xAF;  //1ms прерыания - так сказано в комментарии
  TIMSK0 |= _BV(OCIE0A);  // набор букв какой-то
(см даташит для деталей)

} uint8_t i; //я так понимаю, тут просто объявили переменную. Почему здесь - не понимаю. а где надо? void loop() { //основной бесконечный цикл i++; //инкремент if(i>REG_MAX) i=0; //если i превысит 100, сброс i SetNewPLevel(i); // есть процедура в самом начале - установить мощность. Сначала 1, потом 2, 3, 4...99,100,0,1 да delay(3000); //задержка }

 

SLKH
Offline
Зарегистрирован: 17.08.2015

andreykrasnodar пишет:

Снизить поток воды, в конечном итоге контролировать давление (там из-за "несжимаемости" воды не так всё просто, как кажется: нет линейных зависимостей и при работе насоса давление может долго держаться на отметке в 1 бар и за секунду резко подняться до 9)

есть такое слово "гидрофор"

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

asam, огромное спасибо. Половину кода уже понимаю. Почему устройство не работает, непонятно...

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

SLKH пишет:

есть такое слово "гидрофор"

Насос нужно включить на 100%, а при достижении небольшого давления постепенно снижать давление.

Упростим задачу: помните, в школе "в бассейн по одной трубе...". Вот представьте себе бассейн, в который мощным насосом вливают по кубометру воды в минуту, чтобы наполнить его до нужного значения. Минуту заливают, минуту ждут - такой насос. Понятное дело, это создаёт волны на поверхности. А задача набрать бассейн ровно до отметки 1.5 метра и поддерживать этот объём в течение часа (... а по второй трубе из бассейна уходит...).

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

asam пишет:

Что бы понять срабатывает ли переход через 0 надо настроить сериал на 115200, а после строки 40 поместить

Serial.print("i");

Спасибо. А куда писать

Serial.begin(115200);

Написал в 40 строке, надеюсь, так можно - не видит моя плата высокий сигнал на 2м пине (или модуль диммера её не шлёт).