Код обработки энкодера

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

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

Задача обработать два энкодера подключенных к Arduino Pro Micro.

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

#define encoder0PinA 2                   //вход А  пин 2 
#define encoder0PinB 3                   //вход B  пин 3
#define encoder0PinC 4                  //вход С  пин 4 
#define encoder0PinD 5                  //вход D  пин 5 

volatile long encoder0Pos = 0;        //  переменная в обработчике прерываний по подсчету импульсов 
volatile long encoder0Pos1 = 0;        //  переменная в обработчике прерываний по подсчету импульсов 

void setup() { 
  pinMode(encoder0PinA, INPUT);           
  pinMode(encoder0PinB, INPUT);  
  pinMode(encoder0PinC, INPUT);
  pinMode(encoder0PinD, INPUT);  

  attachInterrupt(0, doEncoderA, RISING);          //функция обработки внешнего прерывания INT0 
  attachInterrupt(1, doEncoderB, RISING);          //функция обработки внешнего прерывания INT0 

  Serial.begin (9600);  
  Serial.println("START READING"); 
} 

void doEncoderB(){ 
if (digitalRead(encoder0PinB)==digitalRead(encoder0PinD))
encoder0Pos1++; else encoder0Pos1--;
}

void doEncoderA(){
if (digitalRead(encoder0PinA)==digitalRead(encoder0PinC))
encoder0Pos++; else encoder0Pos--;

}

void loop () 
{ 
Serial.print("\n"); 
Serial.print(encoder0Pos1);
Serial.print(" ");
Serial.print(encoder0Pos); 
delay(50); 
} 

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

первый энк - канал А ведущий - его на прерывание , канал В - любой пин

второй энк - канал А ведущий - его на прерывание , канал В - любой пин

прерывания - пин 2 и 3

переделать это

01 #define encoder0PinA 2                   //вход А  пин 2
02 #define encoder0PinB 3                   //вход B  пин 3
03 #define encoder0PinC 4                  //вход С  пин 4
04 #define encoder0PinD 5                  //вход D  пин 5

вот в это

01 #define encoder1PinA 2                   //вход 1А  пин 2
02 #define encoder1PinB 4                   //вход 1B  пин 4
03 #define encoder2PinА 3                   //вход 2А  пин 3
04 #define encoder2PinВ 5                   //вход 2В  пин 5

и далее переделать остальной код :)

у вас в коде первый энк двумя каналами долбит ДВА ПРЕРЫВАНИЯ , второй энк - мимо прерываний :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

начните с определений, я в ваших запутался :(

энки - 1 и 2

их каналы - A и B

тогда пины для подключения будут - encoder1A , encoder1B и encoder2A , encoder2B

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

вы понимаете как устроен энк ? знаете как подключить ? как обрабатывать сигналы с его двух каналов ?

спрашиваю не для приколов - а для дальнейшего разговора :)

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015
#define encoder1PinA 2                   //вход 1А  пин 2
#define encoder1PinB 4                   //вход 1B  пин 4
#define encoder2PinA 3                   //вход 2А  пин 3
#define encoder2PinB 5                   //вход 2В  пин 5

volatile long encoder0Pos = 0;        //  переменная в обработчике прерываний по подсчету импульсов 
volatile long encoder0Pos1 = 0;        //  переменная в обработчике прерываний по подсчету импульсов 

void setup() { 
  pinMode(encoder1PinA, INPUT);           
  pinMode(encoder1PinB, INPUT);  
  pinMode(encoder2PinA, INPUT);
  pinMode(encoder2PinB, INPUT);  
  
  attachInterrupt(0, doEncoderA, RISING);          //функция обработки внешнего прерывания INT0 
  attachInterrupt(1, doEncoderB, RISING);          //функция обработки внешнего прерывания INT1

  Serial.begin (9600);  
  Serial.println("START READING"); 
} 

void doEncoderB(){                                    // функция действие вызываемое прерыванием1 
if (digitalRead(encoder2PinA)==digitalRead(encoder2PinB))
encoder0Pos1++; else encoder0Pos1--;
}

void doEncoderA(){                                    // функция действие вызываемое прерыванием1 
if (digitalRead(encoder1PinA)==digitalRead(encoder1PinB))
encoder0Pos++; else encoder0Pos--;
}

void loop () 
{ 
Serial.print("\n"); 
Serial.print(encoder0Pos1);
Serial.print(" ");
Serial.print(encoder0Pos); 
delay(50); 
} 

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

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

SU-27-16 пишет:

вы понимаете как устроен энк ? знаете как подключить ? как обрабатывать сигналы с его двух каналов ?

