ARDUINO Ложные срабатывания щелевого датчика

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
Всех приветствую!
И прошу помощи. Задача собрать намоточный станок, который бы считал длину намотанного провода (в мм). За отсчет длины отвечает щелевой оптический датчик (куплен на известном китайском ресурсе) на компараторе LM393 (фото ниже). В скетче счетчик срабатывает по прерыванию "RISING" ноги D2 (кусок скетча привожу). Довольно часто наблюдаются ложные срабатывания, а именно - по 2 раза бывает срабатывает (привожу скрин счетчика из монитора порта, на котором по таймингам видны по 2 срабатывания в одно и то же время).
Вопрос: как это побороть?
C++:
#define Piece 1// 31,5*PI/24                 //минимальный кусок контролируемой длины (наматываемая длина при при обороте между двумя отверстиями счетчика), мм
//расчет: d*PI/n   - d-диаметр колесика счетчика, n - количество щелей в колесике счетчика

#define encoder 2         //пин счетчика оборотов

volatile int LenghtBuff = 0; //буфер длины намотки для обратного отсчета

void setup()
{
  Serial.begin (9600);
      pinMode(encoder, INPUT);
      attachInterrupt(0, counter, FALLING);
}
void counter() {
  LenghtBuff -= Piece;
  Serial.println(LenghtBuff);
}
 

Вложения

Vlad1984

✩✩✩✩✩✩✩
14 Фев 2023
1
0
Запитайте модуль от 3.3V а не от 5. Была такая же история с этим модулем, не знаю с чем связано.
 

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@Vlad1984, перекинул питание на 3,3V, не помогло, но по ощущениям )) стало понятнее. Теперь если вращать медленно, от руки, то ложных срабатываний нет. Однако, на большой скорости по 2 или 3 срабатывания за раз проскакивает (см. тайминги на скрине).
Подключил осциллограф, дребезга не увидел, однако, увидел не равные по длине импульсы (2 скрина ниже). Осциллограмма снималась при вращении от двигателя. Возможно, не равные импульсы - следствие не равномерного вращения движка. Осциллограмм делал несколько штук, (от руки, от двигателя, с разной скоростью...) - дребезга нет. Но все ровно остается вопрос: откуда в мониторе порта берутся по несколько срабатываний, которые по времени совпадают до миллисекунд?
 

Вложения

poty

★★★★★★✩
19 Фев 2020
3,237
942
@N0rdling, ну, значит, это не дребезг. Объяснение "откуда берутся" я давал в первых постах. Разная ширина импульсов может быть обусловлена разной шириной щелей.
 

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@poty, ширина щелей, конечно не идеально одинаковая, но думаю, что разнится в пределах 3-5 соток, так как сам диск со щелями резался на лазерном станке. Последние испытания проводил на диске с 9-ю щелями всего.
 

Вложения

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@poty, еще в защиту "ровных" щелей: если бы ширина импульсов зависела от разной ширины щелей, то на осцилограмме была бы видна закономерность: повтор ширины импульсов через каждые 9 шт., а ее нет.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@N0rdling, ну, на той осциллограмме, что приведена (где много импульсов на экране уместилось), достоверно увидеть, что они разные тоже проблематично, а уж тем более сравнить периодичность.
Щели могут иметь проблему в соосности с точкой вращения, сама ось вращения может иметь биения, на таких небольших интервалах может иметь место даже шероховатость поверхности... Механика - штука такая.
Самое главное - не в длительности импульсов, а в том, что они не имеют колебания на фронтах и срезах.
 

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@poty, механика-то, конечно, штука не простая)) однако и не соосность расположения щелей относительно оси вращения, и биение самой оси вращения,, да даже шероховатость поверхности - будут давать периодический характер неравномерности импульсов.
Возможно, действительно, для высокой частоты вращения (в моем случае максимум 800-900Гц) наличие сглаживающего RC фильтра на самой плате датчика дает не корректный результат? Или причина в чем-то другом, уже не знаю.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
476
137
@N0rdling,
Время в мониторе порта это время вывода на экран. Когда время между импульсами измеряется миллисекундами, то несколько различных отсчетов сделанных в разное время например с разностью в 2 мс, могут отображаться в мониторе порта одним временем.
 
  • Лойс +1
Реакции: Старик Похабыч

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@Bruzzer, честно говоря не знал, что в мониторе, при выводе сообщений с точностью тайминга до миллисекунд на самом деле время не соответствует. Есть ли способ более точно вывести в монитор порта сигналы?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Абсолютно точно. смотреть время по монитору можно очень приблизительно. Если хочется проверить надежно - сохраняйте микросекунды и выводите их рядом.
Для примера сейчас на столе стоят часы на светодиодной ленте, меняют свои данные и параллельно выводят в монитор контроль. Монитор порта зметно отстает, на какие то доли секунды, но это видно.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
476
137
@N0rdling,
Учтите, что надо увеличить скорость сериал до 115200. Т.к. на 9600 для отправки одно символа требуется примерно 1 мс,, и для большой частоты вращения вы наткнетесь на ограничение со стороны скорости сериал. Подсчитайте, хватит ли скорости для вывода времени, возможно придется укоротить значение.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@N0rdling, а сколько, по Вашему, будут выводиться 3-4 символа (считая с символами перехода на другую строку) на скорости 9600 бит/сек, при условии, что один символ передаётся 9-10 битами?
За счёт какого времени будут выводиться эти символы, если они выводятся в прерывании (т.е. тогда, когда другие прерывания, даже если есть на них запрос, просто будут отложены)? Следующее прерывание будет ожидать окончания текущего (т.е., будет задержано до момента выхода из предыдущей обработки в прерывании), а если снова случится изменение потенциала на входе (второе за период обработки), то одно из прерывания просто не произойдёт.
 

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@Bruzzer, прошлый скрин монитора порта как раз и сделан на скорости 115200.
@Старик Похабыч, @poty, сделал - то же самое (см. скрин ниже: второй столбик - millis()).
Количество прорезей уменьшено до 3х - равномерно распределены по окружности.

П.С. закономерности нет, на прошлом скрине просто совпало, вот еще один:
 

Вложения

poty

★★★★★★✩
19 Фев 2020
3,237
942
Сделали что? Я, как минимум, предположил три вещи и переход на 115200 - лишь одна из них, не снимающая всех проблем. С другой стороны - если Вы убедились на осциллографе, что ложных срабатываний нет, то смысл дальше выводить данные в монитор? Делайте подсчёт, допустим, раз в секунду и сравнивайте с реальностью.
Если уж прям хочется вывода в монитор, то выводите раз в секунду полученное количество импульсов. и делайте это не в прерывании, а в основном коде.
 
  • Лойс +1
Реакции: N0rdling и Vlad1984

Геннадий П

★★★★★★✩
14 Апр 2021
1,974
633
45
C++:
      attachInterrupt(0, counter, FALLING);
}
void counter() {
  LenghtBuff -= Piece;
  Serial.println(LenghtBuff);
}
Кстати, по поводу кода.
Никогда(!) не используйте в прерывании вывод в периферию. Особенно если это достаточно медленная периферия типа UART.
Если уж хотите что то вывести в порт по сигналу прерывания, то делайте флаг, который устанавливаете в прерывании и уже в основном коде (или отдельном потоке, смотря на чем пишете) по установленному флагу выводите что нужно в порт.
 
  • Лойс +1
Реакции: N0rdling

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@poty,
это больше относилось к посту @Старик Похабыч, имеется ввиду, что прописал подсчет millis() с выводом в порт
@poty, уточните, пожалуйста, какие еще 2 вещи вы рекомендовали (кроме перехода на 115200)? Посчитать количество импульсов самостоятельно я не могу: вращается все это дело от двигателя более чем 600об/мин., я быстро считаю, но на таких оборотах могу и сбиться со счета ))) Мне не требуется ничего выводить в монитор, этим я занялся прежде всего из-за того, что понял в результате проверки, что длина намотки считается не верно.

@Геннадий П, в порт выводить вообще-то ничего не требуется. Вся заварушка началась с того, что собранный мной намоточный станок не верно считает длину намотки. Начал копать и выяснил, что похоже, с датчика доходят ложные сигналы.Осциллограф показывает отсутствие "дребезга контактов", но импульсы разной продолжительности (вероятно, можно списать на неравномерность вращения двигателя). В мониторе порта наблюдаются задвоенные / затроенные значения времени подсчета импульсов.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
476
137
@N0rdling,
Раз для совпадающих времен, последние числа разные, значит прерывание действительно вызывается два раза в почти одно и тоже время.
Хотя вы программу меняете, но код не приводите. Так что это только предположение.
 
  • Лойс +1
Реакции: N0rdling

N0rdling

★✩✩✩✩✩✩
15 Янв 2020
154
20
@Старик Похабыч, @Bruzzer, @Геннадий П, @poty, исправил код (привожу основной цикл и обработчик прерываний). Суть такова: Обработчик прерываний фиксирует событие и уменьшает счетчик. Если последнее значение не было выведено, то очередное значение записывается в столбец 2, а если и второе не было выведено, то в столбец 3. Если значение успело попасть в монитор порта, то следующее пишется в столбец 1. Выводится само значение счетчика плюс micros().
C++:
void counter() {
  LenghtBuff -= 1;
  if (SerialFL) SerialFL1 = 1;
  if (SerialFL1) {
    numCount++;
    if (numCount == 3)numCount = 0;
  }
  arr[numCount] = LenghtBuff;
  tmrISR[numCount] = micros();
  SerialFL = 1;
}
void loop() {
  enc1.tick();
  butt.tick();
  enc_but();
  cycle();
  stepper.tick();
  if (SerialFL) {
    numCount = 0;
    while (numCount < 3) {
      Serial.print (tmrISR[numCount]);
      Serial.print ("  ");
      Serial.print (arr[numCount]);
      Serial.print ("      ");
      numCount++;
    }
    Serial.println();
    SerialFL = 0;
    SerialFL1 = 0;
    numCount = 0;
  }
}
Вывод: диск стоит с равномерными 9-ю щелями, на максимальной скорости все успевает посчитаться (иногда очередное значение попадает во второй столбец).

UPD: даже с диском 14 равномерных щелей на максимальной скорости все считается, как надо.
 

Вложения

Изменено:

ELITE

✩✩✩✩✩✩✩
16 Ноя 2023
1
0
Тоже долго мучался с оптикой... ну не работает она адекватно в широком диапазоне оборотов.. гдето, да проскакивает ложные срабатывания...

В общем плюнул и перешел на магнитные датчики - на датчике Холла

И тут на много проще - любой старый кулер= ГОТОВЫЙ датчик оборотов!!! который отлично и без глюков дает от единиц до десятков тысяч оборотов!!!

Единственно если щелевой дитчик по сути сделать "диск" можно любой и просто (например для датчика угла надо точность в градусах и сделать диск 10-12 см на 180 и даже 360 делений в целом не сложно
То вот с магнитными сложнее -из готового - старый двигатель от ХДД имеет от 9 до 15 пар полюсов...
А сделать магнитный диск сложно самому.... да и найти готовый не просто
В итоге для таких вещей приходится делать редуктора...// благо шестерни от старых принтеров найти легко