Диммер, чертовщина на выходе MOC (имеется 2-х кан. осцил.)

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

ARV, прошу прощения за наглость. Но мне бы кусочек кода на C.

Интересует в первую очередь такой момент: 16-тибитный счетчик я уже задействовал. Остались только 8-мибитные. На них можно поднять ДУ ? Я имею ввиду интервалы времени для отслеживания кода посылки можно задать? Вопрос может и глупый, пока к написанию этой части кода не приступал. Но в посылках, насколько я помню, есть интервалы в микросекундах. С 8-мибитным счетчиком кажется к микросекунде не подобраться. Или я ошибаюсь? Вы как делали?
Нельзя всё знать, достаточно понимать.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

я делал на единственном 8-битном таймере тини13 одновременно и фазовое регулирование и прием RC5-кода :) однако, потом пришел к выводу, что занимался извращениями - если для фазового регулирования смысл в таймере еще есть, то прием кодов ДУ элементарно делается исключительно на программных задержках. код вы можете почерпнуть из моей статьи http://arv.radioliga.com/content/view/219/43/

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

Я обычно в случае, если нужно много таймеров настраиваю аппаратный таймер на частоту около 10кГц и в нём декрементирую счётчики программных таймеров. А в основном цикле программы проверяю эти счётчики на равенство нулю.
При этом прерывание выглядит так:

Код: Выделить всё

volatile unsigned char longDelayTimer1,timer1,timer2,timer3,timer4;

ISR(TIMER0_OVF0_vect)
{// 10 kHz
	if (timer1>0) timer1--;
	if (timer2>0) timer2--;
	*****
	if (longDelayTimer1>0) longDelayTimer1--;
	else {
		longDelayTimer1 = 255;
		if (timer3>0) timer3--;
		if (timer4>0) timer4--;
		***
	}
}
А main так:

Код: Выделить всё

int main()
{
	InitSystem();
	sei();
	while (1) {
		if (!timer1) {
			timer1 = 100;
			***
		}
		if (!timer2 && timer2on) {
			timer2 = 200;
			***
		}
		*****
	}
	return 0;
}
При этом в программе нет ни одного вызова delay_ms. Все переменные таймеров очень желательно делать однобайтными для ускорения работы прерывания, а в случае двухбайтных не забывать про неатомарность доступа к ним.
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Да... долго я отсутствовал... На работе был занят. Вернулся к проекту. И вот уже который день бьюсь над плавной регулировкой яркости С ПУЛЬТА ДУ. Она регулируется, но почему то "ступенчато". Не пойму где ошибка в программе.

Итак по порядку:

