#1 2017-04-03 10:13:31

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

энкодер это просто

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

Выглядит это так :

b11ecc1s-960.jpg



Схематично можно изобразить так :

411ecc1s-960.jpg
211ecc1s-960.jpg


Внутри энкодер устроен примерно так :

7e1ecc1s-960.jpg


Из увиденного понятно, что для определения направления вращения ротора нужно определить очередность замыканий контактов "А" и "В" с контактом "С".

Ниже ссылки на скетчи которые это выполняют.

= в первом варианте используется прерывание

/*
**********	Pin - D -	**********
Arduino 00 – ATmega pin 02/0 – 
Arduino 01 – ATmega pin 03/1 – 
Arduino 02 – ATmega pin 04/2 – CLK - A энкодера
Arduino 03 – ATmega pin 05/3 – DT  - B энкодера
Arduino 04 – ATmega pin 06/4 – 
Arduino 05 – ATmega pin 11/5 – 
Arduino 06 – ATmega pin 12/6 – 
Arduino 07 – ATmega pin 13/7 – 
**********	Pin - B -	**********
Arduino 08 – ATmega pin 14/0 – 
Arduino 09 – ATmega pin 15/1 – 
Arduino 10 – ATmega pin 16/2 – 
Arduino 11 – ATmega pin 17/3 – 
Arduino 12 – ATmega pin 18/4 – 
Arduino 13 – ATmega pin 19/5 – 
Arduino RC – ATmega pin 09/6 – (ZQ)
Arduino RC – ATmega pin 10/7 – (ZQ)
**********	Pin - C -	**********
Arduino 14_A0 – ATmega pin 23/0 – 
Arduino 15_A1 – ATmega pin 24/1 – 
Arduino 16_A2 – ATmega pin 25/2 – 
Arduino 17_A3 – ATmega pin 26/3 – 
Arduino 18_A4 – ATmega pin 27/4 – 
Arduino 19_A5 – ATmega pin 28/5 – 
****************************************************
****************************************************
Dx_Out;  	- установка пина Х как выход
Dx_In; 		- установка пина Х  как вход
Dx_High;	- установка высокого уровна на пине Х
Dx_Low; 	- установка низкого уровня на пине Х
Ax_Read; 	- чтение аналогового пина Х
****************************************************
****************************************************
if ((PIND&(1<<2)) == 0) {} 	// если на пин *2D* лог 0
if ((PIND&(1<<2)) != 0) {}	// если на пин *2D* лог 1

PORTD |= (1<<2); 	// установить на пин *2D* лог 1
PORTD &=~ (1<<2); 	// установить на пин *2D* лог 0
PORTD ^= (1<<2); 	// инвертировать состо¤ние пин *2D*
****************************************************
****************************************************
*/

unsigned long currentTime;
unsigned long loopTime;
boolean e_B, e_A, spin;
 
void setup()  {
  Serial.begin(57600);
  Serial.println("  KY-040 Encoder Test Interrupt ");
  
  DDRD = B00000000; 			// назначает выводы со 0 по 7 входными 
	PORTD = B11111111;			// устанавливает на цифровых выводах с 0 по 7 HIGH
		DDRB = B111111;			// назначает вывод с 8 по 13 выходными
		PORTB = B000000;		// устанавливает на выводах с 8 по 13 LOW
			DDRC = B000011;		// назначает выводы с 14 по 15 выходными, с 16 по 19 входными
			PORTC = B100000;	// устанавливает  на выводах с 14 по 18 LOW, с 19 HIGH
// определяем внешнее прерывание на выводе 2  
   attachInterrupt(0, KY040, FALLING);
  } 
 
void loop()  {

 }
  
void KY040() {
if( millis() < (loopTime + 4) ) { return; }
loopTime = millis();
// считываем состояние выхода А и В энкодера 
e_B = PIND&(1<<3);	e_A = PIND&(1<<2);

// выход В = 1, значит вращение против часовой стрелки       
	if((e_B && !e_A) && spin) { f01(); Serial.println(" counter-clockwise "); }   
	if(e_B && !e_A) { spin = true; }	
    
// выход В = 0, значит вращение по часовой стрелке     
	if((!e_B && !e_A) && !spin) { f02(); Serial.println(" clockwise "); }   	
	if(!e_B && !e_A) { spin = false; }	

	}
	
void f01() { PORTB |= (1<<5); }	
	
void f02() { PORTB &=~ (1<<5); }	
 
KY040 Encoder_203.txt
Открыть с помощью
KY040 Encoder_203.txt. На экране.

= в этом скетче реализация без прерываний

