Как сдвинуть импульс?
- Войдите на сайт для отправки комментариев
Вс, 26/06/2016 - 16:10
Добрый вечер.
Пытаюсь собрать схему плавного пуска электродвигателя, с 220в проблем не возникает привязываешься к нулевой точке чистота 100 гец всё работает прекрасно, а вот с 380в на 3 фазы не получается.
Подскажите пожалуйста как можно сместить импульс на 3,3 мс и на 6,6 мс на разные выходы от управляющего сигнала чтобы всё работало от одного синхроимпульса?
Импульсы снимаю с фазы А

#include <avr/delay.h>
int AC_pin = 10; // Выход фазы A
int AC_pinB = 9; // Выход фазы B
int AC_pinC = 8; // Выход фазы C
volatile uint16_t dim;
uint8_t dimmer=0;// уровень димирования (0-255) 0 = max, 255 = min
void setup()
{
pinMode(AC_pin, OUTPUT);
pinMode(AC_pinB, OUTPUT);
pinMode(AC_pinC, OUTPUT);
attachInterrupt(0, FrontUp, RISING); //прерывание по изменению уровня с низкого на высокий
}
// Функция обработки прерывания на подъем
void FrontUp()
{
detachInterrupt(0);
_delay_us(dim+1000); // отсекаем лишнее
digitalWrite(AC_pin, HIGH); // включить симистор
pinMode(AC_pinB, OUTPUT);
pinMode(AC_pinC, OUTPUT);
_delay_us(20); // короткая пауза, чтобы обеспечить включение симистора
digitalWrite(AC_pin, LOW); // выключение симистора(он выключится когда полупериод достигнет нуля)
digitalWrite(AC_pinB, LOW);
digitalWrite(AC_pinC, LOW);
attachInterrupt(0, FrontDown, FALLING);
}
// Функция обработки прерывания на спад
void FrontDown()
{
detachInterrupt(0);
_delay_us(dim); // отсекаем лишнее
digitalWrite(AC_pin, HIGH); // включить симистор
digitalWrite(AC_pinB, HIGH);
digitalWrite(AC_pinC, HIGH);
_delay_us(20); // короткая пауза, чтобы обеспечить включение симистора
digitalWrite(AC_pin, LOW); // выключение симистора(он выключится
digitalWrite(AC_pinB, LOW);
digitalWrite(AC_pinC, LOW);
attachInterrupt(0, FrontUp, RISING);
}
void loop()
{
if(dimmer > 0) dimmer--; else dimmer=255; // пример уменьшения яркости лампы
dim=33*dimmer;
delay(50);
}
Задержка в прерывании - это круто!
А зачем здесь вообще прерывание?
- заводите булеву переменную, индицирующую состояние входного сигнала,
- запоммнаете момент прихода фронта импульса в другой (long) переменной,
- запоминаете момент прихода спада импульса в третьей переменной.
- теперь смотрите, прошло ли нужное время с каждого из записанных событий и соответственно выдаете сигнал в порт.
Если Вы не будете пихать в код всякую гадость типа delay, цикл у Вас будет в доли мс, что при частоте 50 Гц обеспечивает явно избыточную точность.
Смотрите в сторону таймеров. TIMER2 к примеру.
У вас получается что по прерываниею надо таймер обнулить и дождаться пока он дотикает до нужной задержки и вызовет прерывание, в котором уже и будет формироваться импульс.
С буливой так я и не смог сделать
Переделал схему на две фазы , для плавного пуска двигателя двух фаз достаточно.
Сделал два канала контроля нуля 0 и 1 , по отдельности код работает прекрасно
#include <avr/delay.h> int Faza_A = 9; // OUT фаза А volatile uint16_t dim_A; void setup() { pinMode(Faza_A, OUTPUT); attachInterrupt(0, in_Faza_A, RISING); //прерывание по изменению уровня с низкого на высокий } // Функция обработки прерывания на подъем void in_Faza_A() { detachInterrupt(0); _delay_us(dim_A); digitalWrite(Faza_A, HIGH); // включить симистор _delay_us(20); // короткая пауза, чтобы обеспечить включение симистора digitalWrite(Faza_A, LOW); // выключение симистора(он выключится когда полупериод достигнет нуля) attachInterrupt(0, in_Faza_A, FALLING); } void loop() { dim_A = 6000;// Выставляем яркость }Но когда я пытаюсь сделать на два канала у меня получается полный бардак чистоты сбиваются.
Я так полагаю из за этой функц _delay_us
Подскажите пожалуйста как можно решить эту проблему?
#include <avr/delay.h> int Faza_A = 9; // OUT фаза А int Faza_B = 10; // OUT фаза В volatile uint16_t dim_A; volatile uint16_t dim_B; void setup() { pinMode(Faza_A, OUTPUT); pinMode(Faza_B, OUTPUT); attachInterrupt(0, in_Faza_A, RISING); //прерывание по изменению уровня с низкого на высокий attachInterrupt(1, in_Faza_B, RISING); //прерывание по изменению уровня с низкого на высокий } // Функция обработки прерывания на подъем void in_Faza_A() { detachInterrupt(0); _delay_us(dim_A); digitalWrite(Faza_A, HIGH); // включить симистор _delay_us(20); // короткая пауза, чтобы обеспечить включение симистора digitalWrite(Faza_A, LOW); // выключение симистора(он выключится когда полупериод достигнет нуля) attachInterrupt(0, in_Faza_A, FALLING); } void in_Faza_B() { detachInterrupt(1); _delay_us(dim_B); digitalWrite(Faza_B, HIGH); _delay_us(20); digitalWrite(Faza_B, LOW); attachInterrupt(1, in_Faza_B, FALLING); } void loop() { dim_A = 8000;// Выставляем яркость dim_B = 8000;// Выставляем яркость }