Использование промышленных оптических энкодеров в Arduino

30.10.2017 20:46

genaonyx



Введение

Здравствуйте, ранее мы рассказывали вам, как подключить энкодер к Arduino  и создать простейший счетчик импульсов. Примером тогда был механический энкодер KY-040 выполненный в виде модуля для Arduino.

Данный модуль хорошо подходит для пользовательского ввода информации. Навигации по различным меню, задание неких параметров и настроек, но вот использовать его например в станках непрактично. Энкодер быстро изнашивается, а при больших оборотах и вовсе разлетаться в щепки.

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

Далее же я хотел бы показать вам альтернативный скетч для работы с промышленными оптическими энкодерами.

Данный скетч обладает не только повышенной точностью, но способен считать импульсы на довольно приличных оборотах.

Так же необходимо учесть что для работы данного скетча необходима библиотека CyberLib. К сожалению данная библиотека работает не со всеми Arduino, на данный момент это Arduino UNO, Mega, Leonardo.

Собственно сам скетч ниже.


Скетч

// Подключаем библиотеку CyberLib.
#include "CyberLib.h"

// Куча вспомогательных переменных (вынесены за пределы функции прерываний, чтобы ускорить ее работу).
volatile unsigned char In0 = 0;
volatile unsigned char In1 = 0;
volatile unsigned char PredIn0 = 0;
volatile unsigned char PredIn1 = 0;
volatile unsigned char DG01_status = 0;
volatile long stepFront;
volatile bool flgcnt;

// Наш счетчик (т.к. мы ведем подсчет фронтов, то наш счетчик необходимо делить на 4).
volatile long counter = 0;

// Обработчик прерываний энкодера.
void encoders()
{
  In0 = D10_Read; //In0 - направление счета 1-го счетчика (10 порт)
  In1 = D11_Read;  //In1 - счетный вход 1-го счетчика (11 порт)
  if (PredIn1 != In1)
  {
    DG01_status |= 2;
    if (DG01_status != 3)
    {
      stepFront = 2;
      flgcnt = (In0 == 0);
    }
    else
    {
      stepFront = 1;
      if (In1 == 1) flgcnt = (In0 == 1); else flgcnt = (In0 == 0);
    }
    if (flgcnt) counter += stepFront; else counter -= stepFront;
    PredIn1 = In1;
  }
  if (PredIn0 != In0)
  {
    DG01_status |= 1;
    if (DG01_status != 3)
    {
      stepFront = 2;
      flgcnt = (In1 == 0);
    }
    else
    {
      stepFront = 1;
      if (In0 == 1) flgcnt = (In1 == 0); else flgcnt = (In1 == 1);
    }
    if (flgcnt) counter += stepFront; else counter -= stepFront;
    PredIn0 = In0;
  }
}

void setup()
{
  Serial.begin(9600);
  D10_In;
  D11_In;
  // Запоминаем состояния портов.
  In0 = PredIn0 = D10_Read;
  In1 = PredIn1 = D11_Read;
  // Запускаем прерывания.
  StartTimer1(encoders, 20);
}

void loop()
{
  // Выводим счетчик в монитор (т.к. мы ведем подсчет фронтов, то наш счетчик необходимо разделить на 4).
  Serial.println(counter / 4);
  // Используем delay_ms (библиотеки CyberLib), а не стандартный delay чтобы не мешать прерываниям.
  delay_ms(1000);
}


Смотрите также



Расскажи о нас

Сообщение

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