/*
**********	Pin - D -	**********
Arduino 00 – ATmega pin 02/0 – 
Arduino 01 – ATmega pin 03/1 – 
Arduino 02 – ATmega pin 04/2 – 
Arduino 03 – ATmega pin 05/3 – 
Arduino 04 – ATmega pin 06/4 – 
Arduino 05 – ATmega pin 11/5 – CLK - A энкодера
Arduino 06 – ATmega pin 12/6 – DT  - B энкодера
Arduino 07 – ATmega pin 13/7 – 
**********	Pin - B -	**********
Arduino 08 – ATmega pin 14/0 – 
Arduino 09 – ATmega pin 15/1 – 
Arduino 10 – ATmega pin 16/2 – 
Arduino 11 – ATmega pin 17/3 – 
Arduino 12 – ATmega pin 18/4 – 
Arduino 13 – ATmega pin 19/5 – 
Arduino RC – ATmega pin 09/6 – (ZQ)
Arduino RC – ATmega pin 10/7 – (ZQ)
**********	Pin - C -	**********
Arduino 14_A0 – ATmega pin 23/0 – 
Arduino 15_A1 – ATmega pin 24/1 – 
Arduino 16_A2 – ATmega pin 25/2 – 
Arduino 17_A3 – ATmega pin 26/3 – 
Arduino 18_A4 – ATmega pin 27/4 – 
Arduino 19_A5 – ATmega pin 28/5 – 
****************************************************
****************************************************
Dx_Out;  	- установка пина Х как выход
Dx_In; 		- установка пина Х  как вход
Dx_High;	- установка высокого уровна на пине Х
Dx_Low; 	- установка низкого уровня на пине Х
Ax_Read; 	- чтение аналогового пина Х
****************************************************
****************************************************
if ((PIND&(1<<2)) == 0) {} 	// если на пин *2D* лог 0
if ((PIND&(1<<2)) != 0) {}	// если на пин *2D* лог 1

PORTD |= (1<<2); 	// установить на пин *2D* лог 1
PORTD &=~ (1<<2); 	// установить на пин *2D* лог 0
PORTD ^= (1<<2); 	// инвертировать состо¤ние пин *2D*
****************************************************
****************************************************
*/

#include "CyberLib.h"
unsigned long currentTime;
unsigned long loopTime;
byte e_A, e_B;
byte e_A_prev=0;
 
void setup()  { 
  Serial.begin(57600);
  Serial.println("  KY-040 Encoder Test  ");
  	D5_In; D6_In;		// назначает выводы 5 и 6 входными 
	D5_High; D6_High;	// устанавливает на 5 и 6 HIGH
	D13_Out; D13_Low;	// конфигурация СД на 13 выводе
  } 
 
void loop()  {
// проверяем каждые 4мс  
  if( millis() >= (loopTime + 4) ) {
// считываем состояние выхода А и В энкодера   
    e_A = D5_Read;	e_B = D6_Read;
	
// если состояние А изменилось с положительного к нулю	
    if( e_A_prev && !e_A ){
// выход В в 1 сост., значит вращение против часовой стрелки      
	  if(e_B) { f01(); Serial.println(" counter-clockwise "); }
// выход В в 0 сост., значит вращение по часовой стрелке      
	  if(!e_B) { f02(); Serial.println(" clockwise "); }   
						}
// ждем значение А = 1 для следующего цикла 										
	e_A_prev = e_A;			
    loopTime = millis();
 }
	}
 
void f01() { PORTB |= (1<<5); }	
	
void f02() { PORTB &=~ (1<<5); } 
 
KY040 Encoder_103.txt
Открыть с помощью
KY040 Encoder_103.txt. На экране.

Всем удачных проектов !

Неактивний

#2 2017-05-24 12:47:05

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

Небольшое дополнение ...

2017_05_24_121929.jpg


как это работает...


Неактивний

#3 2017-07-06 13:32:40

goodspeedmen
Учасник
З https://discord.gg/6hbs98y
Зареєстрований: 2016-10-02
Повідомлень: 81

Re: энкодер это просто

Вы бы не могли объяснить логику последнего кода?

Неактивний

#4 2017-07-07 20:59:17

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

goodspeedmen пише:

Вы бы не могли объяснить логику последнего кода?

Наверное мог бы...

Неактивний

#5 2017-07-08 14:09:28

goodspeedmen
Учасник
З https://discord.gg/6hbs98y
Зареєстрований: 2016-10-02
Повідомлень: 81

Re: энкодер это просто

