Jump to content
SHipa

Подключение и работа с энкодером

Recommended Posts

Проблема с состовлением прошивки для энкодера (фирмы PEPPERL+FUCHS по данной программе выдает примерно 330-340 импульсов на оборот) линии данных подключил на int0 и int1 atmega8 прошивку пишe в codevision avr 
Включил прерывания int0 и int1 по любому изменению состояния и повешал на оба прерывания функцию обработки
void enkoder(){
    if((PIND.2==0)&&(PIND.3==0)){input = 0;
    }else if((PIND.2==1)&&(PIND.3==0)){input = 1;
    }else if((PIND.2==1)&&(PIND.3==1)){input = 2;
    }else if((PIND.2==0)&&(PIND.3==1)){input = 3;
    };
    if(input!=buf){
        switch(buf) {
            case 0:{
                if(input == 1) impuls++;
                if(input == 3) impuls--; 
                break;
            }case 1:{
                if(input == 2) impuls++;
                if(input == 0) impuls--;  
                break;
            }case 2:{
                if(input == 3) impuls++;
                if(input == 1) impuls--;  
                break;
            }case 3:{
                if(input == 0) impuls++;
                if(input == 2) impuls--; 
                break;
            };
            buf = input;
        };
    }; 
    ugol=impuls;
};

после того как вращаю энкодер и возвращаю его в обратное положение значение переменной impuls неправельное оно всегда больше 0 и с каждым вращением погрешность все больше 
подскажите что я делаю нетак.

Share this post


Link to post
Share on other sites

Литиевые батарейки Fanso для систем телеметрии и дистанционного контроля

Системы телеметрии находят все более широкое применение во многих отраслях на промышленных и коммунальных объектах. Требования, предъявляемые к условиям эксплуатации приборов телеметрии и, как следствие, источников питания для них, могут быть довольно жесткими. Fanso предоставляет широкую линейку продукции, рассчитанной на различные условия эксплуатации, что позволяет подобрать батарейку для каждого конкретного применения, в том числе и для устройств телеметрии.

Подробнее

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

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

Share this post


Link to post
Share on other sites

Как только выполняется break, программа выходит из switch{}. Поэтому строчка

buf = input;

не работает. Её надо передвинуть за следующую фигурную скобку, иначе это присваивание никогда не исполняется.

Share this post


Link to post
Share on other sites
                     

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

Компэл совместно с Texas Instruments 23 октября 2019 приглашают на вебинар, посвященный системам-на-кристалле для построения ультразвуковых расходомеров жидкостей и газов на базе ядра MSP430. Вебинар проводит Йоханн Ципперер – эксперт по ультразвуковым технологиям, непосредственно участвовавший в создании данного решения. На вебинаре компания Texas Instruments представит однокристальное решение, позволяющее создавать точные недорогие счетчики жидкостей и газов.

Подробнее...

10 минут назад, Yurkin2015 сказал:

Как только выполняется break, программа выходит из switch{}. Поэтому строчка


buf = input;

не работает. Её надо передвинуть за следующую фигурную скобку, иначе это присваивание никогда не исполняется.

после перемещения отроки вообще все перестало работать  теперь 1-2 импульса на 1 оборот энкодера

попробую еще раз проверить осцилографом на дребезг и помехи

Edited by SHipa

Share this post


Link to post
Share on other sites

Тут точно правильно :

