Как работает энкодер?

Не будет так. Изначально имеем положение 2, и первое прерывание будет из положения 3 в положение 4. на пине 0.

P.S. Извините, может цитату не к месту привёл, но ТС уже мультиметром измерил, показал, что этот энкодер с устойчивыми состояниями (#94)

значит это энкодер с 4-мя импульсами на шелчок, я о таких не слышал и в руках не держал и, самое главное смысла в таких энкодерах не вижу, китайцы съэкономили на фиксаторе разве что )))
PS даже Гайвер о таких не слышал

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

Вы всерьез полагаете, что существует ответ по существу на вопрос:

На мой взгляд, единственный возможный ответ:
“Вы не понимаете, что прежде, чем идти на форум, нужно было сначала самостоятельно попытаться найти ответ на возникший вопрос. В частности, прочитать (и понять!) хотя бы две-три статьи об устройстве энкодера и принципе его работы.”
а также то, что
“форум не может (и не должен!) заменить учебник или учебное заведение”.
Кстати, на вопрос:

ответили.

И еще:

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

Не совсем понятно, что здесь подразумевается по “импульсами”, но один и тот же энкодер с 20 щелчками на оборот может давать приращение от 20 до 80 единниц на тот же оборот. В зависимости от того, как написан софт.
И, кстати, это непосредственно следует из того рисунка из Википедии, который я приводил выше.

Раз уж возник такой вопрос:

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

Давай я тебе, вместо Дим-дим напишу.

ТС про энкодер ничего не спрашивает.
он УДИВЛЕН странному эффекту:

  1. возмем ОДИН канал энкодера.
  2. повесим прерывание на чейндж.
  3. станем печатать значение прочитанное СРАЗУ после прерывания.
    Логично ждать, что значения ДО и ПОСЛЕ прерывания - разные?
    Так у него выходит, что разные - при вращении в одну сторону и одинаковые - при вращении в другую.
    Это дребезг + несимметричность в энкодере, если бы не его странный код с печатью раз в секунду.
    Я глубже не погружался, но очень странно, что все начали ему про энкодер рассказывать, который тут вообще ни при чем.

ЗЫ: я человеку предложил печатать без прерываний каждое изменение на пине и счетчик изменений, но он “мимо ушей пропустил”. А так можно было бы увидеть несимметричность и дребезг.

1 лайк

Не по теме твоей ветки, но будет полезно.

на есп 32 не стоит вообще заморачиваться прерываниями, там есть специальная периферия для энкодера. PCNT - счетчик импульсов. Два канала, со счетчиками. То есть контроллер энкодера в ЕСП32 железный, встроенный и не занимает прерывания или чего-то еще.

1 лайк

А зачем ты именно мне об этом пишешь?
Мое первое сообщение в этой теме за номером 90.
Так что если уж “все начали”, то это без моего участия. Я лишь продолжил.

И потом, мне кажется очень странным утверждение, что “ТС про энкодер ничего не спрашивает.” когда тема называется “Как работает энкодер?”. Или ты считаешь, что название темы придумал не ТС, а кто-то другой?

надо делать правильно, а анализировать глюки нет смысла

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

Название не соответствует вопросу. Вопрос задан в первом сообщении.
Тебе я написал потому, что ты очень ярко пытался объяснить человеку то, о чем он не спрашивал. Суть его вопроса на “общетехнический” я перевел выше.
Ты же всегда был очень дотошным. Я удивился, что ты (возможно) не прочитал вопрос ТС, а стал рассказывать про энкодер.

Скажи мне, почему фраза “Как работает энкодер?” не соответствует твоим представлениям о том, что является вопросом.

Ну что, мальчишки и девчонки, а также их родители? Веселые истории услышать не хотите ли?

История первая.
Берем код из сообщения #41, новый энкодер KY-040 и плавно вращаем сначала влево, а потом вправо:

clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
clk = 1
on last interrup clk was 0
clk = 1
on last interrup clk was 0
clk = 1
...

Я даже не могу сказать точно, где тут кончается “влево” и начинается “вправо” - поскольку никакой разницы между направлениями обнаружить не удалось. Как и должно быть, если мы читаем только один пин.
Так что никаких загадок вообще.

Вот, как раз МММ о “таком” расказывает)))

Надеюсь сами удостоверитесь

История 2
Как выглядят повороты энкодера на логик анализере
Вправо


Влево

Как видите, в одному случае при спаде CLK значение DT =1, в другую сторону - ноль. Направление вращения определить просто - нужно читать в прерывании по одному каналу состояние ДРУГОГО.

Я признаю, что не сразу понял что в данном энкодере замыкание контактов на массу происходит только в момент “щелчка” на очень короткий момент. Все остальное время контакты подтянуты к питанию.

И история 3

Почему вы всегда видим в прерывании на CLK ноль