1. Составил таблицу временных задержек для регулировки мощности с шагом 1%
2. При нажатии кнопки происходит плавное включение/выключение (РАБОТАЕТ!!!)
3. Добавил пульт ДУ. Он непонятно чьего производства (был куплен за 250 руб взамен умершего пульта от ТВ тюнера Beholder). К тюнеру подошел. Правда пришлось "обучать" программу тюнера (это предусмотрено). Но всё работает. По ссылке, приведенной выше, видно что пульт для техники Samsung. Я предположил что работает он по протоколу NEC. Взял исходник от статьи "Некоторые протоколы ИК-пультов" для NEC протокола... Не заработало :(

Взялся за осциллограф. Оказалось что там не совсем NEC протокол... Т.е. единица и ноль кодируются как и в NEC протоколе:
Изображение
Только вот стартовая последовательность отличается по времени:
Untitled-2.jpg
(191.31 КБ) 341 скачивание
~4,5 мс вместо 9 мс. И нет последовательности повтора!!! Т.е. при удержании кнопки посылка отсылается постоянно. Интервал между посылками 44,8 мс, длинна самой посылки 61,6 мс.
DSC04576.JPG
(144.5 КБ) 419 скачиваний
В посылке 32 бита: "адрес"+"адрес"+"команда"+"инв. команда"
(это данные с осциллографа!!!)

Адрес передается не инвертированный. Но он нам собственно и не нужен. Команда согласно NEC протоколу. Пришлось править исходник. А именно стартовую последовательность.

4. Я выяснил коды нужных мне кнопок, "вставил" их в программу и сравниваю с переменной cmd. А в OCR1A записываю соответствующую задержку:

Код: Выделить всё

/*===== УВЕЛИЧЕНИЕ/УМЕНЬШЕНИЕ ЯРКОСТИ =====================*/

	   if (cmd == 0b11111000) {       // кнопка "Display" - увеличение яркости
          TCCR1B=0x02;
		  status++;
		  if (status >= 98) {
            TCCR1B=0x00;
		    status = 98;   
            PORTC.5 = 1;                // полностью включили
			}
          else {
		    OCR1A = nagruzka[status];   // увеличиваем яркость
		    delay_ms(delay_);
            }
		 }
         
       if (cmd == 0b11000000) {      // кнопка "Sleep" - уменьшение яркости
          TCCR1B=0x02;
		  status--;
		  if (status < 1) {
		    status = 0;                 // чтобы не уйти в минус
            PORTC.5 = 0;                // полностью выключили
            TCCR1B=0x00;
			}
          else {
		    OCR1A = nagruzka[status];   // уменьшаем яркость
		    delay_ms(delay_);
            }
		 }
Но вот незадача. При удержании кнопки яркость меняется, но очень странно. Медленно и как бы рывками что ли.

Т.е. где то в коде не порядок.

У меня есть предположение: Просто сравнивать с переменной cmd видно нельзя. Вводить флаг повтора? Но посылки то одинаковые!!!. Как быть?

Команду я сбрасываю только если ничего не приходит уже на пин. Т.е. Условие if (cmd == 0b11000000) { должно выполняться при удержании кнопки. Или нет??????
Получается оно выполняется с какими то задержками... или где то команда успевает обнулиться и условие перестает выполняться. Чего то я запутался.

Код: Выделить всё

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
        TCNT0=0xFA;                 //переинициировали таймер - отсчитывает 96 мкс
        tick++;                          //увеличили число тиков
        if (tick > 500) {              //если прошло более 48 мс (интервал
                                            // между посылками 44,8 мс)
          TCCR0=0x00;             //сбросили все к исходному состоянию
          TCNT0=0x00;
          tick = 0;                                                       
          start_cond = 0;
          //repeat_cond = 0;
          cmd = 0;
        }
Как в таком случае корректно команду обработать? Вроде всё правильно :(

код:
dimmer.c
(12.07 КБ) 395 скачиваний
Нельзя всё знать, достаточно понимать.
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Совсем никаких идей?
Нельзя всё знать, достаточно понимать.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

И ещё почему то ИНОГДА при плавном включении (от кнопки) проскакивает несколько морганий... то ли контроллер сбивается, то ли датчик нуля барахлит. Может в нем чего нибудь улучшить? Не особо усложняя конструкцию.

P.S. Вопрос по пульту ДУ остается открытым.
Нельзя всё знать, достаточно понимать.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Вот такая схема у меня получилась:
my_dimmer_final.jpg
(180.4 КБ) 537 скачиваний
У кого нибудь есть пример работы с DS1307 с помощью АППАРАТНОГО i2c ? А то во всех примерах программный используется.
Последний раз редактировалось mr_smit Вс ноя 21, 2010 16:10:46, всего редактировалось 1 раз.
Нельзя всё знать, достаточно понимать.
Родился
Сообщения: 3
Зарегистрирован: Чт фев 26, 2009 21:50:04
Откуда: Красноярск

Сообщение toxaml »

LS020 не подключишь к контроллеру на прямую. он 3х вольтовый.
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Уже подключил и РАБОТАЕТ!!!

Как раз только с LS020 это и можно сделать. Дисплеи на других контроллерах сгорают.

Схему посмотрите пожалуйста. Может чего улучшить можно? добавить?
Нельзя всё знать, достаточно понимать.
Прорезались зубы
Аватара пользователя
Сообщения: 219
Зарегистрирован: Вт сен 18, 2007 16:41:16
Откуда: Украина, г. Запорожье

Сообщение alex2103 »

по поводу ДУ непонятно...

Код: Выделить всё

	   if (cmd == 0b11111000) {       // кнопка "Display" - увеличение яркости
          TCCR1B=0x02;
		  status++;
		  if (status >= 98) {
            TCCR1B=0x00;
		    status = 98;   
            PORTC.5 = 1;                // полностью включили
			}
          else {
		    OCR1A = nagruzka[status];   // увеличиваем яркость
		    delay_ms(delay_);
            }
		 }
Получается что яркость устанавливается только после приема пачки команд а не во время приема?
Думаю строчку

Код: Выделить всё

OCR1A = nagruzka[status];
надо куда-то вынести в прерывание - пускай само обрабатывается. В основной программе оперировать только переменной status.

ПС: вернее вообще получается что свет включится только когда status >= 98
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

alex2103 писал(а):ПС: вернее вообще получается что свет включится только когда status >= 98
Нет. Я регулирую яркость от 1% до 99%. Крайние положения выставляю явно, т.е. PORTC.5 = 1 - 100% яркость. Чтобы симистор был полностью открыт. А пока status<98 OCR1A = nagruzka[status];


Переменной cmd присваивается код команды только после того как команда полностью принята.

Я принял за условие что при удержании кнопки переменная cmd всегда равна коду нажатой кнопки <-- может это не правильно???

Поэтому в основной программе и сравниваю cmd с заранее известным кодом кнопки. Т.е. пока команда не равна нулю (пока кнопку не отпустили) увеличивать переменную status и изменять значение OCR1A.

Просто я никак не пойму по какому условию мне фиксировать что кнопка удерживается нажатой???
Получается что

Код: Выделить всё

if (cmd == 0b11111000) {}
не подходит
Нельзя всё знать, достаточно понимать.
Прорезались зубы
Аватара пользователя
Сообщения: 219
Зарегистрирован: Вт сен 18, 2007 16:41:16
Откуда: Украина, г. Запорожье

Сообщение alex2103 »

Действительно...что-то я вчера недоглядел :oops:

cmd формируется в прерывании...почему бы тогда вместо

Код: Выделить всё

if (cmd == 0b11111000) {}
не сделать

Код: Выделить всё

while (cmd == 0b11111000) {}
Я вот тоже на днях займусь диммером. Специально даже пультик небольшой с RC5 прикупил на 8 кнопок :)
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Потому что

Код: Выделить всё

while (cmd == 0b11111000) {}
не работает. Пробовал :(
Нельзя всё знать, достаточно понимать.
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Я в отчаянии... :( Не понимаю почему не работает. Уже столько вечеров убил на это. Не регулируется плавно, хоть об стенку расшибись. :cry:
Нельзя всё знать, достаточно понимать.
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Итак, при нажатии на кнопку вкл/выкл: плавный старт, потом плавное отключение.

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

Я снял на видео как всё происходит: http://www.youtube.com/watch?v=7xy9u1OUq9s

И ещё, ИНОГДА, при плавном старте проскакивает мигание лампы. Иногда всё нормально. Иногда несколько миганий. Откуда берутся эти мигания не понятно. В видео, мигание на 6-ой секунде.
dimmer.c
(12.07 КБ) 360 скачиваний
Нельзя всё знать, достаточно понимать.
Прорезались зубы
Аватара пользователя
Сообщения: 219
Зарегистрирован: Вт сен 18, 2007 16:41:16
Откуда: Украина, г. Запорожье

Сообщение alex2103 »

Думаю это так ошибки приема команды от пульта влияют...ТСОП засвечивается мусором и прерывание возникает.
Я пока взял библиотечку от многоуважаемого ARV для работы с пультиком... Код уверенно распознает нажатие кнопок на пульте, но удержание не очень. Во время удержания мой пульт шлет команду полностью. теперь вот тоже думаю как удержание отрабатывать...
Контактная информация:
Мудрый кот
Аватара пользователя
Сообщения: 1833
Зарегистрирован: Вс окт 04, 2009 13:23:12
Откуда: н. новгород

Сообщение anatol378 »

mr_smit писал(а): Откуда берутся эти мигания не понятно.
dimmer.c
В программировании не силен, но смею предположить что не выполняются условия отсчета времени задержки включения, т.е. "плывет" начальное значение отсчета таймера (сбой привязки) или сбой таймера - вызванные прерываниями.
Лучше умному тупить, чем тупому умничать
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Пока победил это так:

Код: Выделить всё

bit button_up =0;
...
if ((cmd_1 + cmd_0) == 0xFF) {                                  //проверили правильность приема команды
                  button_up = no;
                  cmd = cmd_1;
                  }
...
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
        TCNT0=0xFA;                                                    //переинициировали таймер - отсчитывает 96 мкс
        tick++;                                                        //увеличили число тиков
        if (tick > 500) {                                              //если прошло более 48 мс
          button_up = yes;
          ...
        }
...
if (cmd == 0b11111000) {       // кнопка "Display" - увеличение яркости
          TCCR1B=0x02;
		  while (button_up == no) {
            status++;
		    if (status >= 98) {
              TCCR1B=0x00;
		      status = 98;   
              PORTC.5 = 1;                // полностью включили
			}
            else {
		      OCR1A = nagruzka[status];   // увеличиваем яркость
		      delay_ms(delay_);
            }
		  }
       }
       else if (cmd == 0b11000000) {      // кнопка "Sleep" - уменьшение яркости
          TCCR1B=0x02;
          while (button_up == no) {
		    status--;
		    if (status < 1) {
		      status = 0;                 // чтобы не уйти в минус
              PORTC.5 = 0;                // полностью выключили
              TCCR1B=0x00;
			}
            else {
		      OCR1A = nagruzka[status];   // уменьшаем яркость
		      delay_ms(delay_);
            }
		  }
       }
Т.е. если прошло более 48 мс и от TSOPа ничего не пришло, то значит кнопку отпустили button_up = yes; и увеличение яркости в цикле while (button_up == no) прекращается.

Теперь регулируется плавно. Но заметил такую особенность: если нажать кнопку уменьшения яркости, а потом через 0,5-1 или 2-3 сек нажать кнопку увеличения яркости, то яркость продолжает уменьшаться :(
Подождал. Дальше как надо регулируется.

Достала эта не стабильность :(((((
Нельзя всё знать, достаточно понимать.
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Попытался синхронизироваться по импульсам от ДУ. Т.е. по приходу команды выполнять действие. Как раз разница между посылками вроде и должна дать задержку на плавность:

Код: Выделить всё

...
        if (b_cnt == 32)  {                                                     //если приняли уже 4 байта
                 if ((cmd_1 + cmd_0) == 0xFF) {                                  //проверили правильность приема команды              
                  cmd = cmd_1;
                    if (cmd == 0b11111000) {      // кнопка "Display" - увеличение яркости
                     TCCR1B=0x02;
                     OCR1A = nagruzka[status];
                     status++;
                     if (status >= 98) {
                      TCCR1B=0x00;
                              status = 97;   
                      PORTC.5 = 1;                // полностью включили
                                 }
                    }
Нет эффекта. Так же ступенчато. Хоть об стену расшибись :cry:

Мой код то почти что рабочий. Думаю где то надо просто или прерывания отключать или ещё что. Но не хватает мозгов сообразить где.

как только люди яркость регулируют :dont_know:
Нельзя всё знать, достаточно понимать.
Мудрый кот
Аватара пользователя
Сообщения: 1833
Зарегистрирован: Вс окт 04, 2009 13:23:12
Откуда: н. новгород

Сообщение anatol378 »

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

Вернуться в «Микроконтроллеры и ПЛИС»