Rotationsenkoder

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
davrex
Inlägg: 149
Blev medlem: 18 januari 2009, 22:05:15

Rotationsenkoder

Inlägg av davrex »

Hej sitter nu här i ett litet projekt och försöker få en Rotationsenkoder men det går inte riktigt som det är tänkt. problem 1 att den oftast inte reagerar ens när jag vrider på den men vrider jag riktigt långsamt så ibland så räknar den. Men det kan också hända att den räknar åt fel håll. Så nu behöver jag lite hjälp med hur det ska se ut Här är min nuvarande kod.

denna delen som inte funkar: har alltså koppas in den på pin 0 och 1 på PORTD

Kod: Markera allt

   if(PIND & 0x01){ //kollar om pin 1 är 1 isåfall
	while(temp == 0 || PIND & 0x02){  // vänta här medans temp == 0 eller pin 2 är 1
		if(PIND & 0x02){ // kolalr om pin 2 är 1 i så fall sätt temp till 1
			temp =1;
		}
	}
	temp=0;   //sätter temp till 0 då den har kommit ut loopen och 
	spwm++; // ökar spwm med 1
	test++;   //ökar test med 1
	}
	  if(PIND & 0x02){
	while(temp==0 || PIND & 0x01){
		if(PIND & 0x01){
			temp =1;
		}
	}
	temp=0;
	spwm--;
	test--;
	}

hela koden om det nu hjälpter

Kod: Markera allt

#define F_CPU 8000000

#include <util/delay.h>
#include <avr/interrupt.h>


#define bit_on(BYTE, BIT)  BYTE |= 1 << BIT;
#define bit_off(BYTE, BIT) BYTE &= ~(1 << BIT);

volatile int  rpwm, gpwm, bpwm,spwm, antal,test=100;
volatile int  time=0;
volatile char led_out=0;

int temp =0;

int main (void)
{
   sei();


  rpwm=5;
  gpwm=5;
  bpwm=255;
  spwm=170;
  antal=255;

  DDRC=0xFF; 
  PORTC=0x00;
  DDRB=0xFF;
  PORTB=0x00;
  DDRD = 0x00;
  PORTD = 0x00;

  //Timer0 8Bit setup, ansvarig för PWM
  bit_on(TCCR0, CS00);   
  bit_off(TCCR0, CS01);
  bit_off(TCCR0, CS02);

  TCNT0 = 0x00; 

  bit_on(TIMSK, TOIE0);

  while(1) 
   {

   if(PIND & 0x01){
	while(temp == 0 || PIND & 0x02){
		if(PIND & 0x02){
			temp =1;
		}
	}
	temp=0;
	spwm++;
	test++;
	}
	  if(PIND & 0x02){
	while(temp==0 || PIND & 0x01){
		if(PIND & 0x01){
			temp =1;
		}
	}
	temp=0;
	spwm--;
	test--;
	}

PORTB=test;
  _delay_ms(20);        
	while(rpwm<250){
		rpwm++;
		bpwm--;
		_delay_ms(5); 
	}
	while(gpwm<250){
		gpwm++;
		rpwm--;
		_delay_ms(5); 
	}
	while(bpwm<250){
		bpwm++;
		gpwm--;
		_delay_ms(5); 
	}
}   

}  

SIGNAL(TIMER0_OVF_vect)

{

 TCNT0=256;

  time++;

  if(time>=antal) time=0;

  if(time>=rpwm)
 	 {
 	   bit_off(led_out,0);
 	 }
  else
 	 {
  	  bit_on(led_out,0);
 	 }
  
  if(time>=gpwm)
 	 {
 	   bit_off(led_out,2);
 	 }
  else
 	 {
	    bit_on(led_out,2);
 	 }
  
  if(time>=bpwm)
 	 {
 	   bit_off(led_out,1);
	  }
  else
 	 {
 	   bit_on(led_out,1);
	  }
 if(time>=spwm)
 	 {
 	   bit_off(led_out,3);
	  }
  else
 	 {
 	   bit_on(led_out,3);
	  }

  PORTC = led_out;
}

EDIT: Kommentera nu koden som jag tror är fel
Senast redigerad av davrex 16 oktober 2009, 17:25:21, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Rotationsenkoder

Inlägg av sodjan »

KOMMENTERA !!
V.v tala om vad du *tror* att du gör i koden...
davrex
Inlägg: 149
Blev medlem: 18 januari 2009, 22:05:15

Re: Rotationsenkoder

Inlägg av davrex »

kommentera nu den delen jag tror felet är i eller stort sätt vet att felet är där då övrig kod funkar
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Rotationsenkoder

Inlägg av sodjan »

Det hela verkar bero på att du ligger och väntar.
Läs av encodern regelbundet (några 100 gr/sek brukar vara OK,
jag körde med 400 gr/sek) och jämfär med föregående avläsning.
davrex
Inlägg: 149
Blev medlem: 18 januari 2009, 22:05:15

Re: Rotationsenkoder

Inlägg av davrex »

Hmm okej hur läste du av din? kännas av att mitt sätt inte är det bästa och nu funkar den att läsa av efter jag tog bort delayer
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Rotationsenkoder

Inlägg av sodjan »

En timer triggade en läsrutin ca 400 gr/sek.
Där jämfördes aktuellt värde på de två signalpinnarna
med föregående värde. Om det inte var något skillnad
så gjordes ingenting. Om det var skillnad så bestämdes
riktingen beroende på vilken skillnad det var. Om man vred
riktigt snabbt så missades läsningar, men det har ju ingen
betydelse när man vrider snabbt...
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9127
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: Rotationsenkoder

Inlägg av AndersG »

davrex
Inlägg: 149
Blev medlem: 18 januari 2009, 22:05:15

Re: Rotationsenkoder

Inlägg av davrex »

Har nu gjort ett försök till en bättre kod än den jag hade tidigare denna funkar nästan ända problemet är att varje gång jag vrider ett snäpp så ökar den eller sänker 2 steg. Och jgar har nu stirrat mig bild och fattar inte felet. Och behöver lite hjälp att fatta varför. Tack på för hand

Kod: Markera allt

SIGNAL(TIMER2_OVF_vect)
{


  static unsigned char enc_last = 0;
  unsigned char i = 0;

  if( PINB & 1 )                // input pin D0
    i++;
  if( PINB & 2 )                // input pin D1
    i ^= 3;                     // convert gray to binary

  i -= enc_last;                // difference new - last
  enc_last += i;                // store new as next last

  if( i & 1 ){                  // bit 0 = value (1)
    if( i & 2 ){                 // bit 1 = direction (+/-)
	  spwm--;}
    else{
	  spwm++;}
  }

}
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Rotationsenkoder

Inlägg av Icecap »

Såhär gör jag i ett projekt:
ENC_1_L och ENC_1_H är vilka bits som används, t.ex. 0x01 och 0x02, 0x04, 0x08 eller liknande.

Kod: Markera allt

  Curr_Enc_Port = ENCODER_PORT & (ENC_1_L | ENC_1_H); // Read used port pins
  if(Curr_Enc_Port != Prev_Enc_Port)
    {
    if((Curr_Enc_Port ^ Prev_Enc_Port) & (ENC_1_H | ENC_1_L))
      {
      Work_P = Prev_Enc_Port & (ENC_1_H | ENC_1_L);
      Work_C = Curr_Enc_Port & (ENC_1_H | ENC_1_L);
      if((Work_P == (ENC_1_H | ENC_1_L)) && (Work_C ==  ENC_1_H))
        {
        Pulses++; // At least one step!
        }
      if((Work_P ==  ENC_1_H) && (Work_C == (ENC_1_H | ENC_1_L)))
        {
        Pulses--; // At least one step!
        }
      }
    Prev_Enc_Port = Curr_Enc_Port;
Prev_Enc_Port är en variabel som sparas (alltså en "static"). Programsnutten ovan kallas med 1kHz i en timer-ISR men det är för att den 1kHz används till annat och det är faktisk 3 encoders som avkännas fast med var sin programsnudd. Jag har även plockat bort accelerationsdelen (snabb vrid = många steg per klick) då de bara används som potentiometer. Projektet detta används i är en 2-fas generator med 3 oberoende utgångar som simulerar rotationsgivare, ger frekvenser mellan 0,125Hz och 50,0kHz.
Senast redigerad av Icecap 25 oktober 2009, 09:03:12, redigerad totalt 1 gång.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Rotationsenkoder

Inlägg av jesse »

gör ett flödesschema. Då ser du lättare vad du gör.

Och när det gäller encoder - gör ett tillståndsschema (se nedanstående länk) så vet du vad processorn är i för tillstånd beroende på vilka signaler den fått in.

Vill du ha idéer kring hur man läser av encoders kanske den här tråden kan ge lite tips.
davrex
Inlägg: 149
Blev medlem: 18 januari 2009, 22:05:15

Re: Rotationsenkoder

Inlägg av davrex »

Kanske ska skiva hur jag löste det till slut om någon undrar :)

Kod: Markera allt

int checkEncoder(){	 //returns the state of the encoder
  static int e = 3;
  static int waitcount = 0;

  if ( bit_get(PINB,BIT(0)) ) { 	//we have a trigger signal

    if ( bit_get(PINB,BIT(1)) ) {  // rotating left or right?
      if ( e != 1 ) 	//debounce for polling
	waitcount++;
      e = 1;
    }
    else {
      if ( e != 2 )		//debounce for polling
	waitcount++;
      e = 2;
    }
  }
  else {
    e = 3;
    waitcount = 0;
  }

  if ( waitcount > 1 ) {  //only give a L/R value after non-wait transition
    waitcount = 0;
    return e;
  }
  else
    return 3;	  //ignore
}
sedan kör jag bara denna i en case sats
Användarvisningsbild
E85
Inlägg: 1274
Blev medlem: 29 maj 2007, 16:24:19
Ort: Övik

Re: Rotationsenkoder

Inlägg av E85 »

Jag hade problem med att jag tappade steg när jag snurrade riktigt snabbt men om man kör med interrupt på en pinne och i interruptet kollar man hur den andra pinnen står (för riktning) så funkar det klockrent.
Skriv svar