Rotační enkodér (detekce vpravo a vlevo)

C,C++,C#

Moderátori: psichac, Moderátori

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 12:50

Ahojte. Už delší dobu řeším problém s rotačním enkodérem. Zde je můj kód. A problém spočívá v tom, že při přerušení má dojít k rozeznání jestli se točí doprava nebo doleva a podle toho snižovat nebo zvyšovat proměnnou . Ale zde dochází pouze k tomu, že se hodnota enc jen odečítá ať točím tam nebo tam. A já nevím kde by mohla být chyba. Najde se někdo, kdo by poradil? Dík moc

Kód: Vybrať všetko

#include <stdlib.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "lcd.h"


#define F_CPU 16000000UL

// Deklarace promennych
char str[4];
int enc = 0;
unsigned int timercounter = 0;

// deklarace timerů
void initInterrupts(void);
void TimerInit(void);

//Preruseni INT1

ISR(INT1_vect)
{
 //pokud dojde k preruseni, probehna kontrola pinu PD5 k urceni smeru
 //a podle toho pricteni nebo odecteni 
	 if (PIND & (1 << PD5)) {
	    if (PIND & (1 << PD3)) {
	      enc--;
	    } else {
	      enc++;
	    } 
	    // change to falling detection
	    MCUCR |= ((0 << ISC00) | (1 << ISC01));
	  } else {
	    if (PIND & (1 << PD3)) {
	      enc++;
	    } else {
	      enc--;
	    } 
	    // change to rising detection
	    MCUCR |= ((1 << ISC00) | (1 << ISC11));
	  } 

 //timercounter = 0;
}

// preruseni kazdyhc 10ms
ISR(TIMER1_COMPA_vect)
{
	 // Reset timeru
	 TCNT1 = 0;
}

// Inicializace INT1
void initInterrupts(void)
{
	 // nastaveni PD3 a PD5 jako vstupu
	 DDRD &= ~(1<<PD5);
	 DDRD &= ~(1<<PD3);

	 // povoleni pull-up odporu
	 PORTD |= (1<<PD5)|(1<<PD3);

	 // Preruseni na sestupnou hranu na INT1
	 MCUCR |= (1<<ISC11);
 
	 // povoleni INT1
	 GICR |= (1<<INT1);
}

void TimerInit(void)
{
 
	 // nastaveni delicky (clk/64)
	 TCCR1B |= _BV(CS10);
	 TCCR1B |= _BV(CS11);

	 // 250 pulzu -> kazdou 1 ms test
	 OCR1A = 250;

	 // smazani OCF1A flag
	 TIFR |= _BV(OCF1A);

	 // Povoleni Timeru1 v rezimu COMPARE
	 TIMSK |= _BV(OCIE1A);
}

// Hlavni fce
int main(void)
{
	 // Inicializace IO a casovacu
	 initInterrupts();
	 TimerInit();

	 // povoleni global. preruseni
	 sei();

	 // Inicializace LCDcka
	 lcd_init(LCD_DISP_ON);
	  // napis na prvnim radku LCDcku
	 lcd_gotoxy(0,0);  
	 lcd_puts("Encoder test");


 // nekonečník
 while (1)
 {
   // zapis na LCDcko na pozici 0,1 (znak,radek)
   lcd_gotoxy(0,1);  
   lcd_puts(itoa(enc, str, 10));

   _delay_ms(10);
 }
}

0

sarisHD
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1238
Dátum registrácie: 03 Mar 2009, 00:00

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa sarisHD » 18 Okt 2012, 13:05

0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 13:23

díky moc. Kouknu na to. Snad se mi to z toho podaří.
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 15:06

Tak problém stále trvá a to jsem zkusil co se dalo. Zde jsem zkusil použít rutinu ze stránek, co mi byla doporučena: tady

Kód: Vybrať všetko

ISR(INT1_vect){
  if (PD5)
  {
	  if (enc == 255)
	  {
	  }
	  else
	  	enc++;	
  }
  else
	  if (enc == 0)
	  {
	  }
  	  else
	  {
	  	enc--;
	  }
} 
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 19:25

Tak já už fakt nevím. Přepsal jsem celý program, ale asi dělám jednu a tu samoou chybu. Tady je můj nový kód, a stále dochází k tomu, že se při otáčení enkodéru číslo pouze zmenšuje nezávisle na otáčení (doleva / doprava). Jestli někdo budete mít chvilku, koukněte mi na to. Dík moc za jakoukoli radu

Kód: Vybrať všetko

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#include "lcd.h"
#include "rotary.h"

long int position=0;					

void pause (unsigned int a)				
{ unsigned int i;

  for (i=a;i>0;i--)
   ;
}

char text[16];
void write_position(void)
{ unsigned char i; 
  long int temp;
   temp=position;
   itoa(temp,text,10);
   lcd_gotoxy(0,0);
   lcd_puts(text);
}

ISR (INT0_vect)
{
 if (((PIND&0x01)==0x00)&&(position<9999)) position=position+1;		//inc 
 if (((PIND&0x01)==0x01)&&(position>-9999))position=position-1;		//dec 
}

int main(void)
{ 
DDRD=0xfa;				//PD0,PD2 jako vstup, ostatní jako vystup
PORTD=0x05;				

pause(3000);			//pauza
lcd_init(LCD_DISP_ON);				//Init LCD

 MCUCR=(1<<ISC01)|(1<<ISC00);	//Set INT0 on rising signal on PD2
 GICR=(1<<INT0);

 write_position();		//Write position
	
sei();					//povoleni přerušení

while(1)
 write_position();
return 1;
}

0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa Radus » 18 Okt 2012, 19:42

Ahoj, ako to máš vlastne zapojené? Aký MCU?
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 19:56

Zrovna teď k tomuto programu to mám zapojené:

Enkodér A: PD2 (INT0)
Enkodér B: PD0
LCD mám na portu A bity: 0..5.

Používám Atmegu16 a programuju to v AVR Studiu 4.
0

Používateľov profilový obrázok
awen
Power user
Power user
Príspevky: 609
Dátum registrácie: 11 Feb 2009, 00:00
Bydlisko: Bratislava
Vek: 36

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa awen » 18 Okt 2012, 19:59

Budes tam mat asi zakmity na vystupe z enkodera. Skus pridat kratku pauzu hned po vstupe do ISR a az potom precitat stav PIND.
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 20:04

No ani po přidání krátké prodlevy se nic nezměnilo. Teď přemýšlím, jestli se mi nějak nepodařilo spálit ten enkodér. :-D
Páč už fakt nevím kde by mohla být chyba.
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa Radus » 18 Okt 2012, 20:08

... skús PD0 natvrdo uzemniť, či bude pripočítavať.... (Odpoj Bčko od enkódera a PD0 uzemni...)
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 20:11

No jo. Ejhle. Po uzemnění to i přičítá. Takže problém v SW nebude. :-D
0

Používateľov profilový obrázok
awen
Power user
Power user
Príspevky: 609
Dátum registrácie: 11 Feb 2009, 00:00
Bydlisko: Bratislava
Vek: 36

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa awen » 18 Okt 2012, 20:11

prerusenie mas nastavene na rising edge? Nemalo by byt naopak? :!:
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa Radus » 18 Okt 2012, 20:12

jj, enkóder... vyriešené :)
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 20:14

Tak teď teda nevím. Podle mě to přerušení má být na raising. Ne???
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa Radus » 18 Okt 2012, 20:19

... pošli mi prosím hexa kód, poviem ti to presne.... ... skúšal som rising aj fallinig, funguje to naopak.. :)
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 18 Okt 2012, 21:19

Tady připojuju ten HEX.
Prílohy
rusko_1.hex
(4.16 KiB) 48 stiahnutí
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 06 Nov 2012, 22:01

Zdravíčko. Tak opravdu, problém byl v tom enkodéru. Takže tohle jsem vyřešil.
Ale teď mám nový problém, který řeším dneska celý den, ale ne a ne s ním hnout.
Pomocí toho rotačního enkodéru se snažím nastavit časovač. Nebo-li rotačním enkodérem nastavím hodiny, stisknu tlačítko, nastavím minuty, tlačítko, sekundy. Ale nějak si to dělá co chce. Zapnu program, nastavím hodiny, stisknu tlačítko a už jsem třeba na sekundách. Někdy se nedostanu nikam a zrovna vypadnu ven.

tady je kód kde bych očekával chybu, ale ne a ne na to přijít. Může někdo poradit??

Kód: Vybrať všetko

unsigned char hodiny[16], minuty[16], sekundy[16];
unsigned char flag_h=0;
unsigned int pomoc=0;
unsigned int pomoc_m=0;
unsigned int pomoc_s=0;

void nastav_cas(void)
{
	if (flag_h==0)		//hodiny
		{
		lcd_gotoxy(0,0);
		pomoc=position;
		itoa(pomoc/10, hodiny, 10);
		lcd_puts(hodiny);
		itoa(pomoc%10, hodiny, 10);
		lcd_puts(hodiny);
			if (pomoc>=24)
			{position=0;}
		}
	if (flag_h==1)		//minuty
		{
		lcd_gotoxy(3,0);
		pomoc_m=position;
		itoa(pomoc_m/10, minuty, 10);
		lcd_puts(minuty);
		itoa(pomoc_m%10, minuty, 10);
		lcd_puts(minuty);
			if (pomoc_m>=59)
			{position=0;}
		}
	if (flag_h==2)
		{
		lcd_gotoxy(6,0);
		pomoc_s=position;
		itoa(pomoc_s/10, sekundy, 10);
		lcd_puts(sekundy);
		itoa(pomoc_s%10, sekundy, 10);
		lcd_puts(sekundy);
			if (pomoc_s>=59)
			{position=0;}
		}
}
a zde je přerušení od tlačítka a enkodéru. To přerušení toho enkodéru už vím že funguje.

Kód: Vybrať všetko

//============================================================================
//==================================PRERUSENI=================================
//============================================================================
ISR (INT0_vect)		//ratační enkoder (vlevo/vpravo)
    {
		cli();	//zákaz přerušení, kvůli tlačítku
	if (((PIND&0x01)==0x00)&&(position<9999)) position=position+1;      //inc
	if (((PIND&0x01)==0x01)&&(position>0))position=position-1;      //dec 
		sei();
    }

ISR(INT1_vect)		//tlačitko
	{  
		cli();
		flag_h++;
			if (flag_h==1)
				{pomoc=position;}
			if (flag_h==2)
				{pomoc_m=position;}
			if (flag_h==3)
				{pomoc_s=position;}
		position=0;
		sei();
    } 
A pro jistotu přidávám i main.

Kód: Vybrať všetko

//============================================================================
//=====================================MAIN===================================
//============================================================================
int main(void)
{
    //nastaveni vstupnich pinu portu D
//DDRD=0xfa;            	//PD0,PD2 
DDRD &= ~(1 << PD0);	//PD0 jako vstup
DDRD &= ~(1 << PD2);	//PD2 jako vstup
DDRD &= ~(1 << PD3);	//PD3 jako vstup
	//povoleni vnitřních pull-up odporu
PORTD |= (1 << PD0);
PORTD |= (1 << PD2);
PORTD |= (1 << PD3);
	//nastaveni preruseni od tlacitek
MCUCR|=(1<<ISC01)|(1<<ISC00);   //Set INT0 on rising signal on PD2
MCUCR|=(1<<ISC11)|(1<<ISC10);   //Set INT1 on rising signal on PD3
GICR |=(1<<INT0 )|(1<< INT1);	//enable interrupt

	//nastaveni preruseni od casovace

	//nastaveni displeje
lcd_init(LCD_DISP_ON);            //Init LCD
lcd_gotoxy(0,0);
lcd_puts("00:00:00");

sei();               //povoleni přerušení

	//nastav_cas();	
	
    while(1)
	nastav_cas();	
    return 1;
Budu rád za každou odpověď. Dík moc
0

Používateľov profilový obrázok
petersno
Ultimate člen
Ultimate člen
Príspevky: 2774
Dátum registrácie: 06 Aug 2011, 00:00
Bydlisko: ba
Vek: 63

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa petersno » 06 Nov 2012, 22:13

podla popisu ide o snimanie zakmitov tlacitka. niekedy staci 100n paralelne k tlacitku, niekedy treba sw osetrenie. ak nebude stacit kond, v mikroprocesoroch najdes priklady kodu
0

Používateľov profilový obrázok
Gavin Milarrr
Ultimate člen
Ultimate člen
Príspevky: 2533
Dátum registrácie: 06 Okt 2008, 00:00
Bydlisko: Liberec
Vek: 47

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa Gavin Milarrr » 06 Nov 2012, 22:25

Jste rozmazlený, mě na to stačily dva šváby...
0
Taky vás štve debilita a sopláctví? Na http://efis.tul.cz/forum běží experimentální odblbené fórum.

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: Rotační enkodér (detekce vpravo a vlevo)

Príspevok od používateľa jirka.jirka. » 06 Nov 2012, 22:37

Gavin Milarrr napísal:Jste rozmazlený, mě na to stačily dva šváby...
určitě by to šlo pomocí švábů, ale tak samo to musí jít i pomocí kódu.

Tak jsem použil kondík 100n a je tam vidět zlepšení. Ale pořád občas blbe. Jak by se daly jednoduše na tom ošetřit zákmity?
0

Napísať odpoveď