Перейти к содержанию
    

stm32 программный енкодер.

В 05.04.2023 в 23:11, xvr сказал:

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

На фронт (или спад - по вкусу) сигнала на одной фазе проверяем сигнал на другой. Если там 1 - инкрементриуем счётчик, иначе декрементируем (или наоборот - по вкусу).

Несмотря на много 'если' вверху многие энкодеры как раз такие (за исключением 'чистых сигналов' - но дребезг можно подавить отдельно)

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 05.04.2023 в 23:11, xvr сказал:

, то подсчёт можно сильно упростить

Три строки кода настолько сложны, что можно сильно упростить? 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, mitya1698 said:

Три строки кода настолько сложны, что можно сильно упростить? 

switch() весьма неудобен в реализации и весьма компиляторозависим (особенно, в плане оптимизации).

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

tmp = (EncState ^ EncInput) & 0b11;

if(tmp == 0b11)
    Error++;
else if(tmp == 0b01))
    StepD++;
else if(tmp == 0b10))
    StepD--;

EncState = tmp;

UPD прошу пардонов, писал по склерозу

const uint16_t StepDir 0x1442;

tmp = (EncState ^ EncInput) & 0b11;

if((tmp == 0b01) || (tmp == 0b10))
{
    if(StepDir & (1<<(tmp | (EncState << 2))))
        StepD++;
    else
        StepD--;
}

EncState ^= tmp;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 hours ago, mitya1698 said:

Три строки кода настолько сложны, что можно сильно упростить?

С пяти строк до двух- в 2.5 раза 🙂

if ((EncInput & ~EncState) & 1) Steps += (EncInput & 2) ? 1 : -1;
EncState = EncInput;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, xvr said:

С пяти строк до двух- в 2.5 раза 🙂

if ((EncInput & ~EncState) & 1) Steps += (EncInput & 2) ? 1 : -1;
EncState = EncInput;

 

Если EncInput - какой-нить volatile прямо из порта, то ...

И с ридабилитью сложно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 06.04.2023 в 12:30, xemul сказал:

писал по склерозу

Глючит на увеличении, два шага вперед, один назад.

На уменьшении нормально

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

33 minutes ago, mitya1698 said:

Глючит на увеличении, два шага вперед, один назад.

На уменьшении нормально

Дык у меня кроме склероза ещё и способности к устному счёту пониженные.

const uint16_t StepDir 0x2442;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

unsigned encoder_pool (conts uint8_t faza)
{
  static unsigned counter;
  static uint8_t sequence;
  if (0 != ((sequence ^ faza) & 3))
  {
    sequence = 0x3F & ((sequence << 2) + (faza & 3));
    if (0x12 == sequence) ++counter;
    if (0x21 == sequence) --counter;
  }
  return counter;
}
  

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 06.04.2023 в 18:41, xemul сказал:

способности к устному счёту пониженные.

Да, так работает и меньше моего с кэйсами.

В 06.04.2023 в 19:05, nibelung сказал:

Есть совсем простой код для обработки енкодера,

Ну так это тоже самое, только точность в 4 раза хуже.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, mitya1698 said:

Да, так работает и меньше моего с кэйсами.

if((tmp ^ (tmp>>1)) & 1)
{
    if((StepDir >> (tmp | (EncState << 2))) & 1)

должно быть ещё короче.

 

Не могу найти старый проект. 4 энкодера (без счётчиков) вписались с антидребезгом в 4 байта ОЗУ. В #define's были EncXChY и таблица истинности для состояний энкодера. Остальные magic numbers считались препроцессором.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 06.04.2023 в 19:54, mitya1698 сказал:

только точность в 4 раза хуже.

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

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

Спойлер
unsigned encoder_poll (const uint8_t faza)
{
  static unsigned counter;
  static uint8_t prior;
  uint8_t togle, dir;

  togle = prior ^ faza;
  dir = togle ^ (faza / 2) ^ faza;
  togle ^= togle / 2;
  prior = faza;
  
  if (1 & togle) (1 & dir) ? ++counter : --counter;
  //if ((1<<2) & togle) ((1<<2) & dir) ? ++counter2 : --counter2;
  //if ((1<<4) & togle) ((1<<4) & dir) ? ++counter3 : --counter3;
  //if ((1<<6) & togle) ((1<<6) & dir) ? ++counter4 : --counter4;

  return counter;
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В данном случае это одно и тоже.

Сохраню в копилку, вдруг где несколько опросных энкодеров понадобятся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...