Tuşlu Rotary Encoder Modül Yapımı

Yukarıdaki soruyu sordum ve nasıl olabilir diye düşünürken rotary encoder pinlerinin farklı bağlanmasıyla mümkün olabilir mi dedim...
Biz normalde encoder pinlerinden A ve B pinini pullup yahut pulldown olarak MCU interrupt pinine; bu ikisinin common pinini ise diğerleri pullup iken GND'ye, pulldown iken +5 volta bağlıyoruz.

Eğer A ve B pini giriş ve common pini çıkış olursa, bir tık hareketinin tamamlandığı dört adımda bize sırasıyla şu çıktıları verecektir:
0 ânında: 0
1 ânında: Yalnız A
2 ânında: A+B
3 ânında: Yalnız B
Sonrasında tekrar 0 anına dönecek.

Logic yapılar konusunda hemen hiç bilgim olmamasına rağmen böyle bir bağlantı biçiminin encoder üzerinden hareket okumakta bir artı sağlama imkânını sizlere yeni bir soru olarak sormak istiyorum. Ne dersiniz kullanışlı olabilir mi?

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
 
Şu anda display tarafı ile uğraşıyorum, daha enkodere bakmadım ayrıntılı olarak. Normalde bu iş quadrature decoder denen bir lojik devre ile yapılıyor (bu işi yapan entegreler de var), ama benim yazılımla yapmam gerekecek.
 
Benim şu anda üzerinde çalıştığım projede de encoder okumam gerekiyor. Dönüş sinyalini kesme, A ve B sinyallerini de normal GPIO yapmayı düşünüyorum. İşlemci Renesas RA6M2.
Abi bizim demek istediğimiz ı2c'den gelen bir veriyle kesme oluşturmak
 
i2c için şöyle bir kesme kullanılmış.
Bu kesme bizim picoda kullandığımız kodlamanın aynısı gibi görünüyor. Eve geçince bakacağım bu yapıya.

 
Abi bu uygulamada 3ünü bir arada kullanmış I2C'den kesme yapmıyor kullandığı lcd'ye I2C modül bağladığı için başlığa I2C yazmış
 
Abi bu uygulamada 3ünü bir arada kullanmış I2C'den kesme yapmıyor kullandığı lcd'ye I2C modül bağladığı için başlığa I2C yazmış
Doğru diyorsun. Zaten ekrana niye kesme yapsın ki :D
Ben yarı uyur vaziyette izlediğim için anlamamışım olayı.
 
Keypad için bir çözüme ulaştım gibi.
Eve geçince deneyeceğim.

Screenshot_20220409-105733.jpg


20220409_110006.jpg
 
Bütün interrupt sorunlarını çözdüm.
PCF8574'ün int pini gerçekten kesme için kullanılıyor. Yalnız pullup yapmak şart.
İnterrupt içine yazdığımız fonksiyonların dışarıdan değer almaması şart. Bunun için fonksiyonları tekrar düzenledim.
Çağırıldıkları yerde, kendi içlerinde işlem yapıp sonucu dışarı aktaracaklar. Zaten olması gereken de buydu.
Büyük bir sorunu çözdüm. Bir sıkıntı daha çıkmazsa kısa zamanda kodlamayı bitirip baskı devreyi picoya göre çizmeye başlayacağım.
Tabi birde test edilmesi gereken dijital potlar var sırada. Ne çok iş var yav...

Kodlar bu şekilde. keyPress() fonksiyonu çok uzundu eklemedim buraya.
Aşağıdaki kodlar mantığı anlama konusunda yetecektir. @hafy


C++:
#define interrup 9 //PCF8574'ün pini
#define PinClk 8 // Encoder pini
#define PinDt 7  // Encoder pini
#define PinSw 6 // Encoder Butonu

int sayac = 0;
long oncekiZaman;
boolean oncekiDurum;
boolean buttonSonDurum = HIGH;
boolean yazildimi = false;

void setup(void) {
  Serial.begin(115200);

  pinMode(PinClk, INPUT);
  pinMode(PinDt, INPUT);
  pinMode(PinSw, INPUT);
  pinMode(interrup, INPUT_PULLUP); // PCF8574'ün ataması mutlaka PULLUP' ile yapılacak

// Kesmelerin ikinci sırasına yazılan "encoder","debounce","keyPress" fonksiyonları dışarıdan değer almayacak.
  attachInterrupt(PinClk , encoder , CHANGE );//BAĞLI PINDE DEĞİŞİKLİK OLURSA KES
  attachInterrupt(PinSw , debounce , CHANGE );//BAĞLI PINDE DEĞİŞİKLİK OLURSA KES
  attachInterrupt(interrup , keyPress , LOW );//BAĞLI PIN LOW OLURSA KES

  digitalWrite(PinClk, HIGH);
  digitalWrite(PinDt, HIGH);
 
}

void debounce() {
  boolean butonDurum = digitalRead(PinSw);
  if (butonDurum != buttonSonDurum) {
    butonDurum = digitalRead(PinSw);
    buttonSonDurum = butonDurum;
  }
  if (butonDurum == LOW && yazildimi == false) {
    Serial.println("Butona basildi ! ");
    page = 'i';
    yazildimi = true;

  } else if (butonDurum == HIGH) {
    yazildimi = false;
  }
}
void encoder() {
  boolean PinDT = digitalRead(PinDt);
  boolean PinCLK = digitalRead(PinClk);
  if (millis() - oncekiZaman > 1) {
    if (PinCLK != oncekiDurum) {
      if (PinCLK == LOW) {
        if (PinDT == HIGH) {
          sayac++;
          Serial.print(sayac);
          Serial.println(" : sag");
        } else {
          sayac--;
          Serial.print(sayac);
          Serial.println(" : sol");
        }
      }
    }
    oncekiDurum = PinCLK;
    oncekiZaman = millis();
  }
}

void loop(void) {
  debounce();
  encoder();
  keyPress();
}
 
Bütün interrupt sorunlarını çözdüm.
PCF8574'ün int pini gerçekten kesme için kullanılıyor. Yalnız pullup yapmak şart.
İnterrupt içine yazdığımız fonksiyonların dışarıdan değer almaması şart. Bunun için fonksiyonları tekrar düzenledim.
Çağırıldıkları yerde, kendi içlerinde işlem yapıp sonucu dışarı aktaracaklar. Zaten olması gereken de buydu.
Büyük bir sorunu çözdüm. Bir sıkıntı daha çıkmazsa kısa zamanda kodlamayı bitirip baskı devreyi picoya göre çizmeye başlayacağım.
Tabi birde test edilmesi gereken dijital potlar var sırada. Ne çok iş var yav...

Kodlar bu şekilde. keyPress() fonksiyonu çok uzundu eklemedim buraya.
Aşağıdaki kodlar mantığı anlama konusunda yetecektir. @hafy


C++:
#define interrup 9 //PCF8574'ün pini
#define PinClk 8 // Encoder pini
#define PinDt 7 // Encoder pini
#define PinSw 6 // Encoder Butonu

int sayac = 0;
long oncekiZaman;
boolean oncekiDurum;
boolean buttonSonDurum = HIGH;
boolean yazildimi = false;

void setup(void) {
Serial.begin(115200);

pinMode(PinClk, INPUT);
pinMode(PinDt, INPUT);
pinMode(PinSw, INPUT);
pinMode(interrup, INPUT_PULLUP); // PCF8574'ün ataması mutlaka PULLUP' ile yapılacak

// Kesmelerin ikinci sırasına yazılan "encoder","debounce","keyPress" fonksiyonları dışarıdan değer almayacak.
attachInterrupt(PinClk , encoder , CHANGE );//BAĞLI PINDE DEĞİŞİKLİK OLURSA KES
attachInterrupt(PinSw , debounce , CHANGE );//BAĞLI PINDE DEĞİŞİKLİK OLURSA KES
attachInterrupt(interrup , keyPress , LOW );//BAĞLI PIN LOW OLURSA KES

digitalWrite(PinClk, HIGH);
digitalWrite(PinDt, HIGH);

}

void debounce() {
boolean butonDurum = digitalRead(PinSw);
if (butonDurum != buttonSonDurum) {
butonDurum = digitalRead(PinSw);
buttonSonDurum = butonDurum;
}
if (butonDurum == LOW && yazildimi == false) {
Serial.println("Butona basildi ! ");
page = 'i';
yazildimi = true;

} else if (butonDurum == HIGH) {
yazildimi = false;
}
}
void encoder() {
boolean PinDT = digitalRead(PinDt);
boolean PinCLK = digitalRead(PinClk);
if (millis() - oncekiZaman > 1) {
if (PinCLK != oncekiDurum) {
if (PinCLK == LOW) {
if (PinDT == HIGH) {
sayac++;
Serial.print(sayac);
Serial.println(" : sag");
} else {
sayac--;
Serial.print(sayac);
Serial.println(" : sol");
}
}
}
oncekiDurum = PinCLK;
oncekiZaman = millis();
}
}

void loop(void) {
debounce();
encoder();
keyPress();
}
İnterrupt ile bağlanan encoder, debounce ve keypress fonksiyonunu loop içinde ayrıca çağırmanıza gerek yok. Onlar kesme ile çağrılacak...

Ayrıca encoder fonksiyonunun yapısı daha sade olabilirdi. Şöyleki:
1- (Pinclk, encoder, CHANGE) kesmesini CHANGE seçerek Pinclk pininin Yükselen ve Düşen anında gerçekleşmek üzere ayarlamışsınız. Dolayısıyla encoderin bir tık dönüşünde iki durumu if-else ile kontrol etmek durumundasınız... Bu nedenle void encoder içinde:
if (PinCLK != oncekiDurum)
if (PinCLK == LOW)
if (PinDT == HIGH)
şeklinde üç adet if-else kullanıyorsunuz. Eğer tetiklemeyi RISING yahut FALLING olarak ayarlasaydınız:
if (PinCLK != oncekiDurum)
if (PinCLK == LOW)
kontrol bloklarını doğrudan eleyecektiniz. Ve
if (PinDT == HIGH) bloğu tek başına sizin işinizi görecekti...

2- Debounce için if (millis()-oncekiZaman >1) kontrolünü kullanıyorsunuz. Eğer kesme tetiklendiğinde void encoder dallanınca tüm interrupt ları devredışı bırakırsanız buna da gerek kalmazdı. Çünkü siz kesme ile tetiklenen fonksiyonda gerekli işlemleri yaparken başka bir kesme meydana gelmeyeceği için sayac değişkeninin tüm değerlerini atlamadan görebilirsiniz. Bunun için encoder fonksiyonundan çıkmadan önce kısa bir delay ekleyip tüm kesmeleri aktive ederek fonksiyonu bitirirdiniz.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
 
Bu arada bunlar picoda çalışacak kodlar sanırım. Eğer öyleyse interrupt için Arduino'dakinden farklı bir ayar bulunmuyor....

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
 
Bu arada bunlar picoda çalışacak kodlar sanırım. Eğer öyleyse interrupt için Arduino'dakinden farklı bir ayar bulunmuyor....

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Bulunmuyor abi earlephilhower çok güzel yazmış
 
İnterrupt ile bağlanan encoder, debounce ve keypress fonksiyonunu loop içinde ayrıca çağırmanıza gerek yok. Onlar kesme ile çağrılacak...

Ayrıca encoder fonksiyonunun yapısı daha sade olabilirdi. Şöyleki:
1- (Pinclk, encoder, CHANGE) kesmesini CHANGE seçerek Pinclk pininin Yükselen ve Düşen anında gerçekleşmek üzere ayarlamışsınız. Dolayısıyla encoderin bir tık dönüşünde iki durumu if-else ile kontrol etmek durumundasınız... Bu nedenle void encoder içinde:
if (PinCLK != oncekiDurum)
if (PinCLK == LOW)
if (PinDT == HIGH)
şeklinde üç adet if-else kullanıyorsunuz. Eğer tetiklemeyi RISING yahut FALLING olarak ayarlasaydınız:
if (PinCLK != oncekiDurum)
if (PinCLK == LOW)
kontrol bloklarını doğrudan eleyecektiniz. Ve
if (PinDT == HIGH) bloğu tek başına sizin işinizi görecekti...

2- Debounce için if (millis()-oncekiZaman >1) kontrolünü kullanıyorsunuz. Eğer kesme tetiklendiğinde void encoder dallanınca tüm interrupt ları devredışı bırakırsanız buna da gerek kalmazdı. Çünkü siz kesme ile tetiklenen fonksiyonda gerekli işlemleri yaparken başka bir kesme meydana gelmeyeceği için sayac değişkeninin tüm değerlerini atlamadan görebilirsiniz. Bunun için encoder fonksiyonundan çıkmadan önce kısa bir delay ekleyip tüm kesmeleri aktive ederek fonksiyonu bitirirdiniz.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Bu hususlara yarın değineceğim. Kodlamayı iyi bilmeyince böyle gereksiz işler çıkabiliyor.
 
İnterrupt ile bağlanan encoder, debounce ve keypress fonksiyonunu loop içinde ayrıca çağırmanıza gerek yok. Onlar kesme ile çağrılacak...

Ayrıca encoder fonksiyonunun yapısı daha sade olabilirdi. Şöyleki:
1- (Pinclk, encoder, CHANGE) kesmesini CHANGE seçerek Pinclk pininin Yükselen ve Düşen anında gerçekleşmek üzere ayarlamışsınız. Dolayısıyla encoderin bir tık dönüşünde iki durumu if-else ile kontrol etmek durumundasınız... Bu nedenle void encoder içinde:
if (PinCLK != oncekiDurum)
if (PinCLK == LOW)
if (PinDT == HIGH)
şeklinde üç adet if-else kullanıyorsunuz. Eğer tetiklemeyi RISING yahut FALLING olarak ayarlasaydınız:
if (PinCLK != oncekiDurum)
if (PinCLK == LOW)
kontrol bloklarını doğrudan eleyecektiniz. Ve
if (PinDT == HIGH) bloğu tek başına sizin işinizi görecekti...