boolean A_inc, B_inc, cw_T, cww_T;
=======================================

 A_inc = (digitalRead(2));
 B_inc = (digitalRead(3));
 
 if(A_inc == B_inc)
   {
	cw_T = A_inc;
	cww_T = B_inc;
   }
   
 if(cw_T != A_inc)
   {
	cw_T = A_inc;
    
	if(Selection_flag == 0)
	  {
       if(setTemp <= 450)
	     {
	      setTemp+=10;
	     }
	  }
	if(Selection_flag == 1)
      {
       if(set_Temp <= 450)
	     {
	      set_Temp+=10;
	     } 
      }
	if(Selection_flag == 2)
      {
       if(set_Cooler <= 225)
	     {
	      set_Cooler+=30;	
	     }
   }

}
я написал ваш код так и у меня считает по 20 хотя инкремент как можете видеть по 10 единиц. Если я кручу энкодер оооочень медленно по шагу то действительно инкремент происходит по 10 единиц. два инкремента за шаг

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

Неактивний

#6 2017-07-08 16:44:27

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

goodspeedmen пише:

я написал ваш код так и у меня считает по 20 хотя инкремент как можете видеть по 10 единиц.

Это НЕ мой код... это кусок какого-то вашего кода...

Если хотите изменить "шаг" то просто поменяйте значение с 1 на 10 в моем коде...

Неактивний

#7 2017-07-08 17:01:25

goodspeedmen
Учасник
З https://discord.gg/6hbs98y
Зареєстрований: 2016-10-02
Повідомлень: 81

Re: энкодер это просто

я вроде не где не ошибся но почему инкремент 20 за шаг? смотрел стандартные примеры там вообще 4 mad

Неактивний

#8 2017-07-08 22:45:29

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

goodspeedmen пише:

я вроде не где не ошибся но почему инкремент 20 за шаг? смотрел стандартные примеры там вообще 4 mad

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

Неактивний

#9 2017-07-09 16:58:34

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

Вячеслав Азаров пише:

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

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

Неактивний

#10 2017-07-09 20:31:39

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

Вячеслав Азаров пише:

Вообще то, даже механический энкодер не должен обрывать цепь. Шуметь имеет право а рвать цепь - нет. Это как старый переменный резистор. Я сегодня возился со старым японским щеточным энкодером. Шумит но цепь не обрывает.  А на счет кода - у меня нет желания вникать и  исправлять все у всех.

Так там и скетча собственно нет, чтобы смотреть и тем более править ... smile

У меня тоже энкодеры работают нормально, даже с "двойной точностью" (см. видео)...

Неактивний

#11 2017-07-09 23:09:48

Green
Учасник
Зареєстрований: 2015-11-08
Повідомлень: 593

Re: энкодер это просто

renoshnik пише:

У меня тоже энкодеры работают нормально, даже с "двойной точностью" (см. видео)...

"Сам себя не похвалишь..." Тоже верно. Как и конденсаторы.

Неактивний

#12 2017-07-10 07:33:35

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: энкодер это просто

Green пише:
renoshnik пише:

У меня тоже энкодеры работают нормально, даже с "двойной точностью" (см. видео)...

"Сам себя не похвалишь..." Тоже верно. Как и конденсаторы.

А, что делать если это так и есть ...

Неактивний

#13 2017-07-10 14:27:16

goodspeedmen
Учасник
З https://discord.gg/6hbs98y
Зареєстрований: 2016-10-02
Повідомлень: 81

Re: энкодер это просто

Я переписал ваш код более понятными мне названиями, инкремент происходит в начале шага и в конце, если крутить медленно то это можно увидеть. Какой код вы хотите увидеть? Я написал ту часть которая относится к энкодеру (инкремент, декремент точно такой же), зачем вам мои светодиоды и прочие? sad

Неактивний

#14 2017-07-12 13:35:24

goodspeedmen
Учасник
З https://discord.gg/6hbs98y
Зареєстрований: 2016-10-02
Повідомлень: 81

Re: энкодер это просто

11-07-2017-19-13-06.jpg

Колдовал я колдовал и наколдовал вот такое самое интересное что в Proteus работает в реальности считает только в минус, но судя по снятой диаграмме должно работать mad и в чем причина не понятно...


int counter = 0; 
void setup()  
{
  Serial.begin(57600);
  Serial.println("Encoder - Interrupt");

  DDRD =  B00000000;      //  
  PORTD = B11111111;      // 
  DDRB =  B111111;          // 
  PORTB = B000000;          // 

//INT0 PD2. Mode: Falling Edge. INT1 PD2. Mode: off
EICRA=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (1<<INT0);
EIFR=(0<<INTF1) | (1<<INTF0);
PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
  } 
 
void loop()  
{

  if((digitalRead(2) == 1) && (digitalRead(3) == 1)){EIMSK |= (1<<INT0);}  
  
}


