Как считать 0-255-0 при длительном удержании кнопки?

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

Здравствуйте. Хочу регулировать яркость светодиода в фонаре при помощи только одной кнопки.

1. Кратковременное нажатие кнопки - включение/выключение
2. Длительное удержание кнопки (во включенном состоянии) - регулировка яркости "по кругу" (от нуля до полного, от полного до нуля и т.д.). Отпустили кнопку - остались на текущей яркости. Краткое нажатие - полностью выключили. Ну думаю понятно. Так вот. Контроллер Mega8. Кварц 8 МГц. Запускаю Timer2 -> Fast PWM -> Делитель 8

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

for (i=0;i<255;i++) {    //Плавно повышаем яркость
  OCR2++;
  delay_ms(20);
}
        
for (i=0;i<255;i++) {    //Плавно понижаем яркость
  OCR2--;
  delay_ms(20);
}
Собственно всё работает. Плавно разгорается, плавно гаснет. Тут понятно. Дальше сижу туплю. Как привязать всё это к кнопке??? Вкл/выкл понятно:

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

if (PINB.0 == 0) {
  delay_ms(40);
  if (PINB.0 == 0) {
    PORTB.3^=1;
  }
}
А как быть с долгим удержанием? Как его обработать??? Да ещё так чтобы при этом OCR2 по кругу гонять 0-255-0 ?
Реклама
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение YS »

Изменение яркости я бы запихал в main().

По прерыванию таймера проверял бы кнопку. Нажата кнопка - считаем. Если досчитали до какого-то порогового значения - значит, кнопку удерживают. Устанавливаем глобальный флаг изменения яркости, который проверяется в main(). Отжали кнопку - сбрасываем флаг. Если кнопку отжали, но до порогового значения мы досчитать не успели - вкл/выкл.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Реклама
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

Таймер 0 настроен на 1 мс. Таймер 2 генерирует ШИМ. Сделал так:

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

volatile unsigned int push = 0;
volatile bit dimmer = 0;
volatile bit on_off = 0;

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0x83;
if (PINB.0 == 0) {
  push++;
  if (push > 1000) {
    dimmer = 1;
	}
  else {
    on_off = 1;  
    }
  }
else {
  dimmer =0;
  on_off = 0;
  }
}

...

void main(void) {
...
while (1) {

  if (on_off) {
    TCCR2=0x00;  // выключили ШИМ
    PORTB.3^=1;  // вкл/выкл светодиода
    }
   while (dimmer) {
     dimmer_cicle();  // гоняем яркость по кругу
   }
 }
}
Чего то я запутался. Надо как то в dimmer_cicle(); изменять OCR2 по кругу 0-255-0. Не соображу как.
И как быть с дребезгом в прерывании if (PINB.0 == 0) { Задержку то туда не воткнешь.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение YS »

И как быть с дребезгом в прерывании if (PINB.0 == 0)
Поставить на кнопку конденсатор. А лучше триггер Шмитта с большим гистерезисом.
Надо как то в dimmer_cicle(); изменять OCR2 по кругу 0-255-0. Не соображу как.
Например, так:

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


void dimmer_circle(void)
{
  static unsigned char DimUp=1;

  if (DimUp)
  {
    ++OCR2A;

    if (OCR2A==255)
      DimUp=0;
  }
  else
  {
    --OCR2A;

    if (OCR2A==0)
      DimUp=1;
  }
}

Разница между теорией и практикой на практике гораздо больше, чем в теории.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Отследить короткое и долгое нажатие кнопки в фонаре. Как???

Сообщение poligon »

Весь код целиком в прерывании. В while (1) ничего нет. Должно отрабатываться кратковременное нажатие без проблем. Но четкого срабатывания нет. Нажимаешь - светодиод горит, отпускаешь - гаснет. Срабатывает через раз.

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

#define button PINB.0 

volatile bit long_push = 0;
volatile unsigned int cnt = 0;
volatile bit state = 0;

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
                       // Reinitialize Timer 0 value
  TCNT0=0x06;          // срабатывание каждые 2 мс
  
  if (!button) {
    cnt++;
    if (cnt>65534) {
      cnt=201;
      }
    }
  else {
    cnt=0;
    long_push=0;
    }

  if ((cnt > 25) && (cnt < 200)) {        // подавляем дребезг 50 мс
    if (state) {                          // и проверяем условие короткого нажатия
      OCR2=0x00;
      TCCR2=0x00;    // выключили ШИМ, остановили таймер   (выкл)
      state = 0;
      }
    else {
      OCR2=0xFF;
      TCCR2=0x6A;    // включили ШИМ на полную, запустили таймер    (вкл)
      state = 1;
      }
    }
    
  if (cnt > 200) {   // длинное нажатие
    long_push = 1;
    } 
}

