roboforum.ru

Технический форум по робототехнике.

Работа с Энкодером

Re: Работа с Энкодером

=DeaD= » 17 мар 2011, 18:33

NorthStar писал(а):Если Serial.print (encoder0Pos); убрать, то оно может и работает, только как это понять? У меня индикатора на Arduino нет. Делал скорость COM-порта выше - не помогло.

Пока не разберетесь с основами - не влезайте в другие контроллеры.
Кто вас заставляет в том же цикле делать вывод, да еще и с той же частотой?
У вас никакой контроллер не сможет пихать в COM-порт столько инфы и будет прав.

Вынесите в прерывание обработку энкодера, печать в COM-порт текущего значения - в прерывание по таймеру, скажем 10 раз в секунду, не чаще.

Re: Работа с Энкодером

dccharacter » 17 мар 2011, 18:39

Ну мы можем считать, что в споре у нас родилась какая-то истина?

Re: Работа с Энкодером

=DeaD= » 17 мар 2011, 18:42

Угу, обсуждаем космические скорости, а топикстартер работает без прерываний и на каждом клике отсылает в UART строку с текущим счетчиком.

Re: Работа с Энкодером

dccharacter » 17 мар 2011, 18:53

=DeaD= писал(а):Угу, обсуждаем космические скорости, а топикстартер работает без прерываний и на каждом клике отсылает в UART строку с текущим счетчиком.

ну если увеличить скорость УАРТА до примерно гигагерца, тогда он не будет оказывать заметного влияния на чтение показателей энкодеров.

Re: Работа с Энкодером

NorthStar » 17 мар 2011, 19:01

Вообще-то я уже сказал, что работаю с прерываниями. Что значит - отправка возможна только когда контроллер не занят прерываниями ))Так что я бы не сказал, что пхаю в порт больше, чем туда входит.
PID регулятор туда уже точно не влезет )

Re: Работа с Энкодером

Duhas » 17 мар 2011, 19:18

берете Хмегу и читаете счетчик когда вам угодно...

Re: Работа с Энкодером

=DeaD= » 17 мар 2011, 19:22

NorthStar писал(а):Код вот от сюда брал http://www.arduino.cc/playground/Main/RotaryEncoders.

Блин! А вы не могли бы конкретизировать? Что называется - спасибо, что не просто ссылку на google дали.

Re: Работа с Энкодером

NorthStar » 17 мар 2011, 22:30

Ниже вариант, который я тестил. Жаль, что похоже никто такую задачку тут не решал (

Код: Выделить всёРазвернуть
/* read a rotary encoder with interrupts
   Encoder hooked up with common to GROUND,
   encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
   it doesn't matter which encoder pin you use for A or B 

   uses Arduino pullups on A & B channel outputs
   turning on the pullups saves having to hook up resistors
   to the A & B channel outputs

*/

#define encoder0PinA  2
#define encoder0PinB  4

volatile unsigned int encoder0Pos = 0;

void setup() {


  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.begin (9600);
  Serial.println("start");                // a personal quirk

}

void loop(){
// do some stuff here - the joy of interrupts is that they take care of themselves
}

void doEncoder() {
  /* If pinA and pinB are both high or both low, it is spinning
   * forward. If they're different, it's going backward.
   *
   * For more information on speeding up this process, see
   * [Reference/PortManipulation], specifically the PIND register.
   */
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
    encoder0Pos++;
  } else {
    encoder0Pos--;
  }

  Serial.println (encoder0Pos, DEC);
}

Re: Работа с Энкодером

=DeaD= » 17 мар 2011, 22:38

Just try:
Код: Выделить всёРазвернуть
#define encoder0PinA 2
#define encoder0PinB 4

volatile unsigned int encoder0Pos = 0;

void setup() {

pinMode(encoder0PinA, INPUT);
digitalWrite(encoder0PinA, HIGH); // turn on pullup resistor
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH); // turn on pullup resistor

attachInterrupt(0, doEncoder, CHANGE); // encoder pin on interrupt 0 - pin 2
Serial.begin (9600);
Serial.println("start"); // a personal quirk

}

void loop(){
  Serial.println (encoder0Pos, DEC);
  delay(250); //Wait for 0.25sec
}

void doEncoder() {
if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
encoder0Pos++;
} else {
encoder0Pos--;
}
}

Re: Работа с Энкодером

Duhas » 18 мар 2011, 08:58

еще чуток рекламы атымела

вот кусочек кода после исполнения которого можно просто читать из таймера сколько он там насчитал.. на 16 бит..
Код: Выделить всёРазвернуть
encoder_init:
   ldi      tmp1,         0b00000000      
   sts      PORTF_DIR,      tmp1
   ldi      tmp1,         0b00000011
   sts      PORTF_PIN5CTRL,   tmp1
   
   ldi      tmp1,         0b01111101      
   sts      EVSYS_CH0MUX,   tmp1
   ldi      tmp1,         0b00001001
   sts      EVSYS_CH0CTRL,   tmp1

   ldi      tmp1,         0b00000000
   sts      TCC0_CTRLB,      tmp1

   ldi      tmp1,         0b00000000
   sts      TCC0_CTRLC,      tmp1

   ldi      tmp1,         0b01101000      
   sts      TCC0_CTRLD,      tmp1

   ldi      tmp1,         0b00000001
   sts      TCC0_CTRLA,      tmp1

   ldi      tmp1,         0xff
   sts      TCC0_PER,      tmp1

   ldi      tmp1,         0xff
   sts      TCC0_PER,      tmp1
   ret

Re: Работа с Энкодером

boez » 18 мар 2011, 10:56

NorthStar писал(а):Ниже вариант, который я тестил. Жаль, что похоже никто такую задачку тут не решал


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

Сделай как DeaD написал - вынеси нафиг serial.println из прерывания, это же жопа просто, а не обработчик, он же ждет после каждого тика пока уарт выплюнет всю строчку! И естественно все это время тики пропускает. По всей видимости это код для ручного энкодера, ну которые во всяких там девайсах используют для плавных регулировок, то есть у него штук 50 импульсов на оборот и человек ручку крутит. А для мотора такое неприменимо.

А вот если вынесешь - там в обработчике останется работы тактов на 20-30, соответственно несколько сот кГц он скушает. А нужно всего 5000/60*1024 = 85 кГц.

Re: Работа с Энкодером

blindman » 18 мар 2011, 11:05

Ну тогда чуток рекламы параллакса :)

Запускаем один процессор с программой работы с энкодерами, потом спокойно читаем из памяти чего он там насчитал. 32 бита

Код: Выделить всёРазвернуть
'' Simple dual quadrature encoder interface
'' for Parallax Propeller. Two encoders, each up to
'' 250000 pulses/s at 80 MHz Propeller clock


' ===========================================================
'' buffer points to buffer of 2 LONGs that will
'' contain positions of 2 quadrature encoders
' -----------------------------------------------------------
' Encoders must be connected to 4 consequent pins.
' In basepin, pass the lowest pin number. Say, if you have
' first encoder connected to pins 5 and 6, and second - to
' pins 7 and 8, pass 5 in basepin
' ===========================================================
PUB start(buffer, basepin)
    base := basepin
    pos1_addr := buffer
    cognew(@encoder, 0)

' ===========================================================
DAT

encoder     mov     pos2_addr, pos1_addr
            add     pos2_addr, #4
            mov     old, INA
            shr     old, base
:loop       wrlong  pos1, pos1_addr         ' 8 / 88
            mov     sample, INA             ' 12
            shr     sample, base            ' 16
            wrlong  pos2, pos2_addr         ' 24
            mov     change, old             ' 28
            mov     old, sample             ' 32
            xor     change, sample          ' 36
            xor     change, old             ' 40

            test    change, #2          wz  ' 44
            shr     change, #2          wc  ' 48
