Страница 1 из 1

Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 12:02:35
AxiDim
Прошу помощи так как пока сам не могу разобраться.

Есть конечная задача сделать USB мультимедиа клавиатуру для Кар ПС. Состоять она будет из двух энкодеров и 4 кнопок.
Один энкодер должен регулировать громкость, второй - переключать треки. Ну а кнопки пока еще не определился.

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

Помогите пожалуйста.
Энкодер подключаю к PB0 PB1 c подтяжкой через резисторы к +5в.

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 12:27:15
Леонид Иванович
Вот как пример:
Спойлер

Код: Выделить всё

//----------------------------------------------------------------------------

//Модуль поддержки энкодера.
//Энкодер подключается к портам ENC_F1 (фаза 1) и ENC_F2 (фаза 2).
//Функция Enc_Scan() вызывается в основном цикле.
//Результат обработки энкодера передается в основную программу
//через функцию OnEncoder().

//----------------------------- Константы: -----------------------------------

#define ENC_F2   (1 << PC1) //фаза энкодера F2
#define ENC_F1   (1 << PC2) //фаза энкодера F1

#define Pin_ENC_F2     (PINC & ENC_F2)
#define Pin_ENC_F1     (PINC & ENC_F1)

enum { State0, StateA, StateB, StateAB }; //состояния энкодера

enum { ENC_UP, ENC_DN }; //код шага вверх и шага вниз.

//----------------------------- Переменные: ----------------------------------

static char EncPrev;      //предыдущее состояние энкодера
static char EncPrevPrev;  //пред-предыдущее состояние энкодера

//----------------------- Инициализация энкодера: ----------------------------

void Encoder_Init(void)
{
  EncPrev = State0;       //инициализация предыдущего состояния
  EncPrevPrev = State0;   //инициализация пред-предыдущего состояния
}

//------------------------- Обработка энкодера: ------------------------------

void Encoder_Exe(void)
{
  char EncCur = 0;
  if(!Pin_ENC_F1) EncCur  = StateA; //опрос фазы 1 энкодера
  if(!Pin_ENC_F2) EncCur |= StateB; //опрос фазы 2 энкодера
  if(EncCur != EncPrev)             //если состояние изменилось,
  {
    if(EncPrev == StateAB &&        //если предыдущее состояние StateAB
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == StateB)          //если текущее состояние StateB,
        OnEncoder(ENC_UP);   //шаг вверх
      else                          //иначе
        OnEncoder(ENC_DN);   //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }
}

//----------------------------------------------------------------------------

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 17:42:22
ua1arn

Код: Выделить всё

static uint_fast8_t old_val;

void spool_encinterrupt(void)
{
	const uint_fast8_t new_val = hardware_get_encoder_bits();	/* Состояние фазы A - в бите с весом 2, фазы B - в бите с весом 1 */

	// dimensions are:
	// old_bits new_bits
	static const int_fast8_t graydecoder [4][4] =
	{
		{
			+0,		/* 00 -> 00 stopped				*/
			-1,		/* 00 -> 01 rotate left			*/
			+1,		/* 00 -> 10 rotate right		*/
			+0,		/* 00 -> 11 invalid combination */		
		},
		{
			+1,		/* 01 -> 00 rotate right		*/
			+0,		/* 01 -> 01 stopped				*/
			+0,		/* 01 -> 10 invalid combination */
			-1,		/* 01 -> 11 rotate left			*/
		},
		{
			-1,		/* 10 -> 00 rotate left			*/
			+0,		/* 10 -> 01 invalid combination */
			+0,		/* 10 -> 10 stopped				*/
			+1,		/* 10 -> 11 rotate right		*/
		},
		{
			+0,		/* 11 -> 00 invalid combination */
			+1,		/* 11 -> 01 rotate right		*/
			-1,		/* 11 -> 10 rotate left			*/
			+0,		/* 11 -> 11 stopped				*/
		},
	};


#if ENCODER_REVERSE
	position1 -= graydecoder [old_val][new_val];
#else
	position1 += graydecoder [old_val][new_val];
#endif
	old_val = new_val;
}


/* вызывается при запрещенных прерываниях */
void encoder_initialize(void)
{
	//rotate = backup_rotate = 0;
	//enchistindex = 0;
	//tichist [enchistindex] = 0;
	//enchist [enchistindex] = 0;
	//hardware_encoder_initialize(); // moved to main


	old_val = hardware_get_encoder_bits();	/* Состояние фазы A - в бите с весом 2, фазы B - в бите с весом 1 */
}

spool_encinterrupt вызывается по изменению уровня на выводах PD2 & PD3 (int0 и int1). Разрешить соответствующие прерывания по любому изменению уровня.

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 20:19:40
AxiDim
Хорошо когда понимаешь, что написал.

Вообщем нашел модуль с таким кодом.
#ifndef _ENCODER_
#define _ENCODER_ 1
/*********************************************************************
Модуль программной поддержки контактного квадратурного энкодера
типа РЕС16 и аналогичных (без использования прерываний)

Copyright 2008 © ARV Research.

Внимание! Вы можете использовать данный модуль по своему усмотрению
в любых проектах. При любой публикации ваших проектов, использующих
этот модуль, следует указать ссылку на сайт http://arv.radioliga.com

Требуется компилятор WinAVR
**********************************************************************/

#define ENC_MAX_SPEED 100 /* максимальная "скорость" вращения энкодера */
#define ENC_BIG_STEP 98 /* "большой" шаг при быстром вращении */
#define ENC_FAST_ROTATE 90 /* константа "быстрого" вращения */

#define ENC_A_PIN 3 /* номер линии порта для сигнала А энкодера */
#define ENC_B_PIN 6 /* номер линии порта для сигнала B энкодера */
#define ENC_A_PORT PIND /* порт, к которому подключен сигнал А энкодера */
#define ENC_B_PORT PINB /* порт, к которому подключен сигнал B энкодера */

#define ENC_A_UP (ENC_A_PORT & (1<<ENC_A_PIN))
#define ENC_B_UP (ENC_B_PORT & (1<<ENC_B_PIN))
#define ENC_A_DN (!ENC_A_UP)
#define ENC_B_DN (!ENC_B_UP)

#define rotate_fast(x) (x > ENC_FAST_ROTATE)
#define DDR(x) (*(&x + 1))
#define PORT(x) (*(&x + 2))
/*
Использование модуля элементарно: в начале программы следует вызвать
функцию enc_init(), которая настроит нужные порты ввода-вывода.
Затем в основном цикле в нужном месте можно обратиться либо к
функции enc_rotate(), которая вернет значение, соответствующее направлению
вращения энкодера, либо функцию enc_delta(), которая кроме направления
возвратит и условную величину скорости вращения.
enc_rotate() позволяет использовать энкодер, как 2 кнопки "+1" и "-1"
enc_delta() уже может заменить 4 кнопки "+1", "+100", "-1" и "-100".
Функция способна отличать "рывки туда-сюда" от простого вращения в
одном направлении.

Нажатие встроенной кнопки энкодера НЕ ОБРАБАТЫВАЕТСЯ
*/


// инициализирует порты, к которым подключен энкодер
void enc_init(void);

/* возвращает направление и скорость вращения энкодера
параметр speed - указатель на переменную, в которую возвращается
условная скорость вращения (число от 0 до 100)

возвращает:
-1 - вращение влево (против часовой стрелки)
0 - нет вращения
1 - вращение вправо (по часовой стрелке)

ВНИМАНИЕ! функция выполняется достаточно длительное время:
максимально (при остановленном энкодере) ENC_MAX_SPEED миллисекунд,
при вращении возвращает управление раньше
*/
signed char enc_rotate(unsigned char * speed);

/* возвращает приращение энкодера:
1 или -1 при медленном вращении,
0 - при остановленном
ENC_BIG_STEP или -ENC_BIG_STEP при быстром вращении

ВНИМАНИЕ!!! Функция выполняется долго!!!
при быстром вращении возвращает управление только ПОСЛЕ ОСТАНОВКИ энкодера!
остановкой считается, если в течение 2*ENC_MAX_SPEED миллисекунд не было импульсов
с энкодера.
*/
signed char enc_delta(void);

#endif
Пытаюсь вызвать его в основном коде, а при компилировании ругается на функцию enc_init().

Помогите как этот модуль заставить работать в моей программе.

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 21:39:00
takei
Объяви в основном цикле enc_init();
А вообще код от ARV, как всегда гавно..

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 21:45:09
AxiDim
Так и делаю, но ошибка вылазит. В скобочках надо что нибудь указывать?

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 22:01:46
Flasher
Вот странно-вылизанный код ЛИ даже не смотрится, а ищется какой-то говянный код...

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Пн апр 21, 2014 22:19:57
ARV
takei писал(а):А вообще код от ARV, как всегда гавно..
потрудитесь объясниться :twisted:

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Вт апр 22, 2014 18:11:05
BCluster
takei писал(а):Объяви в основном цикле enc_init();
А вообще код от ARV, как всегда гавно..
особенно, если учесть что приведен какой-то вообще шмат кода, очень разумно об этом судить.
ТС, там где-то в другом файле есть эти функции, найди их, и будет работать :))))

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Вт дек 20, 2016 18:24:01
VNN84
Не программировал больше 2 лет, все напрочь забыл (((. Помогите, пжл, перевести код этого птичьего языка на читаемый. Мне надо его вставить в CodeVisionAVR. Энкодер висит на PINC.3 и PINC.2 c подтяжкой.
Код понравился этот: http://www.leniwiec.org/en/2014/04/28/r ... 2-168-328/ начитается с Gray’s code method

ОРИГИНАЛ
uint8_t read_gray_code_from_encoder(void )
{
uint8_t val=0;

if(!bit_is_clear(PIND, PD2))
val |= (1<<1);

if(!bit_is_clear(PIND, PD3))
val |= (1<<0);

return val;
}

ПЫТАЮСЬ ПЕРЕПИСАТЬ НА CodeVisionAVR
unsigned char read_gray_code_from_encoder (void)
{
unsigned char val=0;

if(!bit_is_clear(PINC.2)) val |= (1<<1); - РАСШИФРУЙТЕ ЭТО ПЖЛ, НА МОИ ПОРТЫ!

if(!bit_is_clear(PINC.3)) val |= (1<<0);

return val;
}

Дальше код из статьи вроде понятен.

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Вт дек 20, 2016 18:39:56
Аlex

Код: Выделить всё

if(!bit_is_clear(PINC, 2))
    val |= (1<<1); 

if(!bit_is_clear(PINC, 3))
    val |= (1<<0);
bit_is_clear скорее всего, задефайнен как-нибудь так :

Код: Выделить всё

#define bit_is_clear(var, bit)       (((var)&(1<<bit))==0)
Либо, для CV-синтаксиса :

Код: Выделить всё

if(PINC.2)
    val |= (1<<1); 

if(PINC.3)
    val |= (1<<0);

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Вт дек 20, 2016 18:46:23
VNN84
Да, спасибо. Запустил энкодер, крутит отлично. Но только вот на быстрое вращение не очень реагирует. Буду дальше разбираться.
Еще вопрос: val |= (1<<1) - можно это переписать в человеческий синтаксис? А то через пару месяцев опять буду смотреть как на китайскую грамоту )))

Re: Энкодер + atmega8 + CodeVisionAVR

Добавлено: Вт дек 20, 2016 21:40:47
Zhuk72
VNN84 писал(а):Еще вопрос: val |= (1<<1) - можно это переписать в человеческий синтаксис? А то через пару месяцев опять буду смотреть как на китайскую грамоту )))
Выставить бит 1 в val. Иначе говоря, val |= 0b00000010 или val = val | 2.