asis-kbr.ru

автоматические системы и системы безопасности
Текущее время: 10 дек 2018, 13:08

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ 1 сообщение ] 
Автор Сообщение
 Заголовок сообщения: Обработка энкодера
СообщениеДобавлено: 21 апр 2015, 10:13 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 19 янв 2012, 12:52
Сообщения: 575
Откуда: KBR
Обработка энкодера от Леонида Ивановича.
Взял отсюда http://forum.easyelectronics.ru/viewtop ... 11#p393711

Код:
//----------------------------------------------------------------------------

//Модуль поддержки энкодера (процессор - STM32F100)

//----------------------- Используемые ресурсы: ------------------------------

//Сигналы энкодера F1 и F2 подключены к портам IO.
//Кнопка энкодера обрабатывается в другом модуле (keyboard.cpp).
//Используется программный опрос (поллинг).
//Аппаратная обработка энкодера на основе таймера
//не применяется по ряду причин:
//- нет подавления дребезга
//- тратится таймер
//- жестко привязываются выводы
//- теряется возможность сделать программное переключение
//  типа энкодера с другой разводкой F1, F2 и GND
//- все равно требуется программный поллинг таймера
//Подавление дребезга энкодера осуществляется на основе анализа стотояний.
//Переход между соседними состояниями не считается событием. Такая обработка
//возможна благодаря тому, что на один щелчок энкодера (на один период
//выходной последовательности) приходится 4 разных состояния.
//Поддерживается адаптивная скорость энкодера. Если измеренное количество
//шагов в секунду превышает пороговое значение ENC_MAX_V,
//то формируются коды событий быстрого инкремента или декремента.
//Специально для плохих энкодеров с большим дребезгом введен
//цифровой фильтр состояний и защита от реверса по таймеру.

//----------------------------------------------------------------------------

#include "main.h"
#include "encoder.h"
#include "data.h"

//------------------------------- Константы: ---------------------------------

#define ENC_MAX_V  14 //пороговая скорость энкодера, шагов в секунду
#define ENC_V_TM  100 //интервал измерения скорости энкодера, mS
#define ENC_R_TM   10 //интервал запрета реверса энкодера, mS

#define ENC_MAX_VC (ENC_MAX_V * 4 / (1000 / ENC_V_TM))

//----------------------------------------------------------------------------
//---------------------------- Класс TEncoder: -------------------------------
//----------------------------------------------------------------------------

//----------------------------- Конструктор: ---------------------------------

TEncoder::TEncoder(void)
{
  Pin_F1.Init(IN_PULL, PULL_UP);
  Pin_F2.Init(IN_PULL, PULL_UP);
  Message = ENC_NOP;
  EncPrev = STATE_0;
  EncPrevPrev = STATE_0;
#if ENC_FLT > 1
  for(char i = 0; i < ENC_FLT; i++)
    EncF[i] = STATE_0;
  FPtr = 0;
#endif 
  EncV = 0; EncS = 0;
  EncTimer = new TSoftTimer(ENC_V_TM);
  EncTimer->Autoreload = 1;
  RevTimer = new TSoftTimer(ENC_R_TM);
  RevTimer->Force();
  Dir = 0;
  Rev = 0;
}

//---------------------------- Опрос энкодера: -------------------------------

void TEncoder::Execute(void)
{
  if(EncTimer->Over())                //проверка таймера энкодера
  {
    EncV = EncS;                      //сохранение текущей скорости
    EncS = 0;
  }
  EncCur = STATE_0;
  if(Rev)
  {
    if(!Pin_F1) EncCur  = STATE_A;    //чтение фазы 1
    if(!Pin_F2) EncCur |= STATE_B;    //чтение фазы 2
  }
  else
  {
    if(!Pin_F1) EncCur  = STATE_B;    //чтение фазы 1
    if(!Pin_F2) EncCur |= STATE_A;    //чтение фазы 2
  }
#if ENC_FLT > 1
  EncF[FPtr] = EncCur;                //заполнение массива фильтра
  if(++FPtr == ENC_FLT) FPtr = 0;     //обновление указателя
  for(char i = 0; i < ENC_FLT; i++)
    if(EncF[i] != EncCur)             //если в массиве есть флуктуации,
      EncCur = EncPrev;               //запрещение обработки состояния
#endif
  if(EncCur != EncPrev)               //если состояние изменилось,
  {
    if(EncCur != EncPrevPrev)
      EncS++;                         //счет шагов для измерения скорости
    if(EncPrev == STATE_AB)
    {
      if(EncCur == STATE_A &&
         EncPrevPrev == STATE_B)
      {
        if(Dir || RevTimer->Over())
        {
          if(EncV >= ENC_MAX_V)       //если порог скорости достигнут, то
            Message = ENC_FAST_STEP;  //сообщение быстрого инкремента
              else                    //иначе
                Message = ENC_STEP;   //сообщение инкремента
          Dir = 1;
        }
        RevTimer->Start();
      }
      if(EncCur == STATE_B &&
         EncPrevPrev == STATE_A)
      {
        if(!Dir || RevTimer->Over())
        {
          if(EncV >= ENC_MAX_V)       //если порог скорости достигнут, то
            Message = -ENC_FAST_STEP; //сообщение быстрого декремента,
              else                    //иначе
                Message = -ENC_STEP;  //сообщение декремента
          Dir = 0;
        }
        RevTimer->Start();
      }
    }
    EncPrevPrev = EncPrev;            //сохранение пред-предыдущего сотояния
    EncPrev = EncCur;                 //сохранение предыдущего сотояния
  }
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------

//Модуль поддержки энкодера, заголовочный файл

//----------------------------------------------------------------------------

#ifndef ENCODER_H
#define ENCODER_H

//----------------------------------------------------------------------------

#include "systimer.h"

//------------------------------- Константы: ---------------------------------

#define ENC_NOP        0 //нет вращения
#define ENC_STEP       1 //нормальный шаг энкодера
#define ENC_FAST_STEP 10 //быстрый шаг энкодера
#define ENC_FLT        1 //размер массива цифрового фильтра

//----------------------------------------------------------------------------
//---------------------------- Класс TEncoder: -------------------------------
//----------------------------------------------------------------------------

class TEncoder
{
private:
  enum EncoderState
  {
    STATE_0,
    STATE_A,
    STATE_B,
    STATE_AB
  };
  TGpio<PORTA, PIN0> Pin_F1;
  TGpio<PORTA, PIN1> Pin_F2;
  char EncPrev;
  char EncPrevPrev;
  char EncCur;
  TSoftTimer *EncTimer;
  TSoftTimer *RevTimer;
  bool Dir;
  char EncV;
  char EncS;
#if ENC_FLT > 1
  char EncF[ENC_FLT];
  char FPtr;
#endif 
public:
  TEncoder(void);
  void Execute(void);
  bool Rev;
  int8_t Message;
};

//----------------------------------------------------------------------------

extern TEncoder *Encoder;

//----------------------------------------------------------------------------

#endif


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ 1 сообщение ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB