Диммер ???

renoshnik
Offline
Зарегистрирован: 11.04.2013

Привожу часть программы

#define f_base 13000
unsigned int du = 0, du_OCR = f_base;

void setup() {   
//  ====================================================================
Serial.begin(57600);
//  ====================================================================
  DDRD =  B00011000;
  PORTD = B00100000;
    DDRB = B000010;
    PORTB = B000000;
//  TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
//  TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);       // mode 14 1110 = Fast Pwm to ICR1
//  TCCR1A = 0xC2;  TCCR1B = 0x19;
cli (); TCCR1A = 0; TCCR1B = 0; ICR1 = f_base; sei ();
    } 

void loop() { 
 if ((PIND&(1<<PIND5))==0) { soft_start(); }  
  }  
 
void soft_start() { cli(); TCCR1A = 0xC2; TCCR1B = 0x19; sei();
label:
  OCR1A = du_OCR; du_OCR = du_OCR-130; delay (25);  
  Serial.print(du_OCR,1);Serial.println(" stp "); 
if (du_OCR > 100 && (PIND&(1<<PIND5))==0){ goto label;}   

cli (); TCCR1A = 0; TCCR1B = 0; ICR1 = f_base; sei ();
  du_OCR = f_base;
  }  

проблема в том, что после подаче питания на ардуину и нажатии кнопки (пин 5) ШИМ не работает  sad  хотя в монитор идут

данные !?!?!
если несколько раз нажать "ресет" перед нажатием кнопки, тогда появляется сигнал на пин 9 ...

 

вопрос - где я косячу ???

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

да практически везде. Весь код - какое-то недоразумение.

Зачем в процедуре из пяти строк делать переход по метке? - нормально не можете написать?

По поводу "не работает" - вы нажимаете кнопку, таймер запускается. пулей пролетает Вашу процедуру soft_start и в строке 28 выключается. Оно будет работать только если держать кнопку или нажимать ее часто...

renoshnik
Offline
Зарегистрирован: 11.04.2013

b707 пишет:

да практически везде. Весь код - какое-то недоразумение.

Зачем в процедуре из пяти строк делать переход по метке? - нормально не можете написать?

По поводу "не работает" - вы нажимаете кнопку, таймер запускается. пулей пролетает Вашу процедуру soft_start и в строке 28 выключается. Оно будет работать только если держать кнопку или нажимать ее часто...

Про переход по метке сделаю другой пост, т.к. есть смысл такого решения...

Естественно я имел ввиду УДЕРЖАНИЕ нажатой кнопки !!!  Проблем в том, что цикл работает, в "сериал" идет информация с изменяющимися значениями, а вот таймер не запускается !!!  Нужно после подачи питания на плату несколько раз нажать ресет, вот после такой процедуры при удержании нажатой кнопки появляется ШИМ сигнал на 9 ножке ....

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

renoshnik пишет:

Про переход по метке сделаю другой пост, т.к. есть смысл такого решения...

Даже интересно стало :)

Morroc
Offline
Зарегистрирован: 24.10.2016

renoshnik пишет:

Естественно я имел ввиду УДЕРЖАНИЕ нажатой кнопки !!!  

Сделайте запуск таймера при нажатии и остановку при отпускании, не надо постоянно все там передергивать. Ну хотя... может и как то так можно. А зачем это условие du_OCR > 100 ? Проверьте тогда что при нажатой кнопке оно из цикла по label не вываливается, а если вываливается - объясните зачем.

Green
Offline
Зарегистрирован: 01.10.2015

ЕвгенийП пишет:

renoshnik пишет:

Про переход по метке сделаю другой пост, т.к. есть смысл такого решения...

Даже интересно стало :)

Дико присоединяюсь.

Morroc
Offline
Зарегистрирован: 24.10.2016

Может религия такая или..

Green
Offline
Зарегистрирован: 01.10.2015

Адвентисты гоу ту?

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

Morroc пишет:

 зачем это условие du_OCR > 100 ?

О. это я пропустил :) Сделать декремент цикла 130, а контроль окончания - du_OCR > 100 - это прям самому себе поставленный капкан...

Реношник, а может вы четче напишите, что вы такое пытаетесь родить? вроде как ШИм в одну строчку делается...

Morroc
Offline
Зарегистрирован: 24.10.2016

Когда писал на бейсике и asm тоже недоумевал как так без goto и зачем собственно так мучиться ? )

renoshnik
Offline
Зарегистрирован: 11.04.2013

Morroc пишет:

renoshnik пишет:

Естественно я имел ввиду УДЕРЖАНИЕ нажатой кнопки !!!  