...

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x03;
TCNT0=0x06;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: Fast PWM top=FFh
// OC2 output: Non-Inverted PWM
ASSR=0x00;
TCCR2=0x00;        // при старте всё выключено
TCNT2=0x00;
OCR2=0x00;         //

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Global enable interrupts
#asm("sei")
Последний раз редактировалось poligon Чт апр 14, 2011 17:31:21, всего редактировалось 1 раз.
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18657
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение ARV »

посмотрите, как сделал я: http://arv.radioliga.com/content/view/152/44/ в конце статьи описание алгоритма управления одной кнопкой всеми функциями, среди которых есть и увеличение/уменьшение, причем быстро и медленно. я назвал такой алгоритм управления "быстро побежал, проскочил мимо - медленно вернулся". многим понравилось...

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

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

Пока только вот это родить смог. Первое событие - кнопка нажата, второе - кнопку отжали

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

#define button PINB.0 

volatile bit enable = 1;
volatile unsigned int timer_count = 0;
...
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
                                    // Reinitialize Timer 0 value
  TCNT0=0xB2;                       // срабатывание каждые ~10 мс  
  timer_count++;                    // постоянно считаем 10 мс интервалы  
  if (timer_count>65534) {          // если насчитали больше 65535, то сбрасываем на 0    
    timer_count=0;                      
    } 
  
  if ((button == 0) && (enable == 1)) {   // если нажата кнопка и это первое срабатывание
	  timer_count = 0;                    // сбрасываем счетчик
	  enable = 0;                         // запрещаем сброс timer_count (случайный дребезг)
    }

  if (timer_count == 4) {                 // подавили дребезг 40 мс
    if (button == 0) {                    // если кнопка всё ещё нажата через 40 мс
	   // кнопка нажата                   // фиксируем что кнопку нажали
	  }
    }
	
  if (timer_count == 30) {                // если через 300 мс кнопка не нажата, то её отпустили
      if (button == 1) {
	    // кнопку отпустили
		enable = 1;
	    }
    }
}
Дальше пока никак
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

Как подождать 40 мс ???

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

#define button PINB.0 

volatile unsigned int timer_count = 0;

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
                                    // Reinitialize Timer 0 value
  TCNT0=0xB2;                       // срабатывание каждые ~10 мс    
  timer_count++;                    // постоянно считаем 10 мс интервалы  
  if (timer_count>65534) {          // если насчитали больше 65535, то сбрасываем на 0    
    timer_count=0;                      
    } 
  
  if (button == 0) {          // если на пине 0, то надо подождать 40 мс и опять проверить пин
                              // если через 40 мс там по прежнему 0, то кнопку нажали   
    }                         // НО КАК ПОДОЖДАТЬ 40 мс ???
}
Я это прекрасно понимаю что это 4 переполнения TCNT0. Но как??? Если сбросить при этом timer_count в ноль и ждать пока timer_count не станет больше 4, то при дребезге счет нарушится!!! Потому что на пине будет то 0 то 1
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение ChipKiller »

poligon писал(а):Я это прекрасно понимаю что это 4 переполнения TCNT0. Но как???
... а кто мешает завести еще одну переменную? :)
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

Как??? Где её инкрементировать, а где сбрасывать???
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение ChipKiller »

poligon писал(а):Как??? Где её инкрементировать, а где сбрасывать???
... мда ... как все запущено .... :))

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

static unsigned char press_rep;

... // есть нажатие
   press_rep+=1;
   if(press_rep>=4) {
   press_rep=4;
   // удержание кнопки - регулировка яркости "по кругу"  
   ...............
}
.... // 
    if (button == 1) {
       // кнопку отпустили
    press_rep=0;
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

В том то всё и дело что не работает такой код! Из за дребезга. Пробовал уже.
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение ChipKiller »

poligon писал(а):не работает такой код! Из за дребезга.
.. дребезг идет в момент нажатия/отпускания, а если идет удержание - причем тут дребезг ? правильно определите основные состояния и правила перехода между ними.....
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Как считать 0-255-0 при длительном удержании кнопки?

Сообщение poligon »

Если б мог - тему бы не создавал
Закрыто

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