Например TDA7294

Форум РадиоКот • Просмотр темы - Алгоритм преодоления дребезга контактов
Форум РадиоКот
Здесь можно немножко помяукать :)



Текущее время: Вт июн 02, 2020 15:17:52

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Форум закрыт Эта тема закрыта, Вы не можете редактировать и оставлять сообщения в ней.  [ Сообщений: 11 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Сб июн 18, 2011 22:00:35 
Родился

Зарегистрирован: Сб июн 18, 2011 21:19:47
Сообщений: 5
Рейтинг сообщения: 0
Добрый День!
Это мое первое сообщение на этом форуме, прошу не пинать :?

Подскажите пожалуйста алгоритм преодаления дребезга контактов
1) с исключением повтора нажатия кнопки
2) без использования задрежки

в кратце о схеме
на одном входе atmega8 речезе АЦП подключено 10 кнопок, через резистры разных номиналов происходит деление напряжения.

алгоритм работы такой
1) настроено прерывание по изменению АЦП
2) если оно входит в заданный диапазон значений, то переменной присваивается номер нажатой кнопки (Key)
3) если этот номер повторяется в течении 100 преобразований то значит дребезга нет
4) вызываю функцию соответсвующей нажатой кнопке (функция тригерная - первый заход один результат, второй другой)
5) ...


вот тут и начинается проблема функия вызывается много раз

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


Код:

  //защита от дребезга и не только. если нажата какая-нибудь кнопка
  //сравниваем совпадают ли текущее состояние и предыдущее
  //если совпадают - проверяем счетчик comp, если нет обнуляем его
  //кнопка считается нажатой если она удерживается в течении 100
 
  if (Key)
  {
    if (Key == LastState)
    {
      if (comp > 100)
       {
         if (Key!=LastBut)
         { 
            Key_p=Key;       
            out_trig();  //  выполняю действия
            LastBut = Key; // переменную lastBut  сбрасываю каждую секунду
         }
         else
         {
         
         }
      }
      else
        comp++;
    }
    else   // сбрасываем счетчик
    {
      LastState = Key;
      comp = 0;
    }
  }
  else            // кнопка не нажата
  {
    comp = 0;
    KeyBuf = KEY_NULL;     
    LastState = KEY_NULL;
  }
  StartConvAdc();  //запускаем преобразование и выходим





ps
камень Atmega8
компилятор CodeVisionAVR


Последний раз редактировалось karimm Сб июн 18, 2011 22:05:44, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Сб июн 18, 2011 22:03:10 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 85
Рейтинг сообщений: 1704
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 15294
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
воспользуйтесь поиском по форуму: я давал ссылку на свои исходники, в котрых есть почти универсальный алгоритм работы с кнопками, воспользуйтесь. избежать повтора реакции можно только сравнением текущего кода кнопки с предыдущим, никакие таймеры тут не требуются

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


Вернуться наверх
 
JLCPCB, всего $2 за прототип печатной платы! Цвет - любой!

Отличное качество, подтвержденное более чем 600,000 пользователей! Более 10,000 заказов в день.

Зарегистрируйтесь и получите два купона по 5$ каждый:https://jlcpcb.com/quote

Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Сб июн 18, 2011 22:18:16 
Родился

Зарегистрирован: Сб июн 18, 2011 21:19:47
Сообщений: 5
Рейтинг сообщения: 0
с дребезгом более менее все ок, проблема с повтором

как обойтись без таймера?

если я нажимаю одну и туже кнопку два раза подряд то должна срабатывать соответсвенная функция
как отличить мое повторное нажатие от "задвоения" результата от АЦП?


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $88 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay
Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Сб июн 18, 2011 22:29:41 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 85
Рейтинг сообщений: 1704
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 15294
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
см. выше

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


Вернуться наверх
 
Новые контролллеры VIPerPLUS - практический вебинар 10 июня от ST