ISR(INT0_vect)  //INT0 PD2. Mode: Falling Edge. \
 { 

 if((digitalRead(2) == 0) && (digitalRead(3) == 0)) {counter++; Serial.println(counter);}
 if((digitalRead(2) == 0) && (digitalRead(3) == 1)) {counter--; Serial.println(counter);}
 EIMSK &=~ (0<<INT0);

 }

12-07-2017-13-29-24.jpg

Остання редакція goodspeedmen (2017-07-12 13:40:20)

Неактивний

#15 2020-02-18 20:13:10

Latifun
Учасник
Зареєстрований: 2020-02-18
Повідомлень: 1

Re: энкодер это просто

Я недавно приобрел энкодер  h.264/avc hd arcotel enc-h410 https://klaster.ua/shop/televidenie/akt … rudovanie/ и он не разочаровал, крайне порадовал удобный интерфейс и благодаря этому настройка была не сложной даже для такого чайника как я) К тому же сжатие современное 1920×1080p за адекватную стоимость, потому если ищете оптимальное соотношение цена/качество, то это как раз об этом энкодере. Так же к плюсам можно отнести, что напряжение требует маленькое, около 220 В, с моей старой проводкой только такой и нужен. Потому если ищете экономически выгодный энкодер и при этом эффективный, то могу посоветовать именно этот.

Остання редакція Latifun (2020-02-20 22:03:26)

Неактивний

#16 2020-03-04 23:53:46

Жорж
Учасник
Зареєстрований: 2019-02-23
Повідомлень: 14

Re: энкодер это просто

Latifun, це стьоб такий ?)

Неактивний

#17 2020-03-05 01:48:59

vvr
Учасник
Зареєстрований: 2015-04-12
Повідомлень: 874

Re: энкодер это просто

нет. это просто спам....

Неактивний

#18 2020-03-05 10:37:23

YK
Учасник
Зареєстрований: 2020-02-26
Повідомлень: 27

Re: энкодер это просто

Я так понимаю что правильное определение вращения это последовательность замыкания и РАЗМЫКАНИЯ контактов
Почему бы не сделать что то  так (пример для первого кода от renoshnik)


unsigned long history=0;
void KY040() {

e_B = PIND&(1<<3);    e_A = PIND&(1<<2);

history=(history <<1) | e_A ;
history=(history <<1) | e_B ;

// теперь можно смотреть последовательности замыканий размыканий
//например для вращения по часовой маска =B0101, т.е.
if(history & (B0101)){ Serial.println(" counter-clockwise ");};
if(history & (B1010)){ Serial.println(" clockwise ");};

//ну и можно "усилить" несколькими щелчками , типа B01010101  - явно крутим против часовой

}
P.S. я код не тестировал, возможно в битах ошибся, просто идея.
Ну и конечно не писать длинных обработчиков в прерываниях, тот же Serial.print уже может быть проблемой, например историю можно анализировать в loop

Неактивний

#19 2020-03-05 12:00:59

Watchdog
Гість

Re: энкодер это просто

YK пише:

... можно анализировать в loop

Можно если loop выполняется не дольше длительности импульсов энкодера. Эта штука называется квадратурный энкодер. Погуглите - полезно.

#20 2020-03-05 12:13:34

YK
Учасник
Зареєстрований: 2020-02-26
Повідомлень: 27

Re: энкодер это просто

Watchdog пише:
YK пише:

... можно анализировать в loop

Можно если loop выполняется не дольше длительности импульсов энкодера. Эта штука называется квадратурный энкодер. Погуглите - полезно.

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

Неактивний

#21 2020-03-05 12:47:00

Watchdog
Гість

Re: энкодер это просто

YK пише:

Принципиально не согласен. ...

Я спорить, с вами, не буду. Лучше достигните согласия со своей программой.

#22 2020-03-06 00:26:01

Xy
Гість

Re: энкодер это просто

Ничего не понял , по моему было предложено хорошее техническое решение, а тут какое то согласие требуется
Я так понимаю форум технический , а не выяснение личностей, если так опровергайте грамотно , или бегите в другую ветку

#23 2020-03-06 00:42:52

Guest1
Гість

Re: энкодер это просто

Согласен, пусть выкладывает код , а не предложения гуглить , все мы гуглим ......раз тема начата обсуждаем код
Гуглим в других местах smile

#24 2020-03-06 06:06:17

Код
Гість

Re: энкодер это просто

Xy пише:

Я так понимаю форум технический , а не выяснение личностей ...

Религиозный!

Guest1 пише:

Согласен, пусть выкладывает код ...

Пусть; "А может вам и ключи от квартиры, где деньги лежат"? Обычно, говорят пожалуйста.

#25 2020-03-06 08:12:33

Watchdog
Гість

Re: энкодер это просто

Guest1 пише:

...раз тема начата обсуждаем код
Гуглим в других местах smile

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

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму