#1 2019-02-10 19:49:01

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

Обробник промислового енкодера.

Вітаю.
Вирішив створити вимірювач довжини матеріалів. Ну щоб була можливість вимірювати довжину кабелю, чи ще якихось причуд.
Спочатку думав що все буде дуже просто. Достатньо обробити енкодер та перерахувати кількість отриманих імпульсів у сантиметри, все це вивести на якийсь дисплей.
В наявності маю енкодер RU1033. Живлення 5 вольт. 2000 імпульсів на один оберт.
Находив дуже багато готових скетчів...
Та все ніяк не можу добитися чіткості підрахунку кількості імпульсів. Виникає питання... Невже ардуїно не здатна працювати з такими енкодерами??

Допоможіть будь ласка. Дякую.

Ось най вірогідніше працюючий код з інтернету. Коли помалу обертаю енкодер, то рахує приблизно однаково, коли ж починаю обертати швидко, отримую помилку.

long int out = 0;
const byte ledPin = 13;
const byte leftPin = 2;
const byte rightPin = 3;
volatile byte state = LOW;
volatile byte x;
volatile byte a;
volatile byte b;
volatile byte c;
boolean OK=false;
boolean OK1=true;
boolean OK2=false;
void setup() {
DDRB |= (1<<DDB5);//pin 13 is in output mode
DDRD&=~(1<<DDD2);//pin 2 is in input mode
PORTD|=(1<<DDD2);// activate the pull-up resistor 14.2.1 atmega 328 datasheet
PORTD&=~(1<<DDD3);//pin 3 is in input mode
PORTD|=(1<<DDD3);// activate the pull-up resistor 14.2.1 atmega 328 datasheet
attachInterrupt(digitalPinToInterrupt(leftPin), encoder, CHANGE);//call left function when pin 2 is changing state
attachInterrupt(digitalPinToInterrupt(rightPin), encoder1, CHANGE);// call right function when pin 3 is changing state
Serial.begin(250000);
}

void loop() {
if(OK2==false){//just for one time
x=PIND&B00001100;// when the sistem start x takes the pins state
a=PIND&B00001100;// when the sistem start a takes the pins state
OK2=true;
}
digitalWrite(ledPin, state);
//Serial.println(x);
Serial.println(out/380);
// Serial.println(OK);
if (OK1==false)
{
  Serial.println("error");// to appear more time on the serial monitor
}

}

void encoder() 
{
  // function to check the rotate direction when pin 2 is changing state
  cli();// stop interrupts which could appear
  a=PIND&B00001100;// a takes the new state of pins beacuse encoder function is call when pin 2 is changing state
  b=a>>2;// move bits for pin 2 and 3 in the places coressponding to 2^0 and 2^1
  c=b | x;// OR function between b and x
  if(c==2 || c==4 || c==11 || c==13)// values in pairs of bits in the format xxyy
    {
      out++;
      OK=false;// right rotate direction
    }
  if(c==1 || c==7 || c==8 || c==14)// values in pairs of bits in the format xxyy
    {
      out--;
      OK=true;// left rotate direction
    }
   else if(OK==true)
    {// if OK is true and c has other values the arduino miss steps in the ccw direction
      OK1=false;
      //Serial.println(“error”);
    }
   x=PIND&B00001100;// x takes the new state of pins
  state = !state;// blink LED from pin 13
  sei();// enable interrupts
}
void encoder1()
{// function to check the rotate direction when pin 2 is changing state
  cli();// stop interrupts which could appear
  a=PIND&B00001100;// a takes the new state of pins beacuse encoder1 function is call when pin 2 is changing state
  b=a>>2;// move bits for pin 2 and 3 in the places coressponding to 2^0 and 2^1
  c=b | x;
  if(c==1 || c==7 || c==8 || c==14)// values in pairs of bits in the format xxyy
    {
      OK=true;// left rotate direction
    }
   if(c==2 || c==4 || c==11 || c==13)// values in pairs of bits in the format xxyy
    {
      OK=false;// right rotate direction
    }
  else if(OK==false)
  {// if OK is false and c has other values the arduino miss steps in the cw direction
    OK1=false;
    Serial.println("error");
  }
  x=PIND&B00001100;// x takes the new state of pins
  state = !state;// blink LED from pin 13
  sei();// enable interrupts
}

Неактивний

#2 2019-02-11 08:48:14

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

Re: Обробник промислового енкодера.

попробуйте

volatile uint8_t enc = 0;
long pos =- 999;
volatile long newpos = 0;

void ISR_ENC()      //прерывание энкодера одно для входа 2 и 3
{
  uint8_t newenc = ((PIND/4) & 0b11);
  uint8_t temp = enc ^ newenc;
  if (temp == 0b01)
    if (enc == 0b00 || enc == 0b11) newpos ++; 
    else newpos--;
  else if(temp == 0b10)
    if (enc == 0b00 || enc == 0b11) newpos --;
    else newpos ++; 
  enc = newenc;
}

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP); 
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(0, ISR_ENC, CHANGE);
  attachInterrupt(1, ISR_ENC, CHANGE);  
}

void loop()
{
  if (newpos != pos)
  {
    pos = newpos/4;    
    Serial.println(pos);
  }
}

Неактивний

#3 2019-02-12 13:12:22

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

Re: Обробник промислового енкодера.

Спробував, працює але ще не досить швидко. Можливо порадите якусь спеціалізовану мікросхему для обробки енкодера?
Просто, якщо нашпигувати контролер функціями роботи з кнопками, датчиками і дисплеем, то він просто не зможе працювати з енкодером.
Варіант з двома arduino, якось не вселяє довіри...

Неактивний

#4 2019-02-12 17:19:56

Кодер
Гість

Re: Обробник промислового енкодера.

Яка буде найбiльша швидкiсть обертання валу енкодера? Або частота фазових iмпульсiв?

#5 2019-02-13 06:29:55

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

Re: Обробник промислового енкодера.

Надів на енкодер коліща від принтера. Намотав капроновий шнур довжиною 1м. Коли протягую зі швидкістю, близько двох обертів на секунду, отримую сталі показники. Коли ж збільшу швидкість до п'яти, показник зменшується. Що свідчить про пропущені імпульси. Шкода ?

Неактивний

#6 2019-02-13 09:07:21

Кодер
Гість

Re: Обробник промислового енкодера.

Або шукайте мiкроконтроллер який має таймер з квадратурним декодером (що до Atmel - це є Х серiя) , або теба зробити невеличку зовтiшню схемку детектування напрямку, шоб застосувати аппаратний таймер для пiдрахунку iмпульсiв.

#7 2019-02-13 09:54:40

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

Re: Обробник промислового енкодера.

а вы никогда не пытались на запорожце разогнаться до 200 км/час ?

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

или примените энкодер с меньшим разрешением или используйте ARM или мини пк.

Неактивний

#8 2019-02-27 18:33:28

gorenkov
Учасник
З Кіев
Зареєстрований: 2015-11-05
Повідомлень: 41

Re: Обробник промислового енкодера.

Мне кажется, вам надо считать обороты. А обороты можно считать датчиком холла

Неактивний

#9 2019-03-27 21:08:32

theoristos
Учасник
Зареєстрований: 2018-08-02
Повідомлень: 37

Re: Обробник промислового енкодера.

gorenkov: и чем это поможет автору?

Віктор: в принципе, можно перевести Таймер1 ардуины в режим счёта импульсов. Считает быстро
Но проблема в том, что делать при изменении направления. Ибо он тупо считает число импульсов
Хотя, если извращаться, то можно сгородить схему на рассыпухе, которая будет разделять импульсы в "ту" и "другую" стороны.
И завести на два таймера  Mega 2560.

Неактивний

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

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

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