1 час назад, SHipa сказал:

    if((PIND.2==1)&&(PIND.3==1)){input = 2;
    if((PIND.2==0)&&(PIND.3==1)){input = 3;

?

А

buf = input;

вынесите за switch. Иначе, как уже сказали выше, точно ничего работать не будет.

Share this post


Link to post
Share on other sites

Да и много лишних телодвижений, эти input и buf тут совсем не нужны по-моему.

Надо сделать проще. Например так

void enkoder(){
    if(PIND.2==0)
    {
        if(PIND.3==0)ugol++;
        else ugol--;
    }
    else
    {
        if(PIND.3==0)ugol--;
        else ugol++;
    }
}

 

Share this post


Link to post
Share on other sites

Ну buf, по всей видимости, нужен для сохранения предыдущего состояния.
 

Share this post


Link to post
Share on other sites

Да, чёт я погорячился. Надо использовать разные процедуры прерывания для разных входов.

Вот, пусть int0 для ноги PIND.2. Если на ноге фронт импульса и другая нога PIND.3 = 0, то прибавляем. Если спад импульса и другая нога = 1, то тоже прибавляем. В остальных случаях - вычитаем.

void enkoder0()
{
    if(PIND.2==1) 
   {
        if(PIND.3==0)ugol++;
        else ugol--;
    }
    else
    {
        if(PIND.3==1)ugol++;
        else ugol--;
    }
}

Аналогично для другого прерывания int1 для ноги PIND.3

void enkoder1()
{
   if(PIND.3==1)
    {   
        if(PIND.2==1)ugol++;
        else ugol--;
    }
    else
    {
        if(PIND.2==0)ugol++;
        else ugol--;
    }
}

 

Edited by Yurkin2015

Share this post


Link to post
Share on other sites

спасибо помогли переместил переменную и прерывания стояли по наростающему фронту поменял на любое изменение сигнала

Share this post


Link to post
Share on other sites

энкодер по таймеру

void encoder_read(void)
{unsigned char tempPORT;	
 static unsigned char encoder; 
    tempPORT=PORTB;
    encoder<<=2;
    if(tempPORT&((1<<2)) encoder |=(1<<0);
    if(tempPORT&((1<<3)) encoder |=(1<<1);

      switch (encoder & 0x0F) {
     
      // UP  
      case 0b0001:
      case 0b0111:
      case 0b1000:
      case 0b1110:          
          impuls++;
        break;
        
      // DOWN 
      case 0b0000:
      case 0b0100:
      case 0b1011:
      case 0b1101: 
          impuls--;
        break;

     // nothing happened      
      case 0b0000:
      case 0b0101:      
      case 0b1010:      
      case 0b1111:
            
      // error
      case 0b0011:
      case 0b0110:
      case 0b1001:
      case 0b1100:      
        break;

         default:
         break;
      }   // switch encoder 6 state

}//end void encoder_read(void)

 

Share this post


Link to post
Share on other sites

Мой вариант сканирования энкодера по таймеру, 1 мс достаточно для отлова самых быстрых вращений рукой. При более длинных не проверял.

uint16_t enc, enc_prev;
int8_t turn = 0;

void encoder (void)   // Scan encoder
{
  uint16_t r;

// Энкодер подключен к портам PA0 и РA1 с внешними подтяжками на +5В через 10к резисторы.
// Никакие дополнительные фильтрующие конденсаторы не требуются. 
  r = (uint16_t)GPIOA->IDR & 3;  // Для других портов/битов/МК, применить соответствующую 
				//команду чтения, маску и сдвиг для помещения результата в младшие разряды.
  if (enc_prev != r)
	{
		enc_prev = r;
		enc = ((enc | r) << 2) & 0xFFF;	// применил маску для страховки, можно попробовать без нее
		if (enc == 0x0E1C) // 0x11_10_00_01_11_00, фазы состояний энкодера 3-2-0-1-3
		{
			r = enc = enc_prev = 0;
			turn = 1; // Поворот по часовой стрелке.
		}
			else if (enc == 0x0D2C) // 0x11_01_00_10_11_00, фазы состояний энкодера 3-1-0-2-3
			{
				r = enc = enc_prev = 0;
				turn = -1; // Поворот против часовой стрелки.
			}
				// else turn = 0;  // Энкодер в простое. Обнулить после использования.
	}
}

Естественно, что указанные "против" и "по часовой стрелке" условны, зависят от того, какой вывод энкодера к какому пину МК подключен.

Edited by Zhuk72

Share this post


Link to post
Share on other sites

мягко сказать странный алгоритм... исходящий из предположений

1. начальное состояние энкодера 3

2. в момент получения кодовой посылки ошибки отсутствуют.

Share this post


Link to post
Share on other sites

Ну и что с того, что 3? Его контакты подтянуты к питанию, стало быть на них "1". Главное отлавливать изменение состояний и их правильную последовательность.

Второй момент не понял. Что вы имели в виду? Если есть сомнения в работоспособности, попробуйте в железе. Железозависимая строка тут только одна, меняется элементарно.

Share this post


Link to post
Share on other sites

1. с того что это работает только на энкодерах с положениями(тактильные щелчки)

2. мне это даже проверять не нужно , мне достаточно что я вижу код и понимаю как это "не работает", то что поймав глюк, данные станут валидны минимум только через 4 импульса энкодера или через одно положение, по русски дребезг контактов потрит всю посылку.

Share this post


Link to post
Share on other sites

1. Других не имею.

2. У меня все работает даже на дешевом китайском энкодере. И ваше сомнение никак на это не влияет.

Share this post


Link to post
Share on other sites

то что из-за высокой скорости опроса вы не видите глюков ее не означает что их нет :)

Share this post


Link to post
Share on other sites

Специально для вас при первом же удобном случае сделаю опрос каждые 10 мс.

Share this post


Link to post
Share on other sites

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

On 10.07.2017 at 11:21 PM, SHipa said:

по данной программе выдает примерно 330-340 импульсов на оборот

таких что-то не припомню. А вот 360 импульсов на оборот да (это импульсов на фазу)

On 10.07.2017 at 12:10 AM, Alex said:

Дребезг контактов учитываете ?

там дребезга не будет. Оптроны

Edited by mail_robot

Share this post


Link to post
Share on other sites
3 минуты назад, mail_robot сказал:

там дребезга не будет. Оптроны

да ну...

Share this post


Link to post
Share on other sites

ну если энкодер "фирменный", то да. Скорее всего да ну

но в аппаратке обычно стоит фильтр на это дело. Причем такецкий фильтр, что даже от обычного ручного энкодера звон отрабатывает. Мега тут полюбому сдуется, как ни крути. Так что смысла качать эту тему на таком железе думаю нет. Можно конечно попробовать воткнуть на каждую фазу по емкости, но тогда фронты могут начать заваливаться на приемлемом подавлении. Ну можно тогда воткнуть ТШ, это поможет. Но все равно надо будет успевать отрабатывать по 360 импульсов на фазу. Причем и по фронту и по срезу. И это еще не известно какая скорость вращения

Оговорка - если мега будет работать только на энкодер, то сколько то оборотов/секунду она сдюжит. Не выполняя основной код )

Edited by mail_robot

Share this post


Link to post
Share on other sites
Только что, mail_robot сказал:

Мега тут полюбому сдуется, как ни крути.

ну по поводу меги не знамо, а первоисточник для ПЫХ на приведенный мной код утверждает работоспособность по изменению порта до 13кГц при 4,096МГц тактовой

Share this post


Link to post
Share on other sites

это с учетом основного кода? Или чисто при работе на энкодер и не по прерываниям?

Share this post


Link to post
Share on other sites

это в прерывании , судя по коду обработка максимум 38мкс , на основной код остается еще 39мкс

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • By Вячеслав_НС
      помогите разобраться с кодом .(послать значение по шине TWI на ЦАП PCF8591) не работает в протеусе ...
      #define F_CPU 8000000UL 
      #include <stdlib.h>
      #include <avr/io.h>
      #include <util/delay.h>
      //*** ИНИЦИАЛИЗАЦИЯ ШИНЫ TWI ***/
      void TWI_Init(void)
      {
          // Установка тактовой частоты F_scl  = 100 кГц
          TWBR =32;
          TWSR &= (~((1<<TWPS1)|(1<<TWPS0)));
          TWCR |= (1 << TWEN);            // Разрешение работы TWI-модуля
      }

      /*** ЗАПУСК TWI ***/
      void TWI_Start(void)
      {
          TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
          while(!(TWCR & (1<<TWINT)));
          TWDR = 1001000; // передача адреса модуля PCF8591 в шину TWI
          TWCR=(1<<TWINT)|(1<<TWEN);
          while(!(TWCR & (1<<TWINT)));
      }
      /*** ОСТАНОВКА TWI ***/
      void TWI_Stop(void)
      {
          TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
          while(TWCR & (1<<TWSTO));        // Ожидание завершения передачи условия СТОП
      }
      /***ПЕРЕДАЧА ДАННЫХ В TWI***/
      void TWI_WriteByte(uint8_t data)
      {
          TWDR = data;                    // Загрузка данных в TWDR
          TWCR=(1<<TWINT)|(1<<TWEN);
          while(!(TWCR & (1 << TWINT)));    // Ожидание завершения передачи данных
      }
      /*** ПЕРЕДАТЬ ЗНАЧЕНИЕ В PCF8591 ***/
      void PCF8591_get(void)
      {
          TWI_Start();                // Запуск TWI
          TWI_WriteByte(0x40);        //включаем цап
          TWI_WriteByte(100);            // запись в ЦАП значения 100
          TWI_Stop();                    // Остановить TWI
      }            
          int main(void)
      {
          TWI_Init();    
          while (1)
      {
              PCF8591_get;
             _delay_ms(50);
        }
      }
    • By LegionKC
      Добрый день.
      Экспериментирую с платой TP4056 и MK ATmega8, конкретнее - пытаюсь собрать простенькое зарядное устройство с выводом параметров при зарядке/разрядке на АЦП МК. Для измерения тока нашел ACS712. Думаю, что получится выводить ток при зарядке (т.е. когда идет питание на TP4056 и нагрузка отключена) и при разрядке (питание выключено, нагрузка подключена). Нагрузка - резистор. Возникла проблема с измерением напряжения на АКБ. Вернее, проблема с отсутствием идей как это сделать. Может какую-нибудь схему делителя напряжения нужно сделать? Прошу помочь советом. Схему из пэинта прилагаю.
      Спасибо.
       

    • By pndbr
      Здравствуйте. Может у кого есть печатная плата для отладочной платы на atmega8,32,128 в корпусе tqfp или attiny2313.
      Накопилось много распая с незалоченными камнями и очень хочется пустить их в дело и наконецто научиться хоть как-то программировать. Рисовать печатку самому не хватает опыта. Может у кого есть наработки? Прошу поделиться.
      Поиск выдает только отладочные платы в дип. А если и есть tqfp то в ардуиновском формате т.е без доп перефирии (же дисплеев,клавиатуры,7 сегментных индикаторов,потенциометров,энкодеров..и.т.д)
    • By Ruslik334
      Уважаемые электроники-программисты. Кто силен в CVAVR? Или может кто подскажет где уже есть. 
      Есть вот такой прогресс бар https://radioparty.ru/programming/avr/c/361-lesson-lib-lcd написанный в Atmel Studio. Но у меня весь проект в CVAVR, попытался привязать его, но не поддается он мне. Помогите или дайте вектор. На Ардуино много, но там для меня совсем темень
    • By touck
      Энкодер DFS60B-TEPK 10000 (Германия), фотоэлектрический переключатель VL18-4P3140(Италия).Новые в заводской упаковке. Недорого.
×
×
  • Create New...