Например TDA7294

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





Текущее время: Вт апр 23, 2024 17:07:13

Часовой пояс: 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 
Ум, честь и совесть. И скромность.
Аватар пользователя

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

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

Мой уютный бложик... заходите!


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

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

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

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


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

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

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

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

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

Мой уютный бложик... заходите!


Вернуться наверх
 
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.

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

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

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

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


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: 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
Рейтинг сообщений: 143
Зарегистрирован: Сб фев 21, 2009 13:11:40
Сообщений: 1900
Откуда: Москва
Рейтинг сообщения: 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
Рейтинг сообщений: 26
Зарегистрирован: Вс апр 10, 2011 02:24:06
Сообщений: 772
Откуда: г.Северодонецк
Рейтинг сообщения: 0
Если в Асме разбираешься, то посмотри, как сделано подавление, задержки и автоповтор.
Из основного цикла подпрограмма вызывается, проверяется код нажатой кнопки и выполняется действие. Для твоего случая нужно только изменить ПП предварительного ввода.


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

_________________
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 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 13
Рейтинг сообщений: 24
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Сообщений: 2029
Откуда: г. Тула
Рейтинг сообщения: 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
Рейтинг сообщений: 143
Зарегистрирован: Сб фев 21, 2009 13:11:40
Сообщений: 1900
Откуда: Москва
Рейтинг сообщения: 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 часа


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

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


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

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


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