Сделайте запуск таймера при нажатии и остановку при отпускании, не надо постоянно все там передергивать. Ну хотя... может и как то так можно. А зачем это условие du_OCR > 100 ? Проверьте тогда что при нажатой кнопке оно из цикла по label не вываливается, а если вываливается - объясните зачем.

А зачем это условие du_OCR > 100 ?  =  в цикле идет плавное заполнение ШИМ ....

Сделайте запуск таймера при нажатии и остановку при отпускании, не надо постоянно все там передергивать. Ну хотя...  =  вроди бы так и сделано, поканажата кнопка в цикле идет плавное заполненение ШИМ.

Проверьте тогда что при нажатой кнопке оно из цикла по label не вываливается  =  НЕ вываливается оно никуда...  при нажатой кнопке цикл РАБОТАЕТ - в "сериал" идут изменяющиеся значения !!! а вот ШИМ сигнал ОТСУТСТВУЕТ...  

Если после подачи питания на плату ардуины несколько раз нажать ресет, то тогда цикл начинает работать как записано в программе - и в сериал идет информация и есть изменяющийся ШИМ !!!!

 

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

Реношник, то есть вы настаиваете, что этот кривой код трогать не нужно, все работает верно, проблема только в РЕСЕТ?

нуну

renoshnik
Offline
Зарегистрирован: 11.04.2013

b707 пишет:

Реношник, то есть вы настаиваете, что этот кривой код трогать не нужно, все работает верно, проблема только в РЕСЕТ?

нуну

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

 

Morroc
Offline
Зарегистрирован: 24.10.2016

Вы осциллографом смотрели ? Потому как у меня запускается - при замыкании 5й ноги на землю появляется ШИМ на 9й ноге, сначала узкий импульс 0->1, потом он расширяется в течении ~2.5 сек и снова сбрасывается на узкий, повторяя цикл (частота ~1.225 кГц), если 5ю ногу отпустить - ШИМ отключается и запускается снова с 5й ноги безо всяких reset'ов. Так задумывалось ? Плата UNO обычная китайская с 328p мегой.

renoshnik
Offline
Зарегистрирован: 11.04.2013

Morroc пишет:

Вы осциллографом смотрели ? Потому как у меня запускается - при замыкании 5й ноги на землю появляется ШИМ на 9й ноге, сначала узкий импульс 0->1, потом он расширяется в течении ~2.5 сек и снова сбрасывается на узкий, повторяя цикл (частота ~1.225 кГц), если 5ю ногу отпустить - ШИМ отключается и запускается снова с 5й ноги безо всяких reset'ов. Так задумывалось ? Плата UNO обычная китайская с 328p мегой.

== да, смотрю осциллографом.

== алгоритм работы именно такой.

получается у меня проблемма с "железом" ...  хотя пробовал на двух ПроМини (от одного продавца) ...

Morroc
Offline
Зарегистрирован: 24.10.2016

какая то странная проблема, но получается так, попробую на nano вечером на всякий случай

renoshnik
Offline
Зарегистрирован: 11.04.2013

Morroc пишет:

какая то странная проблема, но получается так, попробую на nano вечером на всякий случай

В том-то и загвоздка...

Хотя если верить этому ->

b707 пишет:
Реношник, то есть вы настаиваете, что этот кривой код трогать не нужно, все работает верно, проблема только в РЕСЕТ?

нуну

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

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

renoshnik пишет:

вопрос - где я косячу ???

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


void loop() { 
   cli(); 
     TCCR1A = 0xC2; 
     TCCR1B = 0x19; 
   sei();
   
  do {
      OCR1A = du_OCR;  
      du_OCR = du_OCR-130; 
      delay (25);  
      Serial.print(du_OCR,1);
      Serial.println(" stp "); 
      } while (du_OCR > 100);   

   cli (); 
      TCCR1A = 0; 
      TCCR1B = 0; 
      ICR1 = f_base; 
   sei ();

   du_OCR = f_base;
}  
 

на первый взгляд ничего важного нет, что может помешать работать. Стоит только грамотно написать атомарные операции (с сохранением SREG):

void loop() { 
uint8_t sreg:
   sreg = SREG;
   cli(); 
     TCCR1A = 0xC2; 
     TCCR1B = 0x19; 
   SREG = sreg;
   
  do {
      OCR1A = du_OCR;  
      du_OCR = du_OCR-130; 
      delay (25);  
      Serial.print(du_OCR,1);
      Serial.println(" stp "); 
      } while (du_OCR > 100);   

   sreg = SREG;
   cli (); 
      TCCR1A = 0; 
      TCCR1B = 0; 
      ICR1 = f_base; 
   SREG = sreg;

   du_OCR = f_base;
}  