В программе вебинара - новые контроллеры VIPerPlus, расширяющие границы применения этих компонентов. Обзор их характеристик и преимуществ. Практика. Демонстрация испытаний из лаборатории ST. Пример моделирования в среде E-DesignSuite.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Сб июн 18, 2011 23:36:12 
Мудрый кот
Аватар пользователя

Карма: 21
Рейтинг сообщений: 142
Зарегистрирован: Сб фев 21, 2009 13:11:40
Сообщений: 1898
Откуда: Москва
Рейтинг сообщения: 0
karimm писал(а):
с дребезгом более менее все ок, проблема с повтором
как обойтись без таймера?
не смотрел исходники ARV, извиняюсь, если повторяю алгоритм. У меня было реализовано почти как у Вас, karimm, но я ввел флаг не секундного таймера, а флаг того, что кнопка уже нажата.
в прерывании, где Вы определяете нажатую кнопку, после проверки значения счетчика длительности нажатия (в Вашем коде это переменная comp), добавьте проверку этого флага.
Если флаг уже возведен, то значит функция, назначенная кнопке уже была выполнена и еще раз ее выполнять не нужно.
Если флаг не возведен, выполняете действие и возводите этот флаг.
В самом начале прерывания, если не нажата ни одна кнопка (у Вас же есть такое значение АЦП?), сбрасываете этот флаг.

Еще, т.к. у Вас много кнопок, а на каждую заводить счетчик comp нет смысла, и значения АЦП могут иногда скакать, я бы посоветовал Вам завести счетчик прерываний, а не счетчик для каждой кнопки, просто суммировать 128 значений АЦП подряд, а на 128ое прерывание делить значение суммы на 128 (= сдвиг на 7 разрядов вправо) и проверять в какой интервал попадает усредненное значение. Я так делал. Стабильных нажатий стало больше.

_________________
Ставим плюсы: )


Вернуться наверх
 
NanoPower от Maxim – ультранизкое потребление для «бесконечной» работы батареи!

Применяя компоненты NanoPower от Maxim Integrated с минимальным током покоя и минимальным собственным потреблением, вы сможете разработать устройство с максимально эффективной системой питания и продлить срок работы от батареи. Наша подборка статей и новостей по данной теме поможет вам в этом.

Читать статью>>
Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Вс июн 19, 2011 00:16:27 
Родился

Зарегистрирован: Сб июн 18, 2011 21:19:47
Сообщений: 5
Рейтинг сообщения: 0
Спасибо за идеюibiza11

вот что получилось, в шпроте работает хорошо :))

Код:
  if (Key)
  {
    if (Key == LastState)
    {
      if (comp > 100)
       {
         if (Key!=LastBut)
         {         
            out_trig();
            LastBut = Key;
            printf("LastBut %u ",LastBut)  ;
            printf("\n\r");           
         }
         else
         {
            printf("Povtor %u ",LastBut)  ;
            printf("\n\r");
         }
      }
      else
        comp++;
    }
    else
    {
      LastState = Key;
      comp = 0;
    }
  }
  else
  {
    LastBut =0;
    comp = 0;
    KeyBuf = KEY_NULL;
    LastState = KEY_NULL;
  }



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

вот как сделал определение нажатой кнопки

есть массив btn_arr в котором записаны расчетные значения ацп для каждой кнопки,
для того чотбы точно отловить нужную кнопку проверяю входит ли значение полученное с АЦП в диапазон х+rk
дальше все понятно

у меня в схеме параллельно кнопкам размещен конденсатор, и пока он разряжается/заряжается показания АЦП могут плавать,
по этому решил вылавливать поворные попадания в заданный диапазон


