Как сдвинуть импульс?

John2015
Offline
Зарегистрирован: 02.02.2016

Добрый вечер.

Пытаюсь собрать схему плавного пуска электродвигателя,  с 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); 
}  

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Задержка в прерывании - это круто!

А зачем здесь вообще прерывание?

- заводите булеву переменную, индицирующую состояние входного сигнала,

- запоммнаете момент прихода фронта импульса в другой (long) переменной,

- запоминаете момент прихода спада импульса в третьей переменной.

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

Если Вы не будете пихать в код всякую гадость типа delay, цикл у Вас будет в доли мс, что при частоте 50 Гц обеспечивает явно избыточную точность.

roman2712@mail.ru
Offline
Зарегистрирован: 16.01.2014

Смотрите в сторону таймеров. TIMER2 к примеру.

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

John2015
Offline
Зарегистрирован: 02.02.2016

С буливой так я и не смог сделать

John2015
Offline
Зарегистрирован: 02.02.2016

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

Сделал два канала контроля нуля   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;// Выставляем яркость
  
   
}