Устранение дребезга оптического переключателя

xx xxx
Offline
Зарегистрирован: 20.04.2022

Здравствуйте.

Имеется в наличии некоторый оптический переключатель китайского происхождения. Точно не известно, что это, но вроде как FC-33 (на базе H2010) (по крайней мере, так он определяется поисковиком, xd). Выдал преподаватель в универе, сказал "Вот тебе датчик, иди делай робота", и был таков.

Требуется: Используя переключатель как оптический энкодер (в паре с диском с прорезями) определить скорость вращения некоторого вала.

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

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

#define L_encoder 2
volatile unsigned long counter;

void setup() {
  Serial.begin(115200);
  attachInterrupt(0, intrpts, CHANGE);
  pinMode(L_encoder, INPUT);
}

void intrpts() {
  counter ++;
}

void loop() {
  Serial.println(counter);
}

За одну прорезь ардуинка выполняет несколько прерываний. Каждое прерывание увеличивает счётчик на единицу. То есть, за одну прорезь счётчик должен увеличиваться на 1, а на деле, увеличивается на 2+.

Перечитал уйму ресурсов, везде говорят про какие-то триггеры Шмидта, RC-цепи, и программное подавление дребезга(что, в случае с прерываниями неприменимо). Объясните пожалуйста, как тупому, куда припаять резистор с конденсатором, или как ещё можно решить эту проблему.

Заранее прошу не кидать тапками, в последнее время уже крыша едет с этой учёбой.

rkit
Offline
Зарегистрирован: 23.11.2016

xx xxx пишет:

программное подавление дребезга(что, в случае с прерываниями неприменимо)

что-то новое

b707
Offline
Зарегистрирован: 26.05.2017

xx xxx пишет:

за одну прорезь счётчик должен увеличиваться на 1, а на деле, увеличивается на 2+.

с чего бы это?

если внимательно посмотреть на код. как раз на 2 и должен увеличиваться...

sadman41
Offline
Зарегистрирован: 19.10.2016

CHANGE как переводится?

xx xxx
Offline
Зарегистрирован: 20.04.2022

rkit пишет:

xx xxx пишет:

программное подавление дребезга(что, в случае с прерываниями неприменимо)

что-то новое


А есть способ? delay'ем в прерывании не отделаться, только запрещать их на время, после первого срабатывания, скажем, через millis. Но реализовать это у меня не получилось, а готовых решений не нашёл.

xx xxx
Offline
Зарегистрирован: 20.04.2022

b707 пишет:

с чего бы это?

если внимательно посмотреть на код. как раз на 2 и должен увеличиваться...

Должно срабатывать на изменении сигнала, то есть, если сигнал меняется с 0 на единицу, и если с 1 на 0. Вы скорее всего неправильно поняли). "За одну прорезь" - подразумевался проворот диска с прорези на риску. То есть, однократное изменение сигнала. 

Если использовать RAISING, прерывание всё равно будет срабатывать, даже если значение изменится с 1 на 0. Всё из-за дребезга, или как его тут обозвать. Пока не успокоится - сигнал несколько раз сменится от 0 к 1 и обратно. 

xx xxx
Offline
Зарегистрирован: 20.04.2022

Да и, ладно бы если всегда на 2, так по разному же выдаёт. Может счётчик на 1 увеличить, может на 8, и так далее. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

xx xxx пишет:
Всё из-за дребезга, или как его тут обозвать. Пока не успокоится - сигнал несколько раз сменится от 0 к 1 и обратно.

А ты осциллографом-то смотрел, что у тебя на фотоприемнике тварица? 

xx xxx
Offline
Зарегистрирован: 20.04.2022

DetSimen пишет:

А ты осциллографом-то смотрел, что у тебя на фотоприемнике тварица? 


Осциллографа не имею в пользовании, так что с этим затруднения. На борту датчика кстати есть компаратор LM393, пишут, что он грешит подобным.

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

xx xxx пишет:

Если использовать RAISING, прерывание всё равно будет срабатывать, даже если значение изменится с 1 на 0. Всё из-за дребезга, или как его тут обозвать. Пока не успокоится - сигнал несколько раз сменится от 0 к 1 и обратно. 

Без осцилла диагностика причины невозможна. Скорее всего у вас на питании пульсации, которые  в гистерезисе воспринимаются как новый импульс. Для проверки запитайте опто-модуль от батареек.

xx xxx
Offline
Зарегистрирован: 20.04.2022

Увы, никаких изменений. Скачет так же, что с батарейками, что с конденсаторами.

b707
Offline
Зарегистрирован: 26.05.2017

Ищите осциллограф

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Может и таким что то увидите - http://arduino.ru/forum/proekty/virtualnyi-ostsillograf

b707
Offline
Зарегистрирован: 26.05.2017

xx xxx пишет:
delay'ем в прерывании не отделаться, только запрещать их на время, после первого срабатывания, скажем, через millis.

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

Сколько прорезей у вас в диске и какая максимальная скорость вращения?

Green
Offline
Зарегистрирован: 01.10.2015