if_c_and_nz add     pos1, #1                ' 52
if_nc_and_z sub     pos1, #1                ' 56

            test    change, #2          wz  ' 60
            shr     change, #2          wc  ' 64
if_c_and_nz add     pos2, #1                ' 68
if_nc_and_z sub     pos2, #1                ' 72

            jmp     #:loop                  ' 76

pos1        long    0
pos2        long    0
pos1_addr   long    0
base        long    0

pos2_addr   res     1
change      res     1
old         res     1
sample      res     1


Re: Работа с Энкодером

Michael_K » 18 мар 2011, 12:00

boez писал(а):А нужно всего 5000/60*1024 = 85 кГц.

Имхо, вы слегка переоцениваете возможности МК, и недооцениваете работу с энкодерами.

Во-первых, когда говорят "энкодер на 1024 положения", это обычно означает, что энкодер выдает 1024 полных квадратурных цикла. То есть на один оборот вала мы имеем 1024 импульса на каждом из выходов. То есть 2048 фронтов на каждом из выходов.

Во-вторых, тут правильно заметил Dead, что нужно обрабатывать только один выход. НО.... ловить нужно ОБА фронта. Это уже означает, что прерывание (если речь идет о прерываниях) будет вызываться с частотой 170 кГц (период 6 микросекунд).

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

Из этого следует два вывода:
1. Хотя обрабатывать необходимо оба фронта, считать нужно только один (то есть мы как раз получаем 1024 позиции на оборот).
2. После возникновения фронта нужно как можно быстрее считать состояние выходов энкодера (даже при абсолютно симметричной последовательности нужно уложиться в три микросекунды, а если предполагать неидеальность энкодера, то и того меньше).

Именно поэтому нехорошо вешать "три энкодера на три прерывания", как тут смело предположил dccharacter.
dccharacter писал(а):Один pic16f1827 придется полностью выделить под три энкодера без возможности считать с него эти данные.
. Пока обрабатывается одно из прерываний, можно легко пропустить смену состояния на другом входе. Прерывание-то, может быть, защелкнется и отработает позже, но считывание входа произойдет со значительной задержкой и может приводить к неверным результатам.

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

Re: Работа с Энкодером

dccharacter » 18 мар 2011, 12:18

boez писал(а):Сделай как DeaD написал - вынеси нафиг serial.println из прерывания, это же жопа просто, а не обработчик,


АААААААА Я ДАЖЕ КОД НЕ СМОТРЕЛ!!!!!!!! ТАМ СЕРИАЛ ПРИНТ В ПРЕРЫВАНИИИИИИИИИИИ??????????? АААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
:O:

Добавлено спустя 3 минуты 36 секунд:
Michael_K писал(а):Во-первых, когда говорят "энкодер на 1024 положения", это обычно означает, что энкодер выдает 1024 полных квадратурных цикла. То есть на один оборот вала мы имеем 1024 импульса на каждом из выходов. То есть 2048 фронтов на каждом из выходов.

Так, я сделал выводы и хочу задать вопрос ТС: "Зачем такая точность, это ж не героин?"

Re: Работа с Энкодером

Michael_K » 18 мар 2011, 12:24

Да мало ли зачем...

Во время быстрых перегонов такая точность в каждый момент времени вряд ли нужна,
но ведь позицию-то терять все-равно нельзя! Чтобы была возможность точно спозиционироваться
медленно, ПОСЛЕ быстрого перегона.

Типичное решение для станка, например.

Добавлено спустя 2 минуты 12 секунд:
ну и в конце концов, нельзя исключать и просто вариант, что у него под столом завалялись движки с такими энкодерами. Что же ему, выковыривать их что-ли и приклеивать "на жувачку" самодельные? Вот был бы у вас такой энкодер, нужели бы вы его стали раскурочивать?


cron
Rambler\'s Top100 Mail.ru counter