|
|
  |
Энкодер, алгоритм обработки сигнала |
|
|
|
Jan 26 2011, 13:47
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901

|
Добрый день. Алгоритм обработки энкодера взял здесь. Переделал для CVAVR, но заставить работать не получается. К порту B подключены светодиоды, сигналы энкодера A и B подключены к порту D 2 и 3 соответственно. Код Chip type : ATtiny2313 Clock frequency : 8,000000 MHz Memory model : Tiny External SRAM size : 0 Data Stack size : 32 *****************************************************/
#include <tiny2313.h>
int New; // новое значение состояния энкодера unsigned char EncData; // счётный регистр энкодера int EncState; // предыдущее состояние энкодера
void EncoderScan(void) {
New=PIND&0xC; // копируем в New состояние входов 2,3
switch (EncState) // сравниваем текущее значение New со старым смотря в какую сторону вращение изменениям EncData ++ или -- { case 2: { if (New==3) EncData++; if (New==0) EncData--; break; } case 0: { if (New==2) EncData++; if (New==1) EncData--; break; } case 1: { if (New==0) EncData++; if (New==3) EncData--; break; } case 3: { if (New==1) EncData++; if (New==2) EncData--; break; } } EncState=New; // записываем новое значение предыдущего состояния } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { EncoderScan(); // запускаем функцию сканирования энкодера }
// Declare your global variables here
void main(void) { // Declare your local variables here
// Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif
// Port B initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTB=0x00; DDRB=0xFF;
// Port D initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=P State5=P State4=P State3=P State2=P State1=P State0=P PORTD=0x7F; DDRD=0x00;
// Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 1000,000 kHz // Mode: Normal top=FFh // OC0A output: Disconnected // OC0B output: Disconnected TCCR0A=0x00; TCCR0B=0x02; TCNT0=0x00; OCR0A=0x00; OCR0B=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x02;
// Global enable interrupts #asm("sei")
while (1) { PORTB=EncData; }; } Где моё упущение?
|
|
|
|
|
Jan 26 2011, 14:03
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(RicLab @ Jan 26 2011, 16:47)  Где моё упущение?  Вместо Код New=PIND&0xC; следует записать Код New=(PIND >> 2)&0x3; P.S. В начале программы хорошо бы переменной EncState присвоить значение. Как-то так: Код EncState=(PIND >> 2)&0x3;
|
|
|
|
|
Jan 26 2011, 14:05
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Упущение в "магических" константах 0, 1, 2, 3 в операторе switch. Биты вы скопировали, но не туда. switch их ожидает увидить в нулевом и первом битах. Если сделать так: Код New=PIND&0xC >> 2; то должно работать.
|
|
|
|
|
Jan 26 2011, 14:43
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901

|
заработало но на один щелчок энкодера на выходе 4 импульса. Так и должно быть по алгоритму. Как можно сделать 1 щелчок 1 импульс? Автор статьи писал об этом, Цитата А по моей логике, на один импульс приходится четыре смены состояния, т.е. полный период 3201_3201_3201 и один щелчок дает 4ре деления, что некрасиво. Поэтому я считаю до 1024, а потом делю сдвигом на четыре. Получаем на выходе один щелочок - один тик. но я не совсем понял как это реализовать.
|
|
|
|
|
Jan 26 2011, 14:47
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Цитата(RicLab @ Jan 26 2011, 17:43)  Как можно сделать 1 щелчок 1 импульс? Выкинуть из switch три любые ветки case.
|
|
|
|
|
Jan 26 2011, 14:58
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901

|
тогда пострадает надёжность распознования вращения энкодера. Проверил в железе, бывают ложные импульсы.
|
|
|
|
|
Jan 26 2011, 15:23
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(RicLab @ Jan 26 2011, 17:43)  Как можно сделать 1 щелчок 1 импульс? Ну, так же написано: "делю сдвигом на четыре"... Т.е. завести новую переменную, которая будет изменяться на единицу за один щелчок. Вычислять её - как-то так: Код NewEncData= EncData >> 2; что тоже самое Код NewEncData= EncData / 4;
|
|
|
|
|
Jan 26 2011, 15:33
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901

|
сильно не ругайте, я начинающий За советы большое спасибо.
|
|
|
|
|
Oct 17 2011, 17:58
|
Группа: Новичок
Сообщений: 2
Регистрация: 4-12-10
Пользователь №: 61 396

|
а у меня похожый проект.. так же прицеплен енкодер на входы INT0-INT1. у меня енкодер с розришением 1000имп\оборот и гдето в програме ошыбка у меня не работает на железе вот такой код... вроде всё просто а ошибку не могу найти(... у меня считает только в одну сторону (только в+)считает хорошо импульсы не пропускает, а если крутить вал енкодера в противоположную сторону то тоже считает в +..... помогите пожалуста)
#include <mega8535.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x1B ;PORTA #endasm #include <lcd.h> #include <stdio.h> #include <math.h> #include <delay.h> #define KEYIN PINC
char string_LCD[16]; int H,h,i; //i - счётчик импульсов... остальное для обработки количества импульсов
// External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { if (PIND.3==0) { //////////////////////// if (h==5) {h=0;H++;}; i++; h++; if (h==5) { H++; h=0;}; //////////////////////// } else { //////////////////////// if (h==0) {h=5;H--;}; i--; h--; if (h==0) {H--; h=5;}; //////////////////////// }; #asm("cli") }
// External Interrupt 1 service routine interrupt [EXT_INT1] void ext_int1_isr(void) { #asm("cli") } // Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) { } // Declare your global variables here /////////////////////////////////////////////////////////////////////
void print(void) { ///////////////////////////////////////////////////////////// lcd_gotoxy(0,0); sprintf(string_LCD,"i=%iimp ",i); lcd_puts(string_LCD); lcd_gotoxy(9,0); sprintf(string_LCD,"h=%i ",h); lcd_puts(string_LCD); lcd_gotoxy(9,1); sprintf(string_LCD,"H=%imm ",H); lcd_puts(string_LCD); ///////////////////////////////////////////////////////////// } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00;
// Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00;
// Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out // State7=T State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=0 DDRC=0x0F; PORTC=0xFF;
// Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=0 State6=0 State5=0 State4=0 State3=T State2=T State1=T State0=T DDRD=0xF0; PORTD=0x00;
// Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 125,000 kHz // Mode: Normal top=FFh // OC0 output: Disconnected TCCR0=0x02; TCNT0=0x00; OCR0=0x00;
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 0,977 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x05; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x03; OCR1AL=0xD1; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00;
// External Interrupt(s) initialization // INT0: On // INT0 Mode: Rising Edge // INT1: Off // INT2: Off GICR|=0x40; MCUCR=0x03; MCUCSR=0x00; GIFR=0x40;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00;
// LCD module initialization lcd_init(16); // Global enable interrupts #asm("cli"); while (1) { print(); /////////////////////////// #asm("sei; nop; cli; nop") /////////////////////////// }; }
|
|
|
|
|
Oct 20 2011, 19:30
|
Группа: Новичок
Сообщений: 2
Регистрация: 4-12-10
Пользователь №: 61 396

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