News:

Değerli Üyelerimiz,
Forumumuzun altyapısını, sizlere daha iyi bir deneyim sunabilmek adına güncelledik. 2.0.14 sürümünden 2.1.4 sürümüne geçiş yaparak güvenlik, performans ve kullanım kolaylığı açısından önemli iyileştirmeler sağladık.

Main Menu

Atmega 328P encoder

Started by tahtaco, 13 February 2016, 19:46:15

Previous topic - Next topic

tahtaco

Merhaba rotary encoderle değişken değerlerini artır azaltmak istiyorum.
240,45,90 değerleri artırıp azaltmak istiyorum.
timer_1_set_one_shot_value(CALC_US(240));
state = STATE_IS_1;
timer_1_set_one_shot_value(CALC_US(45));
state = STATE_IS_2;
timer_1_set_one_shot_value(CALC_US(90));
state = STATE_IS_3;

uint8_t val =240,val1=45,val2=90; değişkenlere değerleri  verdik.

timer_1_set_one_shot_value(CALC_US(val));
state = STATE_IS_1;
timer_1_set_one_shot_value(CALC_US(val1));
state = STATE_IS_2;
timer_1_set_one_shot_value(CALC_US(val2));
state = STATE_IS_3;



     

    ISR (INT0_vect)
{

if (((PIND&0x04)==0x00)&&(val<240)&&(val1<45)&&(val2<90))   val = val +1 ;   val1  = val1 +1 ;   val2 = val2 +1;    //inc
if (((PIND&0x02)==0x01)&&(val >200)&&(val<25)&&(val2<70))     val = val -1;     val1 = val1 -1 ;       val2 = val2 -1;      //dec

}

 

   
   int main(void)
{
        DDRD &= ~(1 << PD2); //encoder A   input a
DDRD &= ~(1 << PD3); //encoder B input   b
PORTD |= (1 << PD2);    //Pull-UP R
PORTD |= (1 << PD3);    //Pull-UP R
}


int main kısmında hangi registerleri set etmem gerekiyor INT0,INT1 aktif etmek için çok teşekkürler.



__root

#1
Merhaba
Genellikler bu tür basit mikrodenetleyicilerde iki yöntem var. Birincisi sürekli poll yöntemi diğeri interrupt yöntemi. Ben daha önce poll yöntemini kullanmıştım.

b0 = pin_get_status(p0);
b1 = pin_get_status(p1);

if (r_flag==0){
if (b0==0 && b1==1){
azaltildi = 1;
r_flag=1;
}else if (b0==1 && b1==0){
arttirildi = 1;
r_flag=1;
}if (b0==0 && b1==0){
r_flag=1;
}
}else{
if (b0==1 && b1==1){
r_flag=0;
}
}


po ve p1 encoderin iki ucu.burada r_flag b0, b1 static değişkenler. bu fonksiyonu loop içinde sürekli poll ederseniz sağa çevrildiğinde sola çevrildiğinde arrtir azalt değişkenleri 1 ya da sıfır olur.

tahtaco


Uykusuz

#3
Merhaba

Ancak şimdi fırsatım oldu yazmaya, ben de kesme yönteminde yapmanız gerekenleri anlatmaya çalışayım. Kodlarınızı anlamaya çalışmayacağım zira bu kadar zamanım maalesef yok  :)

İlk etapta Rotary encoder'i bağlayacağınız A ve B pinlerini giriş olarak tanımlamalı ve pull-up aktif edilmeli. Bu portlar atmega328 için  PORTD2 ve PORTD3

DDRD |= 0b00001100
PORTD |= 0b00001100


PD2 ve 3 giriş olarak tanımlandı ve pullup aktif edildi.

Sonra kesmeleri açmalısınız.

EICRA = 0b00001010;

Düşen kenarda kesme oluşturuldu.

EIFR = 0b0000011;

Kesme bayrakları temizlendi.

EIMSK = = 0b0000011;

Hem Int0 hem INT1 için de kesmeler aktifleştildi. Bundan sonra her bir düşen kenar durumu algılandığında ISR (INT0_vect) veya ISR (INT1_vect) fonksiyonlarınız çalışacaktır. Sadece birini kullanmak istiyorsanız EIMSK kontrol kaydedicisinden istediğinizi kapatabilirsiniz.

Kolay gelsin.

Projelerimiz için tıklayın You do not have permission to view links! Sign up or Log in
Sipariş ve Bilgi için You do not have permission to view links! Sign up or Log in ile irtibata geçiniz.
Lütfen teknik sorularınızı forumda sorunuz özel mesaj göndermeyiniz

tahtaco

Vakit ayırıp verdiğiniz  cevap için teşekkür ederim  :)

tahtaco

__root  hocam  merhaba
pin_get_status(p0);
pin_get_status(p1);
azaltildi = 1;
arttirildi = 1;
nasıl tanımlıyoruz  :)
            
               
         

__root

p0 ve p1 encoderi bağladığınız iki pin. Hangi pinlere bağladıysanız o pini okuyorsunuz. Encoderin portd ye bağlı olduğunu düşünürsek;


b0 =  ((PIND)>>p0)&1)
b1 =  ((PIND)>>p1)&1)

attirildi ya da azaltildi adlı global değişkenleriniz çevrilen yöne göre 1 ya da sıfır oluyor. Program içerisinde de bu değişkenlere bakarak istediğiniz değişkenin değerini arttrıp azaltabilirsiniz. İşiniz bittikten sonra bu iki değişkeni sıfırlamayı unutmayın.

tahtaco

Bu şekilde güzel çalışıyor simulasyonda denedim.Yardımlarınız için Uykusuz, __root   hocam çok tşkler tekrar.


volatile int v =240 , v1 = 60 ,v2 =90;

void initInterrupts(void);

ISR(INT1_vect){

if (PIND & (1<<PIND3)){

v++;
v1++;
v2++;
}

else{

v--;
v1--;
v2--;
}

}

void initInterrupts(void){

EICRA = 0b00001000;// ISC11 enable
EIFR = 0b0000010;// INTF1 enable
EIMSK =  0b0000010;//INT1 enable

sei();
}

tahtaco

edit : if (PINB & (1<<PINB0)) olacak :)

tahtaco

#9
Merhaba resimde ki zamanlamaları yapmaya çalışıyorum ,bazen tam istediğim gibi  gayet güzel  bazende üsteki sinyale göre  farklı noktalarda on off oluyor neden acaba  saygılar :) #include <avr/io.h>
#include <avr/interrupt.h>


static  uint8_t state = 0;
static uint16_t OCR_advance[] = {240,240,60,60,60,60,60,60,60,540};
#define STATE_COUNT (sizeof(OCR_advance)/sizeof(uint16_t ))

static uint8_t state_1 = 0;
static uint16_t OCR_advance_1[] = {16,104,16,104,16,104,16,1068};
#define STATE_COUNT_1 (sizeof(OCR_advance_1)/sizeof(uint16_t ))

ISR(TIMER1_COMPA_vect)
{
  OCR1A += OCR_advance[state];
  if (++state >= STATE_COUNT)
  state = 0;
}

ISR(TIMER1_COMPB_vect)
{
OCR1B += OCR_advance_1[state_1];
if (++state_1 >= STATE_COUNT_1)
state_1 = 0;
}

int main(void)
{
// OC1A output
DDRB = (1<<1)|(1<<2);
// Toggle OC1A on compare match
TCCR1A = (1<<COM1A0)|(1<<COM1B0);
OCR1A = 540;
OCR1B =1068;
TIMSK1 = (1<<OCIE1A)|(1<<OCIE1B);
// Presc. 1:8 for 1MHz timer tick
TCCR1B = 1<<CS11;
sei();

    while (1)
    {
    }
}

__root

Merhaba
Portları nerede değiştirdiğinizi göremedim o kısmı da ekleyebilir misiniz?

tahtaco

  OC1A,OC1B çıkış
DDRB = (1<<1)|(1<<2);

__root


burada sadece giriş-çıkış ayarları yapılıyor. interrupt rutinlerinde portlarda bir değişim yazmamışsınız.

tahtaco

static uint16_t OCR_advance[] = {240,240,60,60,60,60,60,60,60,540};
dizide ki değerleri  sırasıyla OCR1A  yüklüyor.state 0 ise 240 us 1, state1 240  0 şeklinde devam ediyor.OCR1A,B pwm çıkış pinleri kullanılıyor.

__root

Karşılaştırma sonucu bu pinler sıfır ya da 1 oluyor fakat donanımsal olarak sadece karşılaşma anında bu pinler değiştirilir. Yani timer<ocr ise pin0 kal değilse 1 kal gibi çalışmıyor. Bu yaklaşımınız bu sebeple doğru değil. Her interrupt'a girildiğinde kendiniz bu pini o state durumunda ne olması gerekiyorsa o seviyeye çekmelisiniz. pinler normal io olarak ayarlanmalı, timer ya da pwm modülüne kesinlikle bağlı kalmamalıdır.