Код:
    AdcBuf = ADCH;
   
  if (AdcBuf < btn_arr[0]+rk)
    {
    Key = KEY_S0;
    #ifdef DEBUG
    printf("%u ",Key);
    printf("%u ",AdcBuf);
    printf("\n\r");
    #endif
    }
  else if  (AdcBuf < btn_arr[1]+rk)
      {
        Key = KEY_S1;
        #ifdef DEBUG
        printf("%u ",Key);
        printf("%u ",AdcBuf);
        printf("\n\r");
        #endif
      }
 /// отрезал лишние кнопки

  else if  (AdcBuf > btn_arr[16]+rk)
      {
        Key = KEY_NULL;
        #ifdef DEBUG
        //printf("%u ",Key);
        //printf("%u ",AdcBuf);
        //printf("\n\r");
        #endif
      }




как можно оптимизировать код, с многократно вложенным if ?


Вернуться наверх
 


Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Вс июн 19, 2011 00:40:19 
Мудрый кот
Аватар пользователя

Карма: 21
Рейтинг сообщений: 142
Зарегистрирован: Сб фев 21, 2009 13:11:40
Сообщений: 1898
Откуда: Москва
Рейтинг сообщения: 0
Ну вот смотрите: у вас программа работает так:
1) прерывание АЦП - выявление кода нажатой кнопки. (ну пусть 100 тактов)
2) устранение дребезга и выполнение действия (ну пусть 50 тактов)
3) возврат к пункту 1) (и так 100 раз).
итого за 100 прерываний АЦП - забито 15000 тактов процессорного времени

Я предложил (для простоты возьмем не 128, как я сказал, а 100 прерываний):
1) прерывание АЦП, суммирование результата (пусть 20 тактов)
2) 100 прерываний прошло? (пусть 20 тактов)
да) деление на 100 и выявление нажатой кнопки (пусть 300 тактов, в случае деления на 128 это около 10+100 тактов)
нет) выход
3) устранение дребезга если было выявление нажатой кнопки(если (Key!=KEY_NULL) ) (50 тактов)
итого за 100 прерываний АЦП - забито (20+20)*100+300+50=4350 тактов. :) выигрыш в 3 раза. и еще не нужны кондеры на входе АЦП)

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

_________________
Ставим плюсы: )


Вернуться наверх
 


Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Вт июн 21, 2011 03:04:34 
Опытный кот

Карма: 12
Рейтинг сообщений: 27
Зарегистрирован: Вс апр 10, 2011 02:24:06
Сообщений: 759
Откуда: г.Северодонецк
Рейтинг сообщения: 0
Если в Асме разбираешься, то посмотри, как сделано подавление, задержки и автоповтор.
Из основного цикла подпрограмма вызывается, проверяется код нажатой кнопки и выполняется действие. Для твоего случая нужно только изменить ПП предварительного ввода.


Вложения:
ПП кнопок.txt [1.47 KiB]
Скачиваний: 199

_________________
C0FFEE=‭12648430‬
Вернуться наверх
 

Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Вт июн 21, 2011 09:20:22 
Родился

Зарегистрирован: Сб июн 18, 2011 21:19:47
Сообщений: 5
Рейтинг сообщения: 0
Спасибо ibiza11, eufs
2eufs Был небольшой опыт работы с АСМ но под пик - больше не тянет =)


2 ibiza11 почему именно 128? не могли бы вы показать Свой исходинк.

2 ARV очень трудно найти нужный пост, когда их под 6к =)

вот что нашел среди Ваших ссылок

Код:
uint8_t buf[9];                     // массив для приема данных из датчика

/** Опрос кнопки.
 * Функция возвращает результат опроса кнопки: 0 - не нажата, 1 - было однократное нажатие,
 * 2 - кнопка нажата и удерживается более 2,5 секунд (примерно).
 * @return - возвращаемое значение
 */
uint8_t get_key(void){
   static uint8_t repeat = 0;                  // флаг автоповтора кода кнопки
   // нажатой кнопке соответствует 0 на выводе
   if(!(PINB & _BV(3))){
      // обнаружен 0 - отфильтруем дребезг
      _delay_ms(15);
      if(!(PINB & _BV(3))){
         // через 15 мс (время дребезга) все еще 0
         if(repeat) {
            // идет удержание - делаем автоповтор через 100 мс
            wdt_reset();
            _delay_ms(100);
            return 2;
         }
         // проверим, будет ли кнопка удержана более 2,5 секунд
         for(uint8_t i=0; i<250; i++){
            if(PINB & _BV(3))
               return 1;   // если менее - считаем нажатие однократным
            wdt_reset();
            _delay_ms(10);
         }
         // если держали 2,5 секунды - установим признак автоповтора и вернем соотв. результат
         repeat = 1;
         return 2;
      }
   }
   // если не обнаружено нажатие кнопки - вернем ноль, сбросив флаг автоповтора
   repeat = 0;
   return 0;
}


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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Вт июн 21, 2011 09:54:08 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 12
Рейтинг сообщений: 21
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Сообщений: 2015
Откуда: г. Тула
Рейтинг сообщения: 0
А почему бы не...:

1) ... удалить бы всё лишнее:
Код:

  //защита от дребезга и не только. если нажата какая-нибудь кнопка
  //сравниваем совпадают ли текущее состояние и предыдущее
  //если совпадают - проверяем счетчик comp, если нет обнуляем его
  //кнопка считается нажатой если она удерживается в течении 100
 
  if (Key)
  {
      if (comp++ > 100)
       {
            Key_p=Key;       
            out_trig();  //  выполняю действия
       }
  }
  else            // кнопка не нажата
  {
    comp = 0;
   
  }
  StartConvAdc();  //запускаем преобразование и выходим


2) ... вставить нужное:
Код:
  // Где-нибуть выше
  int KeyPressed = 0; 
 
  ...

  //защита от дребезга и не только.
  //кнопка считается нажатой если она удерживается в течении 100

  if (Key)
  {
      if (!KeyPressed && comp++ > 100)
       {
       KeyPressed = 1;
            //Key_p=Key;       
            //out_trig();  //  выполняю действия
       out_trig(Key); // Лучше всё же так. По усмотрению.
       }
  }
  else            // кнопка не нажата
    comp = KeyPressed = 0;

  StartConvAdc();  //запускаем преобразование и выходим


Так сойдёт?

_________________
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Алгоритм преодоления дребезга контактов
СообщениеДобавлено: Вт июн 21, 2011 10:02:23 
Мудрый кот
Аватар пользователя

Карма: 21
Рейтинг сообщений: 142
Зарегистрирован: Сб фев 21, 2009 13:11:40
Сообщений: 1898
Откуда: Москва
Рейтинг сообщения: 0
128 потому что делить на степень двойки проще всего.
Исходника нет, вот накидал на скорую руку:
Код:
/*это обработчик прерывания окончания преобразования АЦП */
static unsigned short SumADC=0;
static unsigned char Cnt=0;
#define MAX_CNT 128
SumADC+=ADCH;
Key=KEY_NULL;//это из Вашего исходника
if (++Cnt==MAX_CNT)
{
   Cnt=0;
   SumADC=(SumADC>>7); //деление на 128
   /* здесь алгоритм определения нажатой кнопки из Вашего исходника */
}


/*Это главный модуль, здесь делаете то же самое, что и делали кроме счетчика comp*/
 if (Key)
  {
    if (Key == LastState)
    {
      if (Key!=LastBut)
      {         
         out_trig();
         LastBut = Key;
         printf("LastBut %u ",LastBut)  ;
         printf("\n\r");           
      }
      else
      {
         printf("Povtor %u ",LastBut)  ;
         printf("\n\r");
      }     
    }
    else
    {
      LastState = Key;
    }
  }
  else
  {
    LastBut =0;
    KeyBuf = KEY_NULL;
    LastState = KEY_NULL;
  }

_________________
Ставим плюсы: )


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Форум закрыт Эта тема закрыта, Вы не можете редактировать и оставлять сообщения в ней.  [ Сообщений: 11 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y