#1 2017-05-25 10:23:20

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

Энкодер. + Энкодер? + Энкодер!

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

И вот недавно случилось мне заниматься написанием программы для стенда по настройке топливной аппаратуры дизельных двигателей. В программе кроме тахометра, счетчика заданного количества оборотов, кнопок, индикации и т.п. нужно было еще обрабатывать данные с восьми энкодеров. Использование абсолютных энкодеров (ru.wikipedia.org/wiki/Датчик_угла_поворота) проект не предусматривал, поэтому пришлось мучиться с инкрементальными.

Первым делом нужно было избавиться от каких-либо задержек в обработке сигналов. После некоторого «мучения» получился вот такой код.

Сохранить в Альбом

8055f09s-960.jpg

Несмотря на свою краткость, эта программа вполне успешно справляется со своей задачей.
Можете её использовать в проектах для регулировок, в паяльных станциях, усилителях и т.п.

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



Аппетит приходит во время еды, и на определенном этапе разработки было принято решение обрабатывать каждый энкодер своим контроллером. Использовать ATmega или ATtiny85 (это было в наличии) у которых на борту имеется UART, показалось как-то расточительно.
Выбор пал на ATtiny13… если бы я знал какой это мазохизм то наверное … Впрочем не будем об этом.

В сети есть немного информации по программному UART для ATtiny13, я за основу взял этот листинг.
pastebin.com/NBFMq1C6
Немного его доработал, добавил необходимые обработчики и получил такой себе псевдо абсолютный энкодер. Теперь все восемь энкодеров можно подключить на одну шину и не бояться, что основная программа пропустит какое-то изменение угла.

Неактивний

#2 2017-05-25 16:02:45

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

Re: Энкодер. + Энкодер? + Энкодер!

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

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

прерывания используются для UARTa ...

Неактивний

#3 2017-05-25 16:10:39

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

Re: Энкодер. + Энкодер? + Энкодер!

Вы прогрупповые ....

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

По поводу фильтра - двух конденсаторов хватает за глаза...

Неактивний

#4 2017-05-25 17:36:27

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

Re: Энкодер. + Энкодер? + Энкодер!

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

Можно по всякому, и опросом тоже, это не очень принципиально. Лишь бы требуемым параметрам удовлетворить. Есть даже аппаратная поддержка таймерами, для больших скоростей. А RC фильтр на логическом входе - опасная вещь, нужен триггер шмидта.

По поводу этого не знаю.
Сталкивался только с описаниями (тесты в реале) эффективности RC фильтров.
Хотя действительно в некоторых микросхемах на входах для энкодеров аппаратно стоят ТШ.

Неактивний

#5 2017-06-06 11:18:25

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

Re: Энкодер. + Энкодер? + Энкодер!

boolean compare, triger, inc_cw, nc_cww;
byte division,division_CW,division_CWW, backlash_CW, backlash_CWW, backlash;
int counter_lcd , calibre_lcd;

// настройка вннешнего прерывания INT0 и INT1.    
//INT0 PD2. Mode: Falling Edge. INT1 PD2. Mode: Rising Edge.
EICRA = (1<<ISC11) | (1<<ISC10) | (1<<ISC01) | (0<<ISC00);
EIMSK = (1<<INT1) | (1<<INT0);
EIFR = (1<<INTF1) | (1<<INTF0);
PCICR = (0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0); 
//======================================================================


if((digitalRead(10) == 0)&&(triger == 0)) //compare.
  {
   temp++;
   if(temp == 0xff)
     {
      if(counter_lcd < calibre_lcd) //motor_cww.
        {
         compare = 0; 
         PORTD |= (1<<5); //on motor cw.
         while(compare == 0)
              {

              }
         PORTD &= ~(1<<5); //off motor.
         PORTB |= (1<<4);  //on braking.
         braking = 0x3300; //13056 time braking.
         triger = 1;       //set triger.
         goto compare_end;
        }
      if(counter_lcd > calibre_lcd) //motor_cww.
        {
         compare = 0;  
         PORTD |= (1<<4);//on motor cww.  
         while(compare == 0)
              {

              } 
         PORTD &= ~(1<<4); //off motor.
         PORTB |= (1<<4);  //on braking.
         braking = 0x3300; //13056 time braking.
         triger = 1;       //set triger.
         
        }   
     }
  }
compare_end:



ISR(INT0_vect)//INT0 PD2. Mode: Falling Edge. обработка прерываний с деление и люфтом INT0 and INT1 - ON
{
cli();
if((inc_cw == 1)&&(digitalRead(3) == 0))// энкодер++.
{
 if(backlash_CW == backlash)//выбор люфта вперед.
  {
   if(division_CW == division) //деление входных импульсов.
     {
      counter_lcd++;
      if(compare == 1)
        {
         if(counter_lcd == calibre_lcd)
           {
            PORTD &= ~(1<<5);
            compare = 1;    
           }
        }
      division_CW = 0;
      goto out_int_A;
     }
   division_CW++;
   goto out_int_A;
  }
   backlash_CW++;
   backlash_CWW = 0;
   division_CWW = 0;
   goto out_int_A;
} 

if((inc_cww == 1)&&(digitalRead(3) == 1))//энкодер--.
  {
   if(backlash_CWW == backlash)//выбор люфта назад.
     {
      if(division_CWW == division)//деление входных импульсов.
        {
         counter_lcd--;
         if(compare == 1)
            {
             if(counter_lcd == calibre_lcd)
               {
                PORTD &= ~(1<<4); 
                compare = 1;
               }
            }
         division_CWW = 0;
         goto out_int_A;
        }
      division_CWW++;
      goto out_int_A;
     } 
  backlash_CWW++;
  backlash_CW = 0; 
  division_CW = 0;
}  
out_int_A:
inc_cw = 0;
inc_cww = 0;
sei();
}

//==================================================================

//ISR(INT1_vect)//INT1 PD2. Mode: Rising Edge.
{
cli();
  if(digitalRead(2) == 0){inc_cw = 1; inc_cww = 0; goto out_int_B;}//энкодер++.
  if(digitalRead(2) == 1){inc_cww = 1; inc_cw = 0; goto out_int_B;}//энкодер--.
out_int_B:
sei();
} 

//====================================================================

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

if(compare == 1)
{         
  if(counter_lcd == calibre_lcd)           
     { PORTD &= ~(1<<5);  // или PORTD &= ~(1<<4);            
        compare = 1;
      }        
}

Остання редакція goodspeedmen (2017-06-08 15:42:36)

Неактивний

#6 2017-06-06 11:28:31

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

Re: Энкодер. + Энкодер? + Энкодер!

goodspeedmen пише:

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


Вставьте код по правилам форума....

Неактивний

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

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

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