ну и OCR1A - 16-ти битный. Его бы тоже записывать атомарно.

Больше, пока, ничего не заметил.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

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

Использована обычная нанка.

#define f_base 13000
unsigned int du = 0, du_OCR = f_base;

void setup() {
  uint8_t sreg;
  Serial.begin(57600);
  pinMode (3, OUTPUT);
  pinMode (4, OUTPUT);
  pinMode (5, INPUT_PULLUP);

  pinMode (9, OUTPUT);
  digitalWrite (9, LOW);
  //  TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
  //  TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);       // mode 14 1110 = Fast Pwm to ICR1
  //  TCCR1A = 0xC2;  TCCR1B = 0x19;
  sreg = SREG;
  cli ();
  TCCR1A = 0;
  TCCR1B = 0;
  ICR1 = f_base;
  SREG = sreg;

}

void loop() {
uint8_t sreg;

  if (!digitalRead(5)) {
    TCCR1A = 0xC2;
    TCCR1B = 0x19;
    do {
      sreg = SREG;
      cli();
      OCR1A = du_OCR;
      SREG = sreg;
      du_OCR = du_OCR - 130;
      delay (25);
      Serial.print(du_OCR, 1);
      Serial.println(" stp ");
    } while (du_OCR > 100);

    TCCR1A = 0;
    TCCR1B = 0;

    du_OCR = f_base;
  }
}

Запускается по включению питания и никаких сбоев.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

Убрал смешной goto.

Он не смешной! ТС сказал, что

renoshnik пишет:

есть смысл такого решения...

И обещал объяснить его (смысл). Я вот всё жду.

renoshnik
Offline
Зарегистрирован: 11.04.2013

ЕвгенийП пишет:

wdrakula пишет:

Убрал смешной goto.

Он не смешной! ТС сказал, что

renoshnik пишет:

есть смысл такого решения...

И обещал объяснить его (смысл). Я вот всё жду.

 

Ок. раз обещал тогда объясняю....

Признаю. что поспешил с выводом т.к. при отладке из-за опипаста создалось ошибочное впечатление, что 

do { OCR1A = du_OCR; du_OCR = du_OCR-130; delay (25); } 
	while (du_OCR > 100 && (PIND&(1<<PIND5))==0);

работает не корректно. Когда прописал переход по метке, баг пропал.

Потом почистил код избегая копипастов и do { } while ( ); заняло свое место....

 

но с другой стороны переход по метке. для меня это ностальгия по студенчекому прошлому времен фортрана ...  :-)

 

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

Я тоже с децтва фортранец, но про гото забыл как страшный сон Дейкстры

renoshnik
Offline
Зарегистрирован: 11.04.2013

wdrakula пишет:

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

Использована обычная нанка.

#define f_base 13000
unsigned int du = 0, du_OCR = f_base;

void setup() {
  uint8_t sreg;
  Serial.begin(57600);
  pinMode (3, OUTPUT);
  pinMode (4, OUTPUT);
  pinMode (5, INPUT_PULLUP);

  pinMode (9, OUTPUT);
  digitalWrite (9, LOW);
  //  TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
  //  TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);       // mode 14 1110 = Fast Pwm to ICR1
  //  TCCR1A = 0xC2;  TCCR1B = 0x19;
  sreg = SREG;
  cli ();
  TCCR1A = 0;
  TCCR1B = 0;
  ICR1 = f_base;
  SREG = sreg;

}

void loop() {
uint8_t sreg;

  if (!digitalRead(5)) {
    TCCR1A = 0xC2;
    TCCR1B = 0x19;
    do {
      sreg = SREG;
      cli();
      OCR1A = du_OCR;
      SREG = sreg;
      du_OCR = du_OCR - 130;
      delay (25);
      Serial.print(du_OCR, 1);
      Serial.println(" stp ");
    } while (du_OCR > 100);

    TCCR1A = 0;
    TCCR1B = 0;

    du_OCR = f_base;
  }
}

Запускается по включению питания и никаких сбоев.

 

Видимо действительно у меня проблеммы с "железом"...

если закомментировать строки 28 и 46 то после загрузки программы осциллограф показывает нужную картинку... НО ... через какоето время (до одной минуты) частота увеличивается...

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

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

renoshnik пишет:

Видимо действительно у меня проблеммы с "железом"...

Плата случаем не wavgat?

renoshnik
Offline
Зарегистрирован: 11.04.2013

Jeka_M пишет:

renoshnik пишет:

Видимо действительно у меня проблеммы с "железом"...

Плата случаем не wavgat?

нет, классическая ProMini ..

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

