Простая процедура отказов - PullRequest
8 голосов
/ 01 октября 2008

Есть ли у вас простая процедура отладки, удобная для работы с одним входом переключателя?

Это простая система без использования операционной системы.

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

Ответы [ 11 ]

11 голосов
/ 03 октября 2008

Простейшие решения часто являются лучшими, и я обнаружил, что просто чтение состояния переключателя каждые N миллисекунд (между 10 и 50, в зависимости от переключателей) всегда работало для меня.

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

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

Обратите внимание, что этот простой подход добавляет задержку к обнаружению изменения состояния. Если переключателю требуется T мс для достижения нового устойчивого состояния, и он опрашивается каждые X мс, тогда наихудшая задержка для обнаружения нажатия - T + X мс. Ваш интервал опроса X должен быть больше, чем время отказов в худшем случае T.

11 голосов
/ 01 октября 2008

Я думаю, вы могли бы многое узнать об этом здесь: http://www.ganssle.com/debouncing.pdf

Лучше всего всегда делать это аппаратно, если это возможно, но есть и некоторые мысли о программном обеспечении.

Простой пример кода из TFA:

#define CHECK_MSEC 5 // Read hardware every 5 msec
#define PRESS_MSEC 10 // Stable time before registering pressed
#define RELEASE_MSEC 100 // Stable time before registering released
// This function reads the key state from the hardware.
extern bool_t RawKeyPressed();
// This holds the debounced state of the key.
bool_t DebouncedKeyPress = false;
// Service routine called every CHECK_MSEC to
// debounce both edges
void DebounceSwitch1(bool_t *Key_changed, bool_t *Key_pressed)
{
    static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;
    bool_t RawState;
    *Key_changed = false;
    *Key_pressed = DebouncedKeyPress;
    RawState = RawKeyPressed();
    if (RawState == DebouncedKeyPress) {
        // Set the timer which allows a change from current state.
        if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
        else Count = PRESS_MSEC / CHECK_MSEC;
    } else {
        // Key has changed - wait for new state to become stable.
        if (--Count == 0) {
            // Timer expired - accept the change.
            DebouncedKeyPress = RawState;
            *Key_changed=true;
            *Key_pressed=DebouncedKeyPress;
            // And reset the timer.
            if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
            else Count = PRESS_MSEC / CHECK_MSEC;
        }
    }

}

2 голосов
/ 16 октября 2008

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

Но лучший совет - попросить вашего дружественного разработчика аппаратного обеспечения "зафиксировать" значение и позволить вам очистить это значение, когда вы доберетесь до него.

2 голосов
/ 01 октября 2008

Нет единого простого решения, которое работает для всех типов кнопок. Неважно, что кто-то здесь говорит вам использовать, вам придется попробовать это с вашим оборудованием и посмотреть, насколько хорошо оно работает. И посмотрите на сигналы на прицеле, чтобы убедиться, что вы действительно знаете, что происходит. Ссылка Rich B на pdf выглядит как хорошее место для начала.

1 голос
/ 01 октября 2008

Если вы можете обойтись без него, лучшее решение в аппаратном обеспечении состоит в том, чтобы коммутатор имел два разных состояния без какого-либо состояния между ними. То есть используйте переключатель SPDT, при этом каждый полюс подает либо R, либо S линии триггера / флопа. При таком способе вывод триггера / флопа должен быть опровергнут.

1 голос
/ 01 октября 2008

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

0 голосов
/ 25 мая 2019

Вся концепция хорошо описана Джеком Гэнслом. Его решение, опубликованное в качестве ответа на исходный вопрос, очень хорошо, но я нахожу его часть не очень ясной, как оно работает.

Существует три основных способа борьбы с отскоком переключателя: - с помощью опроса - используя прерывания - сочетание прерываний и пулирования.

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

