Андрей Смирнов
Время чтения: ~11 мин.
Просмотров: 1

Как подключить энкодер к ардуино

Принципиальная схема подключения энкодера к преобразователю частоты

Данная схема состоит из платы Arduino Uno, инкрементального энкодера, четырехразрядного светодиодного индикатора, ключевых транзисторов и ограничительного резистора. Эта схема называется счетчиком импульсов. Она считает импульсы, которые будет воспроизводить энкодер при его вращении. Энкодер своими выводами подключен к каналам А2 и А3, вывод кнопки подключен к выводу А4, средний вывод подключен к земле, второй вывод тоже к земле.

Рассмотрим скетч, который называется счетчиком импульсов энкодера управления частотника. Вначале подключаем библиотеки для работы таймера, индикатора LS, для работы с энкодером, для кнопки.

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

Если нажимаем на кнопку индикатора, переменная обнулится, на индикаторе будет ноль.

Монтаж и подключение датчиков поворота

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

Важно прочно закрепить корпус датчика при монтаже

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

Варианты подключения

В самом простом варианте, энкодер подключают к счетчику, запрограммированному измерять скорость.

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

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

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

После подключения желательно проверить все мультиметром.

Arduino Code – Reading Rotary Encoders

Now that you have your encoder hooked up you’ll need a sketch to make it all work.

The following sketch detects when the encoder is being rotated, determines which direction it is being rotated and whether or not the button is being pushed.

Try the sketch out; and then we will dissect it in some detail.

If everything is fine, you should see below output on serial monitor.

If the rotation being reported is the opposite of what you expect, try swapping the CLK and DT lines.

Code Explanation:

The sketch begins with the declaration of the Arduino pins to which the encoder’s CLK, DT and SW pins are connected.

Next, a few integers are defined. The variable represents the count that will be modified each time that the knob is rotated one detent (click).

The and variables hold the state of the CLK output and are used for determining the amount of rotation.

A string called will be used when printing the current direction of rotation on the serial monitor.

The variable is used to debounce a switch.

Now in the Setup section, we first define the connections to the encoder as inputs, then we enable the input pullup resistor on SW pin. We also setup the serial monitor.

At the end we read the current value of the CLK pin and store it in the variable.

In the loop section, we check the CLK state again and compare it to the value. If they are different then it means that the knob has turned and a pulse has occurred. We also check if the value of is 1 in order to react to only one state change to avoid double count.

Inside the if statement we determine the direction of rotation. To do this we simply read the DT pin on the encoder module and compare it to the current state of the CLK pin.

If they are different, it means that the knob is rotated counterclockwise. We then decrement the counter and set to “CCW”.

If the two values are the same, it means that the knob is rotated clockwise. We then increment the counter and set to “CW”.

We then print our results on the serial monitor.

Outside the if statement we update with the current state of CLK.

Next comes the logic to read and debounce the push button switch. We first read the current button state, if it’s LOW, we wait for 50ms to debounce the push button.

If the button stays LOW for more than 50ms, we print “Button pressed!” message on the serial monitor.

Then we do it all over again.

Source Code

Here’s the Arduino code:

/*     Arduino Rotary Encoder Tutorial
 *      
 *  by Dejan Nedelkovski, www.HowToMechatronics.com
 *  
 */
 
 #define outputA 6
 #define outputB 7

 int counter = 0; 
 int aState;
 int aLastState;  

 void setup() { 
   pinMode (outputA,INPUT);
   pinMode (outputB,INPUT);
   
   Serial.begin (9600);
   // Reads the initial state of the outputA
   aLastState = digitalRead(outputA);   
 } 

 void loop() { 
   aState = digitalRead(outputA); // Reads the "current" state of the outputA
   // If the previous and the current state of the outputA are different, that means a Pulse has occured
   if (aState != aLastState){     
     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
     if (digitalRead(outputB) != aState) { 
       counter ++;
     } else {
       counter --;
     }
     Serial.print("Position: ");
     Serial.println(counter);
   } 
   aLastState = aState; // Updates the previous state of the outputA with the current state
 }