2- Debounce için if (millis()-oncekiZaman >1) kontrolünü kullanıyorsunuz. Eğer kesme tetiklendiğinde void encoder dallanınca tüm interrupt ları devredışı bırakırsanız buna da gerek kalmazdı. Çünkü siz kesme ile tetiklenen fonksiyonda gerekli işlemleri yaparken başka bir kesme meydana gelmeyeceği için sayac değişkeninin tüm değerlerini atlamadan görebilirsiniz. Bunun için encoder fonksiyonundan çıkmadan önce kısa bir delay ekleyip tüm kesmeleri aktive ederek fonksiyonu bitirirdiniz.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
1.maddedeki PinClk'ları kaldırıp "interrupt"'u RISING olarak ayarladım. Bu şekilde saat yönünde döndürünce eksiye düşmeye başladı. Sonra FALLING'e çevirince düzeldi.
2.maddeye geçtim ama bir interrupt çalışırken diğerleri nasıl devre dışı bırakılır bilmiyorum. Bağlı oldukları pinleri LOW yada HIGH'a çeksem yeterli olur mu?
 
1.maddedeki PinClk'ları kaldırıp "interrupt"'u RISING olarak ayarladım. Bu şekilde saat yönünde döndürünce eksiye düşmeye başladı. Sonra FALLING'e çevirince düzeldi.
2.maddeye geçtim ama bir interrupt çalışırken diğerleri nasıl devre dışı bırakılır bilmiyorum. Bağlı oldukları pinleri LOW yada HIGH'a çeksem yeterli olur mu?
Bu Arduino'da cli() ve sei() kod satırları ile yapılıyor.
Kesme meydana geldiğinde diyelim encoder fonksiyonuna dallandı.
Void encoder() {
cli()//Tüm interruptları pasif etmek için
//Çalışacak kodlar
sei()//Tüm interruptları aktive etmek için
}

Bu şekilde çalışacaktır, en yukarıda paylaştığım kodları incelerseniz orada da aynen böyle vardı.



Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
 
Bu Arduino'da cli() ve sei() kod satırları ile yapılıyor.
Kesme meydana geldiğinde diyelim encoder fonksiyonuna dallandı.
Void encoder() {
cli()//Tüm interruptları pasif etmek için
//Çalışacak kodlar
sei()//Tüm interruptları aktive etmek için
}

Bu şekilde çalışacaktır, en yukarıda paylaştığım kodları incelerseniz orada da aynen böyle vardı.



Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Evet varmış. Ben fark etmemişim. Bu arada pinleri LOW'a çekmeyi denedim olmuyormuş öyle. Şimdi cli() ve sei()'leri deniyorum.
 
Bu Arduino'da cli() ve sei() kod satırları ile yapılıyor.
Kesme meydana geldiğinde diyelim encoder fonksiyonuna dallandı.
Void encoder() {
cli()//Tüm interruptları pasif etmek için
//Çalışacak kodlar
sei()//Tüm interruptları aktive etmek için
}

Bu şekilde çalışacaktır, en yukarıda paylaştığım kodları incelerseniz orada da aynen böyle vardı.



Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Olmadı...
Pico da olmuyor diyeceğim ama arduino idesinde dahi renkli çıkmadı fonksiyon.
Bunların çalışması için kütüphane filan mı gerek acaba?
cli' was not declared in this scope
 
Olmadı...
Pico da olmuyor diyeceğim ama arduino idesinde dahi renkli çıkmadı fonksiyon.
Bunların çalışması için kütüphane filan mı gerek acaba?
cli' was not declared in this scope
Ben Arduino 1.8 ide de sıkıntı olmadan kullandım, herhangi bir kütüphane de include etmemiştim.
cli() yerine noInterrupt() komutunu deneyebilirsiniz.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
 
Ben Arduino 1.8 ide de sıkıntı olmadan kullandım, herhangi bir kütüphane de include etmemiştim.
cli() yerine noInterrupt() komutunu deneyebilirsiniz.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Evet bende araştırırken noInterrupts() ve interrupts() fonksiyonlarını bulup denedim ama bu seferde hem pico kilitleniyor hemde ide.
ideyi çarpıdan kapatamıyorum bile. Taaki pikonun gücünü kesene kadar.
 

Çevrimiçi üyeler

Forum istatistikleri

Konular
6,142
Mesajlar
104,843
Üyeler
2,553
Son üye
trojann

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top