Если вы работаете с кнопочным переключателем SPST с одним механически устойчивым положением, то я бы предпочел решение, которое работает с использованием комбинации прерываний и объединения.
Вот так: используйте входное прерывание GPIO для обнаружения первого фронта (падение или повышение, противоположное направление неактивного состояния переключателя). Под входом GPIO ISR установлен флаг об обнаружении.
Используйте другое прерывание для измерения времени (т. Е. Таймер общего назначения или SysTick) для подсчета миллисекунд. При каждом увеличении SysTick (1 мс):
Если buttonFlag имеет значение true, то вызвать функцию для опроса состояния кнопки (опроса).
Сделайте это для N последовательных приращений SysTick, затем снимите флажок.

Когда вы опрашиваете состояние кнопки, используйте логику, поскольку вы хотите определить состояние кнопки, например, M последовательных показаний одинаково, среднее значение больше Z, считать, если состояние, последние значения X одинаковы и т. Д.

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

Примите во внимание такие вещи, как: вам нужно «отпустить» кнопку, нужно ли обнаруживать длительное нажатие и нужно ли действовать при отпускании кнопки. Мне не нравится действие кнопки при отпускании кнопки, но некоторые решения работают таким образом.

0 голосов
/ 10 января 2019

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

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

0 голосов
/ 26 ноября 2016

На аппаратном уровне базовая процедура устранения неполадок должна учитывать следующие сегменты поведения физического ключа (или коммутатора):

Клавиша сидит тихо -> палец касается клавиши и начинает нажимать вниз -> клавиша достигает нижней части хода, и палец удерживает ее там -> палец начинает отпускать клавишу, а пружина толкает клавишу обратно вверх -> палец отпускает клавишу, и клавиша немного вибрирует, пока успокаивается

Все эти этапы включают в себя 2 металлических скребка, трения и столкновения друг с другом, колебания напряжения вверх и вниз от 0 до максимума в течение миллисекунд, поэтому на каждом этапе возникает электрический шум:

(1) Шум во время прикосновения к клавише, вызванный проблемами окружающей среды, такими как влажность, вибрация, изменения температуры и т. Д., Вызывающими изменения напряжения на контактах клавиши

(2) Шум, вызванный нажатием клавиши

(3) Шум при удерживании клавиши

(4) Шум при отпускании ключа

(5) Шум при вибрации клавиши после отпускания

Вот алгоритм, по которому мы в основном предполагаем, что человек нажимает клавишу:

прочитать состояние клавиши, которая может быть «может быть нажата», «определенно нажата», «определенно не нажата», «может быть не нажата» (мы никогда не уверены)

Цикл, пока клавиша «может быть» нажата (при работе с аппаратными средствами это выборка напряжения больше некоторого порогового значения), пока не будет «определенно не нажата» (ниже порогового напряжения) (это инициализация, ожидание шума, остановка, определение «может быть» и «определенно нет» зависит от конкретного приложения)

цикл, пока клавиша «определенно не» нажата, пока клавиша «не может быть» нажата

когда клавиша «может быть» нажата, начать цикл и выборку состояния клавиши и отслеживать, как долго клавиша «может быть» нажата - если клавиша возвращается в состояние «возможно, нет» или «определенно нет» в течение определенного периода времени, перезапустите процедуру - в определенное время (число миллисекунд), которое вы выбрали (обычно путем экспериментирования с различными значениями), вы решаете, что значение выборки больше не вызвано шумом, а, скорее всего, вызвано тем, что ключ фактически удерживается человеком пальцем и вы вернете значение «нажата»


while(keyvalue = maybepressed){
//loop - wait for transition to notpressed
sample keyvalue here;
maybe require it to be "notpressed" a number of times before you assume
it's really notpressed;
}
while(keyvalue = notpressed){
//loop - wait for transition to maybepressed
sample keyvalue
again, maybe require a "maybepressed" value a number of times before you 
transition
}
while(keyvalue=maybepressed){
  presstime+=1;
  if presstime>required_presstime return pressed_affirmative
  }
}
return pressed_negative
0 голосов
/ 26 января 2015

В алгоритме от ganssle.com может быть ошибка. У меня сложилось впечатление, что следующая строка

static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;

следует читать

static uint8_t Count = PRESS_MSEC / CHECK_MSEC;

для правильного дебатирования начального пресса.

...