Komandir пишет:

Может и таким что то увидите - http://arduino.ru/forum/proekty/virtualnyi-ostsillograf

Тут и аналог то не нужен. Просто выдавайте измеряемый 0/1 в сериал (плоттер) на максимуме скорости UART. Или через буфер, если не достаточно разрешения.

xx xxx
Offline
Зарегистрирован: 20.04.2022

b707 пишет:
не надо запрещать, просто не увеличивайте счетчик некоторое время после первого срабатывания.

Не получилось реализовать такое в коде. Да и аппаратно гасить всяко надёжнее.

b707 пишет:
Сколько прорезей у вас в диске и какая максимальная скорость вращения? 

Прорезей в диске 20, за максимальную скорость не отвечу точно, но не больше 1000 об/мин. Крутит простенький моторчик с редуктором: 

nik182
Offline
Зарегистрирован: 04.05.2015

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

xx xxx пишет:
как ещё можно решить эту проблему.
Вот здесь всё написано и нарисовано.

b707
Offline
Зарегистрирован: 26.05.2017

xx xxx пишет:

b707 пишет:
не надо запрещать, просто не увеличивайте счетчик некоторое время после первого срабатывания.

Не получилось реализовать такое в коде. Да и аппаратно гасить всяко надежнее.


не получилось реализовать? Скажите честно, что даже не пробовали.

Что там " реализовывать"? При входе в прерывание первым делом проверяем время с прошлого входа и если прошло менее ХХХ мкс - тут же выходим. ВСЕ.

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

Мне кажется, вы вообще ничего сами делать не хотите, готового решения ждете? Зря.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

xx xxx пишет:
как ещё можно решить эту проблему.
Вот здесь всё написано и нарисовано.

одно дело потрепаться на аглицком, но читать - это уже за гранью )))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

одно дело потрепаться на аглицком, но читать - это уже за гранью )))

Что и Вы не знаете о существовании онлайн-переводчиков? Ужость! :-(

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

ЕвгенийП пишет:

ua6em пишет:

одно дело потрепаться на аглицком, но читать - это уже за гранью )))

Что и Вы не знаете о существовании онлайн-переводчиков? Ужость! :-(

так они напереводят...и как быть с ненормативной, но очень выразительной лексикой? )))

b707
Offline
Зарегистрирован: 26.05.2017

ua6em пишет:

так они напереводят...и как быть с ненормативной, но очень выразительной лексикой? )))

Это какой ? "дребезг"?

Pyotr
Offline
Зарегистрирован: 12.03.2014
xx xxx
Offline
Зарегистрирован: 20.04.2022

b707 пишет:
Скажите честно, что даже не пробовали.

b707 пишет:
Мне кажется, вы вообще ничего сами делать не хотите, готового решения ждете? Зря. 

За что вы на меня набрасываетесь? Перепробовал много всего, результатов не было, отчего сослался на свою некомпетентность в данном вопросе и полез на форумы. Глупость? Может быть. Лень? Не думаю.

А за советы спасибо. 

xx xxx
Offline
Зарегистрирован: 20.04.2022

Я правда не один десяток сайтов пересмотрел, но такого не находил. Эх ох... Видно поиск информации - не моё). Спасибо большое

xx xxx
Offline
Зарегистрирован: 20.04.2022

Проверил - тестовый код работает как надо. Спасибо ещё раз!

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

Выходит, что этот модуль идёт совсем без гистерезиса. А так с резистором получается по факту триггер шмитта, который отсекает все мелкие колебания уровня засветки и помехи от питания.  

Pyotr
Offline
Зарегистрирован: 12.03.2014

Сразу виден уровень схемотехника этого модуля. В схему надо добавить не только ПОС, но и плавающее смещение на инверсный вход, чтобы обеспечить стабильную работу схемы при разных уровнях внешней засветки.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

xx xxx пишет:

Проверил - тестовый код работает как надо. Спасибо ещё раз!

Аппаратно одолел, а программно? В твоём коде:
 

#define L_encoder 2
volatile unsigned long counter;

void setup() {
  Serial.begin(115200);
  attachInterrupt(0, intrpts, CHANGE);
  pinMode(L_encoder, INPUT);
}

void intrpts() {
  counter ++;
}

void loop() {
  Serial.println(counter);
}

 

xx xxx
Offline
Зарегистрирован: 20.04.2022

ua6em пишет:

Аппаратно одолел, а программно?

#define L_encoder 2
volatile int counter = 0;
volatile unsigned long Last_signal = 0;
void setup() {
  Serial.begin(115200);
  attachInterrupt(0, intrpts, CHANGE);
  pinMode(L_encoder, INPUT);
}

void intrpts() {
  if (Last_signal + 50000 <= micros()) {
    Last_signal = micros();
    counter ++;
  }
}

void loop() {
  Serial.println(counter);
}

Как-то так наверное. Не знаю, как будет работать, проверить возможности уже нет). Датчик пропаян, прикручен, и справляется как и должен, не хочу разбирать.