Защита от дребезга дискретных сигналов

shplint
Offline
Зарегистрирован: 03.01.2015

Допустим есть массив оперативных сообщений на 100 элементов, куда пишутся все изменения дискртеных сигналов. Так мало потому что ОЗУ в контроллере больше нет... Есть несколько датчиков, которые начинают дребезжать...тем самым благодаря этому дребезку массив очень быстро переполнится и контроллер "повиснет"(( Первое что приходит в голову - переставать писать в массив когда подходим к его границе, но тогда мы теряем часть событий, это не есть хорошо... Второй вариант сделать какой-нибудь фильтр через который пропускать DI сигналы, но как сделать совсем непонятно(( Помогите советом, что можно сделать в такой ситуации :)

inspiritus
Offline
Зарегистрирован: 17.12.2012

Подберите конденсатор такой емкости, чтобы дребезг глушился , но фронт полезного сигнала не заваливатся более, чем ( скажем) на 15% от минимальной длительности полезного импульса... И поставте его между сигналом и GND.

axill
Offline
Зарегистрирован: 05.09.2011

Проще сделать програмно да и надежнее - фиксировать нужно только те изменения сигнала которые стабилизировались в течении заданного времени. Т.е. Вы не должны реагировать на любое изменение сигнала, а только на то изменение которое стабильно (не меняется) в течении заданного времени. Примеров реализации масса. Я использую счетчики на таймере, можно использовать mills()

shplint
Offline
Зарегистрирован: 03.01.2015

axill, а это хорошая мысль))

shplint
Offline
Зарегистрирован: 03.01.2015

axill, посмотрел я на форуме мельком как народ отслеживает промежуток времени(tmp=mills(); mills() - tmp > N мсек), а что будет если переменная tmp переполнится?  Пусть через 10-20 суток, но она переполнится, а нам нужна система работающая в режиме 24/7))

axill
Offline
Зарегистрирован: 05.09.2011

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

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

я иногда использую более простой способ програмной борьбы с дребезгом если не используются прерывания. Как только поймал изменение статуса, делаю delay(100) и после такой задержки проверяю совпадает ли статус с тем, который был перед задержкой. Для кнопок это вполне нормально работает (задержка подбирается от 100 до 500). Но нужно по задаче смотреть.

Datak
Offline
Зарегистрирован: 09.10.2014

shplint пишет:
посмотрел я на форуме мельком как народ отслеживает промежуток времени(tmp=mills(); mills() - tmp > N мсек), а что будет если переменная tmp переполнится?  Пусть через 10-20 суток, но она переполнится, а нам нужна система работающая в режиме 24/7))

Переменная tmp может переполняться, и значение mills( ) тоже, а разность ( mills( ) - tmp ) всё равно всегда будет правильной - такой вот фокус.

shplint
Offline
Зарегистрирован: 03.01.2015

Datak, разность само собой что не переполнится...А вот что произойдет когда tmp переполнится. Для того чтобы система работала в режиме 24/7 может быть стоит использовать функции получения времени(восвращающие время, а не мс с момента запуска контроллера)?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

shplint, а какие у вас конкретно датчики? Может просто не нужно их часто опрашивать? 

Datak
Offline
Зарегистрирован: 09.10.2014

shplint пишет:
разность само собой что не переполнится...А вот что произойдет когда tmp переполнится.

shplint, ты же написал, что этот способ используется для отсчёта нужных промежутков времени.
Так и есть, и время старта контроллера тут вообще не важно. Измеряется именно промежуток между сохранением значения в tmp, и текущим временем, полученным из millis( ).

И такой способ будет работать правильно для любых интервалов времени, почти до максимального значения millis( ) и, соответственно, tmp.
"Почти" -  потому что при интервалах очень близких к максимальному есть риск пропустить нужное значение разности, если опрос millis( ) выполняется не достаточно часто.

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

Попробуй сам, хотя бы на бумаге. Чтобы считать было проще, тренироваться советую на байтах - смысл от этого не меняется.

Anatoliy4
Offline
Зарегистрирован: 04.01.2015

Вот здесь есть отличный топик (http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku), там хорошо описаны способы подавления дребезга контактов. Можно подавлять дребезг без функции millis() (в этом топике это описано). Ну а если использовать millis(), то по истечении 50 дней таймер функции достигнет максимального значения, и если у вас Arduino на мк Atmega328(Arduino Uno), то можно сделать ватчдог(про это есть статья на хабрахабре), возможно ватчдог поддерживают и дркугие мк, но я проверял только Уно(поддерживает) и Мегу(почему-то не работает). А если боитесь, что переменная tmp перезаполнится, то возмите переменную типа unsigned long, памяти этой переменной чуть-чуть не хватает до полных пятидесяти дней(естественно в миллисекундах, потомучто millis() возвращает миллисекунды), вы сами посчитайте, сколько в миллисекундах будет 50 дней и какое максимально число можно записать в unsigned long, и сравните. Так же существует библиотека bounce.