спрашиваю не для приколов - а для дальнейшего разговора :)

Как работает энкодер я знаю, задавайте вопросы. 

Для справки он Инкреминтальный. 200 Гц за оборот вала.

http://back.es-electro.ru/res/production/files/Autonics/encoders/E30S.pdf

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

200 Гц за оборот вала.

 

не понял :( , может за оборот даёт 200 тиков ? этот параметр не очень важен ПОКА

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

SU-27-16 пишет:

200 Гц за оборот вала.

 

не понял :( , может за оборот даёт 200 тиков ? этот параметр не очень важен ПОКА

Пусть будет тиков разницы нет. Грубо говоря 200 импульсов. По схеме во вложении видно в энкодере стоит транзюк.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
не копируется PDF вашего энка :(
.... два выхода энка - четыре состояния - анализируйте их - по преравынию в любом канале можно определить куда вращение....
ищите тему про энкодеры - тут их море !
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Yarockiisergei пишет:

SU-27-16 пишет:

200 Гц за оборот вала.

 

не понял :( , может за оборот даёт 200 тиков ? этот параметр не очень важен ПОКА

Пусть будет тиков разницы нет. Грубо говоря 200 импульсов. По схеме во вложении видно в энкодере стоит транзюк.

транзюк - согласователь уровней - на логику обработки НЕ влияет !

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

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

Может быть проц не справляется с таким колличеством прерываний возникающих на разных входах одновременно?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

уточнение :

- только энк1 на пинах 2 и 4 - работает

только энк2 на пинах 3 и 5 - работает

- а оба - НЕТ ?

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

SU-27-16 пишет:

уточнение :

- только энк1 на пинах 2 и 4 - работает

только энк2 на пинах 3 и 5 - работает

- а оба - НЕТ ?

Нет, оба на пинах. один крутиш работает, два крутиш счет сбивается.

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

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

дайте крайний код

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015
#define encoder1PinA 2                   //вход 1А  пин 2
#define encoder1PinB 4                   //вход 1B  пин 4
#define encoder2PinA 3                   //вход 2А  пин 3
#define encoder2PinB 5                   //вход 2В  пин 5

volatile long encoder0Pos = 0;        //  переменная в обработчике прерываний по подсчету импульсов 
volatile long encoder0Pos1 = 0;        //  переменная в обработчике прерываний по подсчету импульсов 

void setup() { 
  pinMode(encoder1PinA, INPUT);           
  pinMode(encoder1PinB, INPUT);  
  pinMode(encoder2PinA, INPUT);
  pinMode(encoder2PinB, INPUT);  
  
  attachInterrupt(0, doEncoderA, RISING);          //функция обработки внешнего прерывания INT0 
  attachInterrupt(1, doEncoderB, RISING);          //функция обработки внешнего прерывания INT1 

  Serial.begin (9600);  
  Serial.println("START READING"); 
} 

void doEncoderB(){                                    // функция действие вызываемое прерыванием1 
if (digitalRead(encoder2PinA)==digitalRead(encoder2PinB))
encoder0Pos1++; else encoder0Pos1--;
}

void doEncoderA(){                                    // функция действие вызываемое прерыванием1 
if (digitalRead(encoder1PinA)==digitalRead(encoder1PinB))
encoder0Pos++; else encoder0Pos--;
}

void loop () 
{ 
Serial.print("\n"); 
Serial.print(encoder0Pos1);
Serial.print(" ");
Serial.print(encoder0Pos); 
delay(50); 
} 

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

подключены 2 , первый крутим - норм , второй крутим - норм , оба крутим одновременно - фуйня ? в чём она выражается ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

SU-27-16 пишет:

подключены 2 , первый крутим - норм , второй крутим - норм , оба крутим одновременно - фуйня ? в чём она выражается ?

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

Может наводки какие......

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
volatile long encoder0Pos = 0;        //  переменная в обработчике прерываний по подсчету импульсов 
volatile long encoder0Pos1 = 0;        //  переменная в обработчике прерываний по подсчету импульсов 
 
опять про определения :
volatile long encoder1Pos = 0;        //  переменная в обработчике прерываний по подсчету импульсов энка первого
volatile long encoder2Pos = 0;        //  переменная в обработчике прерываний по подсчету импульсов энка второго
 
это моя мнения - обзывайте как вам хочется , лишь бы не запутацца.....
Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

Как я понял в принцыпе код верный..... А вот работать нормально отказывается, так плучается?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

не наводки ! а ваш код скорее всего.... в кучу определения... уже устал - может ГУРЫ ещё чё напишут ? :) типа - айм би бек !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Yarockiisergei пишет:

Как я понял в принцыпе код верный..... А вот работать нормально отказывается, так плучается?

НЕверный !!! - поэтому и отказывается :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

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

.....а не двумя дрелями на скорости 2000 rpm :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

  pinMode(encoder1PinA, INPUT);

а подтяжка к VCC ? где ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

дребезг контактов ещё вы не устранили :(

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

Vcc (+5 В) беру с ножки ардуино а сама она питается от USB. Поясню оба энкодера питаются с ножки ardvino с ножки Vcc. Gnd я также повесил только на две ножки  3 контакт и 22. Далее с энкодера беру импульсные входы A - вращение влево B - вращение вправо ну и далее один на 2 и 4 ногу, второй на 3 и 5.

Моя aarduino: http://carduino.ru/product_info.php?products_id=1964

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

"... входы A - вращение влево B - вращение вправо ..." - неправильно, нет привязки А и В к право и лево

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

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

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

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

Философия: мне кажется что проблема в том что я привязал два прерывания на разные энкодера контакта А и без прерывания анализирую состояние входа В. За счет того что прерывания срабатывают практически одновременно входы без прерываний не успевают......

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

по состоянию выходов энкодер имеет 4 положения , за оборот ваш даёт 200 тиков - т.е. за оборот он имеет 50 одинаковых зон и определить в какой зоне он находится невозможно , положение своё знают только абсолютные энкодеры.

анализируя изменения на выходах энка можно только определить направление вращения и на сколько тиков повернули , +тик или -тик изменяют переменную encoder0Pos - вот она-то и будет хранить положение чего-то, например - сервы, если на неё подавать encoder0Pos  

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Yarockiisergei пишет:

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

Философия: мне кажется что проблема в том что я привязал два прерывания на разные энкодера контакта А и без прерывания анализирую состояние входа В. За счет того что прерывания срабатывают практически одновременно входы без прерываний не успевают......

выходы А и В равноправны, они и не лев, и не прав....

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

при изменении в канале А сигнал изменился от хиг в лов - состояние выхода В может быть лов или хиг - смотря куда крутнули энк

поищите здесь темы - обсуждений на страниц 400 потянет....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder

вот пример без аппаратных прерываний, просто отслеживается изменение в одном канале и анализируется состояние второго

Yarockiisergei
Offline
Зарегистрирован: 17.01.2015

Без прерываний точность теряется. Все же от прерываний уходить нехочеться.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

так работает ? то что значения скачут за один тик энка не на 1, а на 1.......15 - это дребезг контактов энка, главное чёбы изменялось в +/- от напрВращения

и ещё особенность - при такой обработке изменение за тик энка будет или 2, или 4 - не помню :(

второй энк - как и первый прописать....

#define enc1A 2         // А и В на пины , третий провод на землю
#define enc1B 4
volatile long enc1Pos = 500;
//================================================
void setup()
{ 
  pinMode( enc1A , INPUT );
  digitalWrite( enc1A , HIGH );    // подтяжка
  pinMode( enc1B , INPUT );  
  digitalWrite( enc1B , HIGH );    // подтяжка
  attachInterrupt( 0 , doEnc1 , FALLING );
  Serial.begin( 9600 );  
  Serial.println( "START READING" ); 
} 
//================================================
void doEnc1()
{
  if ( digitalRead( enc1B ) == 0 ) enc1Pos++;
  else                             enc1Pos--;
}
//================================================
void loop () 
{ 
  Serial.print( "enc1Pos = " );
  Serial.print( enc1Pos );
  Serial.print( "      " );
  Serial.print( "enc2Pos = " );
  Serial.println( "....." );
  delay( 50 ); 
}
//================================================

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

"Все решил проблему! А все очень просто. Добавил обычный керамический конденсатор на 1мф мжду контактами кнопки. И вуаля абсолютно никакого дребезга. Кнопку с большой частотой нажимал на сколько мог. Дребезга нет, удивительно)"  - Вы просто ещё не попали в ситуацию когда дребезг даст о себе знать снова. Да, конденсатор значительно сглаживает сигнал дребезга, но не устраняет полностью.

"Все таки добавить две строки куда проще чем впаивать конденсатор."

.....поищите про антидребезг

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Многовата ёмкость.... Ведь конденсатор разряжается через короткое на кнопку (большой ток) да и долго заряжаться будет от резистора подтяжки.  Обычно ставлю 4700 пик или 10 нан, проблемм не было.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

#34 - это примеры решения проблемы других форумчан :) , я не парюсь - у миня оптические

sva1509
Offline
Зарегистрирован: 07.12.2012

Судя по даташиту у этого энкодера на выходе npn открытый коллектор, так что дребезг мимо.

Покажи схему включения.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

sva1509 пишет:

Судя по даташиту у этого энкодера на выходе npn открытый коллектор, так что дребезг мимо.

Покажи схему включения.

с открытым коллектором - это инвертируйщий усилитель напряжения, если контакты механические - то ОК не спасёт... плюс ОК - возможность включать в схемы с любым питанием ( 3.......48..... V ), только резистор в коллекторе расчитать правильно... щас поищу описание энка этого...

КЛАССНО ! 

unsigned long conv(char *str)
{
        unsigned long l1=0;
        while(*str) l1 = (l1 << 1) | (unsigned long) (*str++ - 48);
        return l1;
}
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Power supply: 5 VDC , 12-24 VDC +/-5% - ваш энк какого исполнения ? напишите его маркировку с корпуса...

Black - Out A , White - Out B , Orange - Out Z , Brown - +V ( 5 МВС ) , Blue - GND ( 0 V ) - 

Out A - пин2 , Out B - пин4 , Out Z - в этой задаче не нужен , +V - пинVCC , GND - пинGND.

 

максимальный ток коллектора 30 mA - при внутренней подтяжке резисторы в коллекторе будут 20 k - ток 250 mkA,

с внешними по 10 k - ток 500 mkA, с внешними по 4,7 k - ток 1 mA, с внешними по 2 k - ток 2,5 mA - надо пробовать, чем меньше резистор тем больше помехоустойчивость....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
Тип энкодера
Тип выхода
Выходной код фаза A, не A, B, не B, Z, не Z
Оптическое разрешение (имп/оборот или имп/дюйм)
Напряжение питания
Тип вала
Тип энкодера
Тип выхода
Выходной код фаза A, не A, B, не B, Z, не Z
Оптическое разрешение (имп/оборот или имп/дюйм)
Напряжение питания
Тип вала

...за 4000 р. он просто обязан быть ОПТИЧЕСКИМ , хорошая штучка :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

...а я чёта всё про такой :(   http://www.chipdip.ru/product/ec11k0920601/

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
#define enc1A 2             // А и В на пины , VCC , GND
#define enc1B 4
volatile int enc1Pos;       // -32768 ... 32767
// volatile byte enc1Pos;   // 0 ... 255

#define enc2A 3             // А и В на пины , VCC , GND
#define enc2B 5
volatile int enc2Pos;       // -32768 ... 32767
// volatile byte enc2Pos;   // 0 ... 255
//================================================
void setup()
{ 
  pinMode( enc1A , INPUT );
  digitalWrite( enc1A , HIGH );    // подтяжка
  pinMode( enc1B , INPUT );  
  digitalWrite( enc1B , HIGH );    // подтяжка
  attachInterrupt( 0 , doEnc1 , FALLING );
  enc1Pos = -100;

  pinMode( enc2A , INPUT );
  digitalWrite( enc2A , HIGH );    // подтяжка
  pinMode( enc2B , INPUT );  
  digitalWrite( enc2B , HIGH );    // подтяжка
  attachInterrupt( 1 , doEnc2 , FALLING );
  enc2Pos =  100;

  Serial.begin( 9600 );  
  Serial.println( "START READING" ); 
} 
//================================================
void doEnc1()
{
  if ( digitalRead( enc1B ) == 0 ) enc1Pos++;
  else                             enc1Pos--;
}
//================================================
void doEnc2()
{
  if ( digitalRead( enc2B ) == 0 ) enc2Pos++;
  else                             enc2Pos--;
}
//================================================
void loop () 
{ 
  Serial.print( "enc1Pos = " );
  Serial.print( enc1Pos );
  Serial.print( "      " );
  Serial.print( "enc2Pos = " );
  Serial.println( enc2Pos );
//  delay( 50 ); 
  delay( 500 );      // чтобы в сериалМониторе не скакало
}
//================================================

 

SLOM
Offline
Зарегистрирован: 06.11.2014

Yarockiisergei пишет:

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

 

я не программист но мне кажеться в вашем коде на 2 энкодера один счетчик? 

который получает инфу от 2х энкодеров, когда говорит один все ок, когда тараторят оба - ниче не понятно... 

вы бы тоже ничего не поняли если бы вам 2 человека одновременно говорили...

может нужно 2 счетчика, для каждого свой.  это и логичней если это машинв то на каждую сторону по энкодеру, и по счетчику.