Диммер, управляемый через Serial

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Добрый день!

Требуется создать диммер, управляющий яркостью лампочки. Яркость задается через com порт через сериал. Окончание числа - пробел (мне так удобнее). Схему собрал согласно статье http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circ.... Вот сама схемка: http://cdn.instructables.com/FQZ/NYV7/H8CVG9TK/FQZNYV7H8CVG9TK.LARGE.jpg Вот код прошитый в ардуинку (Due):

String Bi = "";
int AC_LOAD = 3;   
int dimming = 256;

void setup() {
Serial.begin(9600);
pinMode(AC_LOAD, OUTPUT);// Устанавливаем AC Load пин как вывод
attachInterrupt(2, ZC, RISING); 
}

void ZC(){
  int dimtime = (39*(256-dimming));    // Полное время     
  delayMicroseconds(dimtime);    // Ждем 
  digitalWrite(AC_LOAD, HIGH);   // Триак посылает сигнал зажечься
  delayMicroseconds(10);         // Триак ждет, для 50 Гц - 10мс 
  digitalWrite(AC_LOAD, LOW);    // Триак посылает сигнал потухнуть
}


void loop() {

 while (Serial.available() > 0)
  {
   char c = Serial.read();
   
      if (c == ' ')
      {
          Serial.println(Bi);
          dimming = Bi.toInt();  
          Bi = "";
      }
       else 
       {
         Bi += c;    
       } 
  }
}

Посылаю через сериал яркость и пробел: пару значений воспринимает нормально и регулирует яркость, а потом не принимает ничего, а лампочка ведет себя более чем странно: яркость постепенно падает, потом доходит до 0, затем снова на максимум и повторяется :( помогите, пожалуйста!

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Неужели никто не знает, где ошибка? (

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А что тут знать ?! Как по вашему. Вот поднялось прерывание. Процессор все бросил и начал его отрабатывать. А в нем задержка. А все другие прерывания ? Что с ними ? Что вычитывает процессор с последовательного интерфейса ? Ошибок нет ? Вы уверены ? 

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

т.е. из-за того, что каждый полуцикл в сети у меня включается функция прерывания, у меня не прочитывает данные с serial?  Если так, то подскажите, пожалуйста, альтернативу. С другой стороны, вычисления в прерывании простые, и задержки равны микросекундам, что не должно сильно портить ситуацию

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Я всего лишь предположил. И это не из-за того, что прерывание происходит 50 раз в секунду, а изза того , что в нем используется тупая задержка, пожирающая ресурсы процессора. Почитайте тему "мигаем без задержки", должно помочь. Для исключения зависания в прерываниях стоит воспользоваться прерыванием от таймера. Не знаю возможно ли это в ардуино, но атмел это может точно.

Кстати максимальное восьмибитное значение это 255, а не 256 :-)

com
Offline
Зарегистрирован: 06.09.2013

ChemDevil пишет:

...задержки равны микросекундам, что не должно сильно портить ситуацию

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

а альтернатива - никаких задержек в прерываниях.

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Переправил чуть код. Постарался избавиться от delay... но совсем не работает: лампочка горит постоянно. Подскажите, пожалуйста, в чем ошибка?

String Bi = "";
const int AC_LOAD = 3;   
int dimming = 255;
unsigned long previousMicros = 0; 

void setup() {
Serial.begin(9600);
pinMode(AC_LOAD, OUTPUT);// Устанавливаем AC Load пин как вывод
attachInterrupt(2, ZC, RISING); 
}

void ZC()
  { 
    unsigned long currentMicros = micros();
    previousMicros = currentMicros;
    int dimtime = (39*(255-dimming));    // Полное время
    while(currentMicros - previousMicros <= dimtime) {}
    previousMicros = currentMicros;
    digitalWrite(AC_LOAD, HIGH);// Триак посылает сигнал зажечься
    while(currentMicros - previousMicros < 10)// Триак ждет, для 50 Гц - 10мкс  
    {}
    digitalWrite(AC_LOAD, LOW);// Триак посылает сигнал потухнуть
  }

void loop() {
 while (Serial.available())
  {
   char c = Serial.read();
   
      if (c == ' ')
      {
          Serial.println(Bi);
          dimming = Bi.toInt();  
          Bi = "";
      }
       else 
       {
         Bi += c;    
       }    
  }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

 

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

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

В той статье действительно сравнение в теле цикла Loop...Попытался сделать так же, как описано там. High - это маркер, чтобы не повторять по многу одно и тоже до следующего прерывания... Вот код: на посылку из сериал яркость лампы не реагирует, хотя и воспринемает и отсылает обрптно.

String Bi = "";
int AC_LOAD = 3;   
int dimming = 255;
unsigned long currentMicros = micros();
unsigned long previousMicros = 0;
int High = 0;

void setup() {
Serial.begin(9600);
pinMode(AC_LOAD, OUTPUT);// Устанавливаем AC Load пин как вывод
attachInterrupt(2, ZC, RISING); 
}

void ZC()
{ 
High = 1;
previousMicros = currentMicros;
}

void loop() {
int dimtime = (39*(255-dimming));
if (High == 1 && (currentMicros - previousMicros) > dimtime)
{
  digitalWrite(AC_LOAD, HIGH);
  if ((currentMicros - previousMicros) > (dimtime+10))
  {
    digitalWrite(AC_LOAD, LOW);
    High = 0;
  }
}
while (Serial.available() > 0)
  {
   char c = Serial.read();
     if (c == ' ')
      {
          Serial.println(Bi);
          dimming = Bi.toInt();  
          Bi = "";
      }
       else 
       {
         Bi += c;    
       }      
  }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Добавьте перед 38 строкой serial.println(dimming,DEC) ; . Что получается ?

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Помимо Вi, выводится димминг. Точно такое же числовое значение, т.е. воспринимается

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

ВИЖУ !!! 

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

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

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Перед 22 строкой добавляем сurentMicros=micros(); кроме того переменную curentMicros можно вообще выбросить изменив ее на micros().

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

То же самое: 0 эмоций лампы

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Покажите исправленый скетч.

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014
String Bi = "";
int AC_LOAD = 3;   
int dimming = 255;
unsigned long currentMicros = micros();
unsigned long previousMicros = 0;
int High = 0;
	 
void setup() {
Serial.begin(9600);
pinMode(AC_LOAD, OUTPUT);// Устанавливаем AC Load пин как вывод
attachInterrupt(2, ZC, RISING); 
}
	 
void ZC()
{ 
High = 1;
previousMicros = currentMicros;
}
 
void loop() {
int dimtime = (39*(255-dimming));
currentMicros = micros();
if (High == 1 && (currentMicros - previousMicros) > dimtime)
{
  digitalWrite(AC_LOAD, HIGH);
  if ((currentMicros - previousMicros) > (dimtime+10))
  {
    digitalWrite(AC_LOAD, LOW);
    High = 0;
  	  }
}
while (Serial.available() > 0)
  {
   char c = Serial.read();
     if (c == ' ')
	     {
  Serial.println(Bi);
  dimming = Bi.toInt();
  Serial.println(dimming,DEC);  
  Bi = "";
    }
     else
     {
      Bi += c;    
     }      
  }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

В прерывании currentMicroc на micros то же попробуйте заменить.

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

То же самое: ничего не изменилось

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Давайте пожалуйста 22 строчку поменяем на вот так

if ((High == 1) && ((currentMicros - previousMicros) > dimtime))

Ну и для красоты расчет из 21 строчки я бы перенес в 41 оставив в 21 только объявление переменной.

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Опять не меняется яркость... есть подозрение, что я неудачник :(

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну тогда я тоже :-)

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

В любом случае, спасибо за помощь! Если найду как поправить - напишу сюда

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Хм..Схема впорядке: прошил старую программу: регулируется пару раз, потом старая проблема.

А вот закомментил строку - действительно не гаснет... Вот код 

String Bi = "";
int AC_LOAD = 3;   
int dimming = 255;
unsigned long currentMicros = micros();
unsigned long previousMicros = 0;
int High = 0;
	 
void setup() {
Serial.begin(9600);
pinMode(AC_LOAD, OUTPUT);// Устанавливаем AC Load пин как вывод
attachInterrupt(2, ZC, RISING); 
}
	 
void ZC()
{ 
High = 1;
previousMicros = currentMicros;
}
 
void loop() {
int dimtime = (39*(255-dimming)); 
if ((High == 1) && ((currentMicros - previousMicros) > dimtime))

{
//  digitalWrite(AC_LOAD, HIGH);
  if ((currentMicros - previousMicros) > (dimtime+10))
  {
    digitalWrite(AC_LOAD, LOW);
    High = 0;
  	  }
}
while (Serial.available() > 0)
  {
   char c = Serial.read();
     if (c == ' ')
	     {
  Serial.println(Bi);
  dimming = Bi.toInt();
  Serial.println(dimming,DEC);  
  Bi = ""; 
  }
     else
     {
      Bi += c;    
     }      
  }
}	  

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ешкин дрын... где 

currentMicros = micros();

???

ChemDevil
ChemDevil аватар
Offline
Зарегистрирован: 30.03.2014

Извините, видимо не сохранил!

Вроде работает! Огромное вам спасибо!

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А всего лишь невнимательность :-)  Да со всеми бывает. Иной раз зациклишься на какой то мелочи и кукуешь.