renoshnik пишет:
ностальгия по студенчекому прошлому времен фортрана ...  :-)
Тогда и арифметический if нужен. 

renoshnik
Offline
Зарегистрирован: 11.04.2013
#define f_base 13000
unsigned int du_OCR = f_base;

void setup() {   
  DDRD =  B00011000;	PORTD = B00100000;
  DDRB = B000010;	    PORTB = B000000;
	TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;
    } 

void loop() { if ((PIND&(1<<PIND5))==0) { soft_start(); }  }  
 
void soft_start() { TCCR1A = 0xC2; TCCR1B = 0x19; du_OCR = f_base;
	do { OCR1A = du_OCR; du_OCR = du_OCR-130; delay (25); } 
	while (du_OCR > 100 && (PIND&(1<<PIND5))==0);
					TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;
	}  
  

на данный момент это самый удачный у меня вариант...

хотя иногда при нажатии кнопки ИНОГДА первый проход идет на случайной частоте но потом при удержании кнопки все происходит по алгоритму...

sadman41
Offline
Зарегистрирован: 19.10.2016

Вот у вас условие есть: du_ocr > 100. Что с ним будет при начальном значении 110 и декременте 130?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

renoshnik пишет:
ИНОГДА первый проход идет на случайной частоте но потом при удержании кнопки все происходит по алгоритму...

Я же тебе написал: как правильно.

ICR1 - 16битный регистр, ты пишешь туда число длиннее байта - 13000. Нужно писать атомарно.

renoshnik
Offline
Зарегистрирован: 11.04.2013

wdrakula пишет:

renoshnik пишет:
ИНОГДА первый проход идет на случайной частоте но потом при удержании кнопки все происходит по алгоритму...

Я же тебе написал: как правильно.

ICR1 - 16битный регистр, ты пишешь туда число длиннее байта - 13000. Нужно писать атомарно.

Если я правильно понял, то должно выглядеть так :

#define f_base 13000
unsigned int du_OCR = f_base;

void setup() {   
  uint8_t sreg;
  DDRD =  B00011000;	PORTD = B00100000;
  DDRB = B000010;	    PORTB = B000000;
  sreg = SREG;
  cli ();  
	TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;
  SREG = sreg;
    } 

void loop() { if ((PIND&(1<<PIND5))==0) { soft_start(); }  }  
 
void soft_start() { 
uint8_t sreg;
TCCR1A = 0xC2; TCCR1B = 0x19; du_OCR = f_base;
	do { 
      sreg = SREG;
      cli();	
	OCR1A = du_OCR; 
      SREG = sreg;	
	du_OCR = du_OCR-130; delay (25); } 
	while (du_OCR > 100 && (PIND&(1<<PIND5))==0);
					TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;
	}  
  

 

но баг остается...

https://youtu.be/7G9jbh4twKQ

renoshnik
Offline
Зарегистрирован: 11.04.2013

Похоже, что проблемма решена...

#define f_base 13000
volatile uint16_t du_OCR = f_base;

void setup() {   
  DDRD =  B00011000;	PORTD = B00100000;
  DDRB = B000010;	    PORTB = B000000;
  cli(); TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;	sei();
    } 

void loop() { if ((PIND&(1<<PIND5))==0) { soft_start(); }  }  
 
void soft_start() { 
cli(); 
	TCCR1A = 0xC2; TCCR1B = 0x19; du_OCR = f_base; ICR1 = f_base;   
	do { OCR1A = du_OCR; du_OCR = du_OCR-130; 
sei();
		delay (25);	} 
	while (du_OCR > 100 && (PIND&(1<<PIND5))==0);
cli(); TCCR1A = 0; TCCR1B = 0; ICR1 = f_base; sei();
	}  

добавление в строку 14 ,  ICR1 = f_base;  решило проблему

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

 

решил поэкспериментировать с атомарностью...

#define f_base 13000
volatile uint16_t du_OCR = f_base;

void setup() {   
  DDRD =  B00011000;  PORTD = B00100000;
  DDRB = B000010;     PORTB = B000000;
  TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;
    } 

void loop() { if ((PIND&(1<<PIND5))==0) { soft_start(); }  }  
 
void soft_start() { 
TCCR1A = 0xC2; TCCR1B = 0x19; du_OCR = f_base; ICR1 = f_base;   
  do { OCR1A = du_OCR; du_OCR = du_OCR-130; delay (25); } 
  while (du_OCR > 100 && (PIND&(1<<PIND5))==0);
TCCR1A = 0; TCCR1B = 0; ICR1 = f_base;
  } 
  

ухудшения работоспособности пока не заметил...