Sida 1 av 1

Rotationsenkoder

Postat: 16 oktober 2009, 17:14:14
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

Re: Rotationsenkoder

Postat: 16 oktober 2009, 17:20:09
av sodjan
KOMMENTERA !!
V.v tala om vad du *tror* att du gör i koden...

Re: Rotationsenkoder

Postat: 16 oktober 2009, 17:26:14
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

Re: Rotationsenkoder

Postat: 16 oktober 2009, 17:35:41
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.

Re: Rotationsenkoder

Postat: 16 oktober 2009, 17:46:38
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

Re: Rotationsenkoder

Postat: 16 oktober 2009, 18:05:10
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...

Re: Rotationsenkoder

Postat: 16 oktober 2009, 19:59:48
av AndersG

Re: Rotationsenkoder

Postat: 24 oktober 2009, 20:02:03
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++;}
  }

}

Re: Rotationsenkoder

Postat: 24 oktober 2009, 20:29:29
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.

Re: Rotationsenkoder

Postat: 25 oktober 2009, 00:25:01
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.

Re: Rotationsenkoder

Postat: 14 november 2009, 15:29:22
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

Re: Rotationsenkoder

Postat: 14 november 2009, 16:50:59
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.