Из-за конструкции энкодера (см предыдущее сообщение) - первое прерывание после покоя всегда по спаду CLK. Это прерывание код ТС успешно ловит и отправляет на печать. Мы видим строчку

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

Фокус в том, что это самый обычный энкодер из набора ардуино, а ведь 116 пост уже обсуждаем))

Спойлер

Получается, Вы так и не поняли вопроса ТС? Второе прерывание и не важно, ТС удивлялся, почему у него сразу после спада читается 1, хотя ожидается 0. Ваш опыт(а также мои примеры в wokwi ) ясно доказывают, что налицо
железная проблема и к логике работы энкодера отношение не имеет

Прежде чем отвечать, нужно проверить - а есть ли проблема.

Вот я и проверил -
у меня с его кодом никакой 1 не читается, и направо и налево читается только ноль.

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

еще я не могу понять где в коде нужно поправить что бы он выдавал сигнал не 1-255 или 1- 65000 а только низкий и высакий
это конечно не во нешнем прерыватели. там все понятно. и еще заметил что с аналового пинов a0. a1. сигнал считывается легче чем с чем с псевдо аналоговых 2,3,4,9,10 с них хуже у меня есть еще два рабочих кода один работает только с аналоговым. другой на пид прерываниях я их сейчас изучаю
я прошу помощи для переделки одного из кодов для считывания только двух сигналов 1 и -1 или 1,0,-1 а пока он сзаписывает их 1-255 или1-65000 как я пропишу это . я его тоже хочу испытать для состовной части моего проекта .
внешний прерыватель я ему такой поставил только на 1 -1 но он пишет 1-255
как исправить в коде ? помогите кто понимает.

ДА , ЗАБЫЛ НАПИСАТЬ .
ВНЕШНЕЕ ПРЕРЫВАНИЯ Я ДОБАВИЛ

attachInterrupt(1, loop, FALLING)

ПОЧЕМУ ,FALLING’’ ДЛЯ НАГЛЯДНОСТИ ЕСТЬ РАЗНИЦА И ВСЕ .


/* Rotary encoder read example */работает только на аналоговых пинах
#define ENC_A A0 // Analog A0 encoder Data 
#define ENC_B A1 // Analgo A1 encoder Clock 
#define ENC_PORT PINC
 
void setup()
{
  /* Setup encoder pins as inputs */
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);
  Serial.begin (9600);
  Serial.println("Start");
}
 
void loop()
{
 static uint8_t counter = 0;      //this variable will be changed by encoder input
 int8_t tmpdata;
 /**/
  tmpdata = read_encoder();
  if( tmpdata ) {
    Serial.print("Counter value: ");
    Serial.println(counter, DEC);
    counter += tmpdata;
  }
}
 
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}

Ребята, ну, может, мы все-таки начнем читать книжки и использовать общепринятую терминологию, а не изобретать свою?
Нет в энкодере никакого CLK.
Ну режет глаза, честное слово.

Энкодеры попадаются совершенно разной конструкции.


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

Для кого даже это не аргумент, замечу, что

его ротор может быть остановлен в любом положении, не обязательно на “щелчке”.

Вот самый обычный энкодер из набора Ардуино:


И таких энкодеров тьма тьмущая самой разной конструкции.

Ну вот как раз и пример “не совсем обычного энкодера для Ардуино”.
Это к тому, что нужно писать код, который будет работать с любым энкодером, а не только с “обычным для Ардуино”.

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

Это разумное поведение.
Могу порекомендовать проверенный и исправнео работающий код “от Леонида Ивановича”.

//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
volatile int enc;
void setup(){                
Serial.begin(9600);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
PCIFR=PCIFR; PCICR=1<<PCIE1; //разрешить прерывание
PCMSK1=1<<PCINT8 | 1<<PCINT9; //выбрать вход на котором сработает прерывание 
}

ISR(PCINT1_vect){
static char EncPrev=0;      //предыдущее состояние энкодера
static char EncPrevPrev=0;  //пред-предыдущее состояние энкодера
  char EncCur = 0;
  if(!(PINC & (1 << PC0))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
  if(EncCur != EncPrev)             //если состояние изменилось,
  {
    if(EncPrev == 3 &&        //если предыдущее состояние 3
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == 2)          //если текущее состояние 2,
        enc++;            //шаг вверх
      else                          //иначе
        enc--;            //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }


  }



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

Этот код можно обобщить и на большее количество энкодеров. В частности, в одном из моих проектов энкодеров было 5 штук.

Это можно сделать разными способами, например, взять остаток от деления по модулю 2. Или даже просто логическ4им отрицанием, вот так: counter = !counter.
Все зависит от того, каких целей Мы хотим достичь. Но мне кажется, что в любом случае он при этом перестанет выполнять функции энкодера.

Очень интересно.
Пишите еще.