Перейти к содержанию
    

Подавление дребезга контактов

Привет всем!

 

Написал небольшой кусочек кода для

подавления дребезга контактов, IMHO данный

код должен "фильтровать" ложные срабатывания

менее заданного периода.

Но почему-то не покидает ощущение того, что

в коде могут оказаться грабли :)

 

Какие еще есть правильные методы,

либо можно это сделать проще или красивее?

 

Пример для одного бита порта ввода:

 

#define BOUNCE_CANCELLATION_PERIOD 20

 

 

unsigned char BITcounter=0; //счетчик состояний бита

bit BITstate=0; //используемое (устойчивое) состояние бита (более 20 мсек)

bit BITmemory=0; // промежуточная переменная, запоминающаяя предыдущее состояние бита

bit toggled=0; //флаг,указывающий на изменение состояния бита

 

interrupt Timer0() //возникает 1 раз в мсек

{

if(BITmemory^BITn){if(toggled){BITcounter=0;} toggled=1;}

if(toggled ){BITcounter++;}

if(BITcounter==BOUNCE_CANCELLATION_PERIOD){BITstate=BITn;BITcounter=0;toggled=0;

}

BITmemory=BITn; //чтение с порта

}

 

 

 

Вот, примерно так...

Изменено пользователем Axxel

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Давно и хорошо работающий код. Обслуживает несколько клавиш.

 

unsigned long int debounced_state = 0,debounced_stateOld = 0;

unsigned long int A = 0x0;

unsigned long int B = 0x0;

unsigned long int C = 0x0;

 

void debounce(unsigned long int new_sample)

{

unsigned long int delta;

 

delta = new_sample ^ debounced_state; //Find all of the changes

 

/* clock_A ^= clock_B; //Increment the counters

clock_B = ~clock_B;*/

 

A = A^(B&C);

B = B^C;

C = ~C;

 

A &= delta; //Reset the counters if no changes

B &= delta; //were detected.

C &= delta;

 

//Preserve the state of those bits that are being filtered and simultaneously

//clear the states of those bits that are already filtered.

debounced_state &= (A|B|C);

//Re-write the bits that are already filtered.

debounced_state |= (~(A|B|C) & new_sample);

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а я просто опрашиваю клавиатуру с интервалом большим, чем максимальное время дребезга. Скажем в первом примере вместо прерывания каждую 1 мс делать опрос раз в 20-50мс. Человек такую задержку не чувствует

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Контролировать один раз нажатие клавиши (совет NVade) глупо, т.к. любой дребезг вызовет событие нажатия.

 

По хорошему необходимо контролировать время первого удержания клавиши (состояния порта) и через контрольный тайм-аут, если состояние ни разу не изменилось, принимать решение о нажатии клавиши. После этого необходимо переходить на другой этап и контролировать время отпускания. Через определенный тайм-аут принимать решение об завершении работы с клавишей.

И уже после всего этого можно переходить к повторному ожиданию нажатия клавиши.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По хорошему необходимо контролировать время первого удержания клавиши (состояния порта) и через контрольный тайм-аут, если состояние ни разу не изменилось, принимать решение о нажатии клавиши. После этого необходимо переходить на другой этап и контролировать время отпускания. Через определенный тайм-аут принимать решение об завершении работы с клавишей.

И уже после всего этого можно переходить к повторному ожиданию нажатия клавиши.

 

 

Да, примерно так и сделано, т.е к примеру если BOUNCE_CANCELLLATION_PERIOD равен 20

то в течение за все 20 прерываний от таймера значение бита должно быть равно одному и тому

же значению, только в этом случае состояние запоминается.

 

Вопрос: нормально ли для этого алгоритма использование прерывания от таймера?

Может есть способы без прерываний?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Думаю лучший вариант реализуется при помощи прерываний от линий IO кнопок.

В этом случае изменение состояния линии не пропустишь, а по таймеру только проверять время, прошедшее с момента последнего изменения состояния и через скажем 20 мс фиксировать логическое состояние кнопки (нажата/нет).

Вопрос только в количестве кнопок и аппаратных прерываний, но у последних AVR их много.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На самом деле достаточно ловить первый фронт изменения состояния и через таймаут проверить сохранилось ли состояние. И не надо ждать когда сигнал перестанет дребезжать, и только потом включать выдержку времени, это бессмысленно. Подумайте. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На самом деле достаточно ловить первый фронт изменения состояния и через таймаут проверить сохранилось ли состояние. И не надо ждать когда сигнал перестанет дребезжать, и только потом включать выдержку времени, это бессмысленно. Подумайте. :)

 

Если неждать то кто даст гарантию что после принятия решения о нажатой кнопке не происходит дребезга

А с дребезгом при отжатии как быть ??

 

По моему мнению самый верный способ - запускать програмный таимер по нажатию

Делать +1 если нажата и -1 если отжата

Ограничить нулем и числом А снизу и сверху

И принимать решение о точ что нажата кнопка когда таимер достигнет А

 

Заодно можно и блительное нажатие обрабатывать

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если неждать то кто даст гарантию что после принятия решения о нажатой кнопке не происходит дребезга

А с дребезгом при отжатии как быть ??

Либо я не ясно выразился, либо одно из двух. :)

Ловим фронт изменения входа (не важно какой), запоминаем новое состояние, ждем время достаточное чтоб дребезг успокоился, проверяем вновь состояние входа, если совпало, его и принимаем за текущее. Обрабытывается таким образом и вкл и выкл.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я проще делаю. В 8-битный сдвиговый регистр каждые 10 мс вдвигаю текущее состояние кнопки. Если в сдвиговом регистре все '1', то кнопка нажата, выходной сигнал устанавливаю в '1'. Если все '0', то кнопка отжата, выходной сигнал устанавливаю в '0'. Все другие комбинации игнорируются и не меняют состояние вых. сигнала.

 

При опроcе каждые 10 мс и 8-ми битах время получается 80 мс, это отлично работает со всеми обычными кнопками, в т.ч. с мембранными клавами. Для массивных контактов, которые могут дребезжать с малой частотой (контактор какой-нибудь, например), время опроса можно увеличить до 20..30 мс.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Объясните пожалуйста, как такое возможно?

 

Помехи например, ложные срабатывания от датчиков, ведь такое IMHO может быть

 

Я проще делаю. В 8-битный сдвиговый регистр каждые 10 мс вдвигаю текущее состояние кнопки. Если в сдвиговом регистре все '1', то кнопка нажата, выходной сигнал устанавливаю в '1'. Если все '0', то кнопка отжата, выходной сигнал устанавливаю в '0'. Все другие комбинации игнорируются и не меняют состояние вых. сигнала.

 

При опроcе каждые 10 мс и 8-ми битах время получается 80 мс, это отлично работает со всеми обычными кнопками, в т.ч. с мембранными клавами. Для массивных контактов, которые могут дребезжать с малой частотой (контактор какой-нибудь, например), время опроса можно увеличить до 20..30 мс.

 

Можно кусочек кода?

 

И еще вопрос: используя прерывания от аппаратного таймера для подавления

дребезга, с какой частотой целесообразнее всего устраивать эти прерывания?

И каков риск что пользовательская функция-обработчик не успеет обработаться

до возникновения следующего прерывания?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...