Description of the code: So first we need to define the pins to which our encoder is connected and define some variables needed for the program. In the setup section we need to define the two pins as inputs, start the serial communication for printing the results on the serial monitor, as well as read the initial value of the output A and put the value into the variable aLastState.

Then in the loop section we read the output A again but now we put the value into the aState variable. So if we rotate the encoder and a pulse is generated, these two values will differ and the first “if” statement will become true. Right after that using the second “if” statement we determine the rotation direction. If the output B state differ from the output A state the counter will be increased by one, else it will be decreased. At the end, after printing the results on the serial monitor, we need to update the aLastState variable with aState variable.

That’s all we need for this example. If upload the code, start the Serial Monitor and start rotating the encoder we will start getting the values in the serial monitor. The particular module that I have makes 30 counts each full cycle.

Чтение порта микроконтроллера и программная защита от помех (цифровой фильтр)

Рассмотрим обработку порта PА.

Всего энкодер EP50S8-720-2F-N-5 имеет 10 проводников (разрядность 10 бит) для обеспечения 720 чисел на 1 оборот. Теперь будет читать каждый из разрядов порта (не забудем выполнить инверсию порта ~GPIOA->IDR — т.к. у нас выполнена подтяжка резисторами к питанию). Младший разряд, подключаемый к PA4 мы сдвигаем на 4 разряда вправо для получения правильного конечного числа (GPIO_IDR_IDR4>>4). И самый старший разряд мы сдвигает влево на 9 (GPIO_IDR_IDR0<<9), т.к. соответствующий провод энкодера подключен к PA0, а должен соотноситься к 10 биту. Можно было бы подключить какой-либо провод к другому порту, например PВ и выполнить процедуру чтения из ноги PB0: ((~GPIOВ->IDR & GPIO_IDR_IDR0)<<9). В этом заключается универсальность процедуры чтения.

Цикл for(uint8_t i = 0; i <= 200; i++) необходим для 200-кратного подтверждения установки значения энкодера равного 55. Это своеобразный цифровой фильтр от помех, которые неизбежно могут возникнуть в 10 проводной параллельной линии связи.

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

Промышленный абсолютный энкодер

Промышленные абсолютные энкодеры служат для точного позиционирования механизмов и, в частности, валов электрических двигателей, в том числе на испытательных стендах для подсчета частоты вращения двигателей.Они бывают инкрементные с простым тиканьем шагов при повороте и абсолютные с выдачей конкретного числа на каждом шаге — угле поворота. Сегодня мы рассмотрим работу с абсолютным энкодером, имеющим разрешение 720 положений. Это соответствует угловому шагу (точности) 360/720 =½ градуса. Абсолютные энкодеры бывают с различными напряжениями питания и интерфейсами подключения. Рассмотрим варианты интерфейсов энкодеров.

Абсолютный энкодер практически не подвержен помехам, если сам не поврежден. Если диск энкодера не может полноценно быть считан (считываются только его старшие разряды) из-за слишком быстрого вращения, то при уменьшении скорости вращения угол поворота будет вычислен точно (будет возможность вычисления младших разрядов). Таким образом, точность считывания положения падает при увеличении скорости вращения вала выше декларируемой. Абсолютный энкодер относительно устойчив к вибрациям ввиду отсутствия подсчета импульсов.

Подключение инкрементного энкодера к Ардуино

пример создания такого меню

  • CLK и DT — выводы энкодера, они подтянуты к линии питания резисторами 10кОм;
  • SW — вывод кнопки, при нажатии вывод замыкается на землю;
  • + и GND — линии питания и земли. Данный энкодер является механическим, питание для него не требуется, линии нужны для цепи с подтягивающими резисторами.

Подключим энкодер к Ардуино по следующей схеме:

ссылка

#define pin_CLK 2
#define pin_DT  4
#define pin_Btn 3

unsigned long CurrentTime, LastTime;
enum eEncoderState {eNone, eLeft, eRight, eButton};
uint8_t EncoderA, EncoderB, EncoderAPrev;
int8_t counter;
bool ButtonPrev;

eEncoderState GetEncoderState() {
  
  eEncoderState Result = eNone;
  CurrentTime = millis();
  if (CurrentTime - LastTime >= 5) {
    
    LastTime = CurrentTime;
    if (digitalRead(pin_Btn) == LOW ) {
      if (ButtonPrev) {
        Result = eButton; 
        ButtonPrev = ;
      }
    }
    else {
      ButtonPrev = 1;
      EncoderA = digitalRead(pin_DT);
      EncoderB = digitalRead(pin_CLK);
      if ((!EncoderA) && (EncoderAPrev)) { 
        if (EncoderB) Result = eRight;     
        else          Result = eLeft;      
      }
      EncoderAPrev = EncoderA; 
    }
  }
  return Result;
}

void setup() {
  pinMode(pin_DT,  INPUT);
  pinMode(pin_CLK, INPUT);
  pinMode(pin_Btn, INPUT_PULLUP); 
  Serial.begin(9600);
  counter = ;
}

void loop() {
  switch (GetEncoderState()) {
    case eNone: return;
    case eLeft: {   
        counter--;
        break;
      }
    case eRight: {  
        counter++;
        break;
      }
    case eButton: { 
        counter = ;
        break;
      }
  }
  Serial.println(counter);
}
EncoderA = digitalRead(pin_CLK);
EncoderB = digitalRead(pin_DT);

Обработка сигналов энкодера с помощью прерываний

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

В Atmega328 есть два типа прерываний, которые можно использовать для этих целей; внешнее прерывание и прерывание по изменению состояния вывода. Выводы и назначены на внешнее прерывание, а — назначены на прерывание по изменению состояния вывода. Внешнее прерывание может определить, произошел ли спад или нарастание входного сигнала, и может быть запущено при одном из следующих состояний: нарастание, спад или переключение. Для прерывания по изменению состояния выводов существует гораздо больше аппаратных ресурсов, но оно не может обнаруживать нарастающий и спадающий фронты, и оно вызывается, когда происходит любое изменение логического состояния (переключение) на выводе.

Чтобы использовать прерывание по изменению состояния выводов, подключите выходы поворота энкодера A и B к выводам и , а выход кнопки – к выводу платы Arduino, как показано на принципиальной схеме. Установите выводы , и в режим входа и включите их внутренние подтягивающие резисторы. Включите прерывание по изменению состояния выводов в регистре и включите прерывания для выводов , и в регистре . При обнаружении любого изменения логического состояния на одном из этих входов будет вызовано (прерывание по изменению состояния выводов).

Поскольку прерывание по изменению состояния выводов вызывается для любого логического изменения, нам необходимо отслеживать оба сигнала (и A, и B) и обнаруживать вращение при получение ожидаемой последовательности. Как видно из диаграммы сигналов, движение по часовой стрелке генерирует и . Когда мы записываем оба сигналы в байты и , сдвигая последнее чтение вправо, мы можем сравнить эти значения и определить новый шаг вращения.

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

Использование внешнего прерывания делает процесс более простым, но поскольку для этого прерывания назначено только два вывода, то вы не сможете использовать его для других целей, если займете его энкодером. Чтобы использовать внешнее прерывание, вы должны установить выводы 2 () и 3 () в режим входа и включить их внутренние подтягивающие резисторы. Затем выберите вариант спадающего фронта для вызова обоих прерываний в регистре . Включите внешние прерывания в регистре . Когда начнется вращение вала энкодера, сначала ведущий сигнал падает до логического нуля, а второй сигнал некоторое время остается на уровне логической единицы. Поэтому нам нужно определить, какой из сигналов во время прерывания находится в состоянии логической единицы. После того, как ведущий сигнал упал до логического нуля, через некоторое время второй сигнал также упадет до логического нуля, что вызовет другое прерывание. Но этот раз и другой (ведущий) сигнал будет на низком логическом уровне, что означает, что это не начало вращения, поэтому мы игнорируем его.

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

Макет для проверки кода работы с инкрементальным поворотным энкодером на Arduino

Полный код скетча Arduino, включающий основной цикл приведен ниже:

Энкодер в действии вы можете увидеть на видео, приведенном ниже:

Вот и всё! Надеюсь, статья оказалась полезной. Оставляйте комментарии!

Рейтинг автора
5
Материал подготовил
Максим Иванов
Наш эксперт
Написано статей
129
Ссылка на основную публикацию
Похожие публикации