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

ben millis komutundan şüphelendim ama earlephilhower abi şu şekilde yazmış bunları.
ms.png
 
Enkoder kodlarını fonksiyon içine alıp kursor adımına göre işlem yaptırmak istedim.
Ama hem doğru atlamıyor, hem ilk haneyi 30v'u aşmaması için 3 ile sınırlandırmama rağmen 4-5-6 diye gidiyor, hemde yan rakama atladığımda ilk rakamı sıfırlıyor. Böyle parça parça uğraşınca odaklanamıyorum. Kodda benim görmediğim bir sıkıntı var mı?

C++:
/// Rotary Encoder Fonksiyonu /////////////
void encoder(int ifSay, float carpan, boolean clk, boolean dt){
      if (millis() - oncekiZaman > 1) {
        if (clk != oncekiDurum) {
          if (clk == LOW) {
            if (dt == HIGH) {
              kursorSayac++;
              if (kursorSayac <= ifSay || kursorSayac >= 0) {
                voltaj_akim = kursorSayac * carpan;
                Serial.print(kursorSayac);
                Serial.println(" : sag");
              }
            } else {
              kursorSayac--;
              if (kursorSayac <= ifSay || kursorSayac >= 0) {
                voltaj_akim = kursorSayac * carpan;
                Serial.print(kursorSayac);
                Serial.println(" : sol");
              }
            }
          }
        }
        oncekiDurum = clk;
        oncekiZaman = millis();
      }
}


/// Rotary Enkoder İle İşlem Yapma /////////////
    if (kursor_konum == 0) {
      encoder(3,10.0,b,a);
    } else if (kursor_konum == 1) {
      encoder(9,1.0,b,a);
    } else if (kursor_konum == 2) {
      encoder(9,0.1,b,a);
    } else if (kursor_konum == 3) {
      encoder(9,0.01,b,a);
    }
 
Enkoder kodlarını fonksiyon içine alıp kursor adımına göre işlem yaptırmak istedim.
Ama hem doğru atlamıyor, hem ilk haneyi 30v'u aşmaması için 3 ile sınırlandırmama rağmen 4-5-6 diye gidiyor, hemde yan rakama atladığımda ilk rakamı sıfırlıyor. Böyle parça parça uğraşınca odaklanamıyorum. Kodda benim görmediğim bir sıkıntı var mı?

C++:
/// Rotary Encoder Fonksiyonu /////////////
void encoder(int ifSay, float carpan, boolean clk, boolean dt){
      if (millis() - oncekiZaman > 1) {
        if (clk != oncekiDurum) {
          if (clk == LOW) {
            if (dt == HIGH) {
              kursorSayac++;
              if (kursorSayac <= ifSay || kursorSayac >= 0) {
                voltaj_akim = kursorSayac * carpan;
                Serial.print(kursorSayac);
                Serial.println(" : sag");
              }
            } else {
              kursorSayac--;
              if (kursorSayac <= ifSay || kursorSayac >= 0) {
                voltaj_akim = kursorSayac * carpan;
                Serial.print(kursorSayac);
                Serial.println(" : sol");
              }
            }
          }
        }
        oncekiDurum = clk;
        oncekiZaman = millis();
      }
}


/// Rotary Enkoder İle İşlem Yapma /////////////
    if (kursor_konum == 0) {
      encoder(3,10.0,b,a);
    } else if (kursor_konum == 1) {
      encoder(9,1.0,b,a);
    } else if (kursor_konum == 2) {
      encoder(9,0.1,b,a);
    } else if (kursor_konum == 3) {
      encoder(9,0.01,b,a);
    }
acaba interrput kullanma zamanımız geldi mi.
senin program içindeki delaylar sapıtttırıyor sanırım intterpt kullanırsak enkoderi döndürüğümüzde kesip saydırıp devam eder
 
acaba interrput kullanma zamanımız geldi mi.
senin program içindeki delaylar sapıtttırıyor sanırım intterpt kullanırsak enkoderi döndürüğümüzde kesip saydırıp devam eder
loop içinde sadece 70ms delay var. onarda if koşulu sağlanırsa çalışıyor. Çok etki edeceğini sanmam. interrput kullanmayı bilmiyorum. Önce bi ne olduğunu anlamam lazım.
 
loop içinde sadece 70ms delay var. onarda if koşulu sağlanırsa çalışıyor. Çok etki edeceğini sanmam. interrput kullanmayı bilmiyorum. Önce bi ne olduğunu anlamam lazım.
benimde bir yandan pico ile nası kullandığını öğrenmem lazım.

şöyle özet geçeyim picoyu boşver 328 ile çalışıyoruz 2. çekirdek falan yok

yazdın 20 saniye delay 20 saniye dolana kadar başka bir işlem yapamazssın mecbur o delayı tamamlayacak.
birde butonun var butona ne zaman basacağın belli değil basınca bir led yanıyor ve basar basmaz yansın istiyorsun ama program içinde 20 saniye beklemen var.
butonu bir intterpt pininden okuyup interrpt olarak okuma yaparsan 20 saniye delayın içindeyken interrpt tetiklenirse delayı bırakır gider interrpt'da işlem yapar geri gelir
 
benimde bir yandan pico ile nası kullandığını öğrenmem lazım.

şöyle özet geçeyim picoyu boşver 328 ile çalışıyoruz 2. çekirdek falan yok

yazdın 20 saniye delay 20 saniye dolana kadar başka bir işlem yapamazssın mecbur o delayı tamamlayacak.
birde butonun var butona ne zaman basacağın belli değil basınca bir led yanıyor ve basar basmaz yansın istiyorsun ama program içinde 20 saniye beklemen var.
butonu bir intterpt pininden okuyup interrpt olarak okuma yaparsan 20 saniye delayın içindeyken interrpt tetiklenirse delayı bırakır gider interrpt'da işlem yapar geri gelir
Anladım ama benim programıma göre delayı kesmesi de sıkıntı olabilir. Detaylı bakmak lazım.
 
Burada OR (||) yerine and (&&) olması gerekiyor gibime geldi.
Evet. iki koşulunda sağlanması lazım. (OR)a da yanılmışım :D
birde voltaj_akım değişkenine tüm sayıları fonksiyon içinde tek tek girmem gerekiyor sanki. Aynı tuşlamada yaptığım gibi.
Gerekli düzenlemeleri tekrar yapmaya çalışayım bakalım ne çıkacak.
 
Anladım ama benim programıma göre delayı kesmesi de sıkıntı olabilir. Detaylı bakmak lazım.
Sayın @Gokrtl, rotary encoder uygulamasını bir nevi USB, UART, SPI, I2C haberleşmesi gibi düşünün. Meydana gelmiş bir hareket rotary encoder vasıtasıyla dijital bir dataya dönüştürülüyor. Doğal olarak da bu dijital datanın okunabilirliği CLOCK palsinin varlığına bağlı... CLOCK palsinin başka herhangi bir kesintiye maruz kalmadan takip edilmesi şart; bunun yolu da bir donanım kesmesi yani interrupt kullanmak... Ancak bu sayede CLOCK palsi uygulandığında DATA pininin durumu sağlıklı olarak okunabilir. Çünkü encoder yoluyla DATA pini hızla değişebilir, bu değişim elde etmek istediğiniz sonucu belirsizleştirir.

İnterrupt ile kesilen akışa hızla dönmeyi sağlayacak bir kod yapısı, sizin ana programınızda işleyen delay i soruna uğratmayacaktır.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
 
3 saat Türkçe çalışınca sayısala geçemedim bir türlü. Basmadı kafa.
İş uzuyor ama yine yarına bırakacağım devamını. Yatmam gerek.

C++:
void encoder(int ifSay, float carpan, boolean clk, boolean dt, float basamakBir, float basamakIki, float basamakUc, float basamakDort){
      if (millis() - oncekiZaman > 1) {
        if (clk != oncekiDurum) {
          if (clk == LOW) {
            if (dt == HIGH) {
              kursorSayac++;
              if (kursorSayac <= ifSay && kursorSayac >= 0) {
                voltaj_akim = kursorSayac * carpan;
                voltaj_akim = basamakBir * 10.0 + basamakIki * 1.0 + basamakUc * 0.1 + basamakDort * 0.01;
                Serial.print(kursorSayac);
                Serial.println(" : sag");
              }
            } else {
              kursorSayac--;
              if (kursorSayac <= ifSay && kursorSayac >= 0) {
                voltaj_akim = kursorSayac * carpan;
                voltaj_akim = basamakBir * 10.0 + basamakIki * 1.0 + basamakUc * 0.1 + basamakDort * 0.01;
                Serial.print(kursorSayac);
                Serial.println(" : sol");
              }
            }
          }
        }
        oncekiDurum = clk;
        oncekiZaman = millis();
      }
}


Sayın @Gokrtl, rotary encoder uygulamasını bir nevi USB, UART, SPI, I2C haberleşmesi gibi düşünün. Meydana gelmiş bir hareket rotary encoder vasıtasıyla dijital bir dataya dönüştürülüyor. Doğal olarak da bu dijital datanın okunabilirliği CLOCK palsinin varlığına bağlı... CLOCK palsinin başka herhangi bir kesintiye maruz kalmadan takip edilmesi şart; bunun yolu da bir donanım kesmesi yani interrupt kullanmak... Ancak bu sayede CLOCK palsi uygulandığında DATA pininin durumu sağlıklı olarak okunabilir. Çünkü encoder yoluyla DATA pini hızla değişebilir, bu değişim elde etmek istediğiniz sonucu belirsizleştirir.

İnterrupt ile kesilen akışa hızla dönmeyi sağlayacak bir kod yapısı, sizin ana programınızda işleyen delay i soruna uğratmayacaktır.

Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Tamam ozaman yarın bu interrupt ile ilgili biraz video izleyeyim. Madem şart oldu, öğrenelim.
 
int:
attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T> userFunc, PinStatus mode, T& param)

Böyle bir kullanımı var ama kafamı karıştırdı bu şekil

Ben bunu 328 için yazarken interrupt olarak kullandığım pini kesme olacağında gireceği voidi hangi koşulda keseceğini yazıyordum(0 olunca ,1 olunca, değişince, yükselen kenar,düşen kenar olunca vs.)

328 örn
328:
attachInterrupt(digitalPinToInterrupt(2), gireceği void adı, ne durumda kesecği);
 
int:
attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T> userFunc, PinStatus mode, T& param)

Böyle bir kullanımı var ama kafamı karıştırdı bu şekil

Ben bunu 328 için yazarken interrupt olarak kullandığım pini kesme olacağında gireceği voidi hangi koşulda keseceğini yazıyordum(0 olunca ,1 olunca, değişince, yükselen kenar,düşen kenar olunca vs.)

328 örn
328:
attachInterrupt(digitalPinToInterrupt(2), gireceği void adı, ne durumda kesecği);
Bu gün biraz inceledim. Arduino için gerçekten kolay görünüyor. Aynı senşn yazdığın koddaki gibi.
Pico için çalışan bir örnek bulmak lazım. Biraz fazla karışık gibi kodlaması.
 
dur abi nereye daha interupt kestirecektik
O iş cepte.
Aslında önümüzdeki iki hafta evde çok vakit geçirecek zamanım var ama şu sınava odaklı olduğumdan projeye yüklenemiyorum.
 
Tamam ozaman yarın bu interrupt ile ilgili biraz video izleyeyim. Madem şart oldu, öğrenelim.
Sayın @Gokrtl Interrupt vasıtasıyla bir Rotary Encoder uygulamasına örnek olmak üzere aşağıdaki kodları hazırladım.
Elimdeki Arduino'dabirkaç sene evvel kendi hazırladığım Rotary Encoder Modülü ile denerken bazı sayı kaçırmalar oldu. Sanırım pek korunaklı bir durumda olmadığından kontaklarının maruz kaldığı haller buna sebep oldu. Ancak yeni bir rotary encoder ile deneyince neredeyse hiç bir hata vermeden çalıştı.
Bununla birlikte Pico için herhangi bir katkıda bulunabileceğimi sanmıyorum, bu konuda sizin deneyimlerinizden istifade etmeye çalışacağım.
Umarım incelemelerinizde faydası olur...

Arduino IDE 1.8.13 Üzerinde Arduino UNO İçin Yazıldı:
 int RE_B = 7; //(DATA Pini Olarak:) Arduino UNO'nun 7. Pinini Rotary Encoder'ın B Pinine Atadık
 int RE_A = 2; //(CLK Pini Olarak:) Arduino UNO'nun 2. Pinini (0 Nolu Yani 1. İnterrupt Pinini) Rotary Encoder'ın A Pinine Atadık
 int RE_Bt = 3; // Arduino UNO'nun 3. Pinini (1 Nolu Yani 2. İnterrupt Pinini) Rotary Encoder'ın Button Pinine Atadık
 int PinB; //PinB RE_B Pininin Durumunu Kaydetmek İçin PinB Değişkenini Tanımladık
 int Sayac1 = 0; //Rotary Encder Buttonu'nun Hareketini Saymak İçin Sayac1 Değişkenini Tanımladık
 int Sayac = 0; //Rotary Encder Dönüş Hareketini Saymak İçin Sayac Değişkenini Tanımladık
 int DebounceSuresi = 100;
 String Yon="Bos"; //Rotary Encder Dönüş Yönünü Belirlemek İçin Yon Değişkenini Tanımladık
 boolean Oldu = 0; //Kesme Meydana Gelip Gelmediği Bilgisini Bazı İşlemlerde Kullanmak Üzere Tutmak İçin "Oldu" Değişkenini Tanımnladık

 void setup() {
   cli();//Kurulum Tamamlanana Kadar Tüm Interrupt'ları Durdurduk
   pinMode (RE_A,INPUT_PULLUP); //RE_A Pinini INPUT ve PULLUP Olarak Ayarladık
   pinMode (RE_B,INPUT_PULLUP); //RE_B Pinini INPUT ve PULLUP Olarak Ayarladık
   pinMode (RE_Bt,INPUT_PULLUP); //RE_Bt Pinini INPUT ve PULLUP Olarak Ayarladık
   attachInterrupt(0, Encoding, FALLING);
    //Arduino UNO 2. Pinine Bağlı 0 Nolu Interrupt'a Encoding Fonksiyonunu Atadık. Kesme Tetiklenince Bu Fonksiyona Dallanacak
    //Pin PULLUP Olarak Ayarlandığı İçin FALLING İle Sinyalin GND'ye Çekildiğinde Kesmenin Aktif Olmasını Ayarladık
   attachInterrupt(1, Bt_Pushed, FALLING);
    //Arduino UNO 3. Pinine Bağlı 1 Nolu Interrupt'a Bt_Pushed Fonksiyonunu Atadık. Kesme Tetiklenince Bu Fonksiyona Dallanacak
    //Pin PULLUP Olarak Ayarlandığı İçin FALLING İle Sinyalin GND'ye Çekildiğinde Kesmenin Aktif Olmasını Ayarladık
   Serial.begin (9600);
//Burada Değişkenlerimizin Taşıdıkları Değerleri Herhangi Bir Kesme Meydana Gelinceye Kadar Gözleyebilmemiz İçin Kontrol Amacıyla Ekrana Yazdırıyoruz
   Serial.print(Yon);
   Serial.print("; Sayac: ");
   Serial.println(Sayac);
   Serial.print("Button: ");
   Serial.println(Sayac1);
   sei();//Kurulum Tamamlandığı İçin Tüm Interrupt'ları Aktive Ettik
 }

void Encoding(){//0 Nolu Interrupt Arduino UNO 2. Pinindeki Sinyalin GND'ye Çekilmesiyle Tetiklendi ve Buraya Dallandı
  cli(); //Bu Interrupt İçindeki İşlemleri Tamamlayana Kadar Yeni bir Interrupt Meydana Gelmemesi İçin Tüm Interrupt'ları Durdurduk
  PinB=digitalRead(RE_B); //Kesme Meydana Geldiği Anda DATA Pini Durumunu Bu Komutla PinB Değişkenine Atadık
    //Rotary Encoder Herbir Tık Hareketinde CLK (Yani A Pini) ve DATA (Yani B Pini) Pinlerini Sıralı Olarak Tetikler.
    //Bu Pinler Tıpkı Binary Sayılar Gibi 0 (LOW) ve 1 (HIGH) Durumlar Aldığı İçin 2 Bitlik/Basamaklı BINARY Bir Sayı Gibi Okunabilir
    //Soldan İlk Bit/Basamak CLK Pini ve Diğer Bit/Basamak DATA Pini Değerini Tutar
    //Pinler PULLUP Olduğu İçin Kesme Öncesi İlk Durumlarının Karşılığı 11 Olacaktır. CLK Pini GND'ye Çekildiğinde Interrupt Tetiklenir
    //Encoder'in SAĞ'a (Saat Yönünde) Dönüşünde:
    /*------------------------------
    0- CLK: 1, DATA: 1 => BINARY: 11 Burası Kesme Meydana Gelmeden Hemen Önceki Durum
    1- CLK: 0, DATA: 1 => BINARY: 01 Burası Kesme Meydana Geldiği Andaki Durum
    2- CLK: 0, DATA: 0 => BINARY: 00
    3- CLK: 1, DATA: 0 => BINARY: 10
    4- CLK: 1, DATA: 1 => BINARY: 11
    --------------------------------*/
    //Şeklindeki Akışla Bir Tık Tamamlanır

    //Encoder'in SOL'a (Saatin Tersi Yönde) Dönüşünde:
    /*------------------------------
    0- CLK: 1, DATA: 1 => BINARY: 11
    1- CLK: 1, DATA: 0 => BINARY: 10 Burası Kesme Meydana Gelmeden Hemen Önceki Durum
    2- CLK: 0, DATA: 0 => BINARY: 00 Burası Kesme Meydana Geldiği Andaki Durum
    3- CLK: 0, DATA: 1 => BINARY: 01
    4- CLK: 1, DATA: 1 => BINARY: 11
    --------------------------------*/
    //Şeklindeki Akışla Bir Tık Tamamlanır
    //Bu Tetikleme Esnasında Pinlerin Birbirbiri İle Olan Durumlarına Göre Dönüş Yönünü Belirlenir.

    //Interrupt, CLK Pininin LOW'a Çekilmesiyle Tetikleneceğinden Yukarıdaki BINARY Verilerden CLK Pininin 0'a Döndüğü Anlar Kesmenin Meydana Geldiği Anlar Olacaktır.
    //***** EĞER Interrupt FALLING Yerine RISING Olarak Yani CLK Pininin LOW'dan HIGH'a (0'dan 1'e) Döndüğünde Tetiklenecek Olsaydı Bu Akışlar Tersine Dönecekti.*****
    //Buna Göre:
    //SAĞ Yönde CLK Pininin 1'den 0'a Dönmesiyle Kesmenin Tetiklendiği 1. Durumda DATA Pininin 1
    //SOL Yönde CLK Pininin 1'den 0'a Dönmesiyle Kesmenin Tetiklendiği 2. Durumda DATA Pininin 0 Değerinde Olduğu Görülecektir.
    //CLK Pininin 1'den 0'a Dönüşü Kesmeyi Tetiklerken DATA Pininin 1 veya 0 Oluşu Dönüş Yönünü Göstermektedir
    //Biz de Aşağıdaki IF-ELSE Yapısı İle DATA Pininin İki Durumunu Karşılaştırarak Dönüş Yönünü Tespit Edecğiz
  if (PinB) {
    Yon="Sag"; //PinB Kesme Anında 1 Durumunda İSE Dönüşün SAĞ Yönde Olduğunu Tespit Ediyoruz
    Sayac++; //PinB Kesme Anında 1 Durumunda İSE Sayac Değişkenini Artırıyoruz
  } else {
    Yon="Sol"; //PinB Kesme Anında 1 Durumunda DEĞİL İSE Dönüşün SOL Yönde Olduğunu Tespit Ediyoruz
    Sayac--; //PinB Kesme Anında 1 Durumunda DEĞİL İSE Sayac Değişkenini Azaltıyoruz
  }
  delay(DebounceSuresi); //Kesmeye Kontrolümüz Dışında Fazla Kesme Meydana Gelmemesi İçin Bir Nevi Yazılımsal Bir DEBOUNCE Uyguluyoruz
  Oldu = 1; //Kesme Olduğu Bilgisini Değişkene Atadık
  sei(); //İşlemler Tamamlandığı İçin Yeni Interrupt Beklemek Üzere Tüm Interrupt'ları Aktive Ettik
}

void Bt_Pushed(){//1 Nolu Interrupt Arduino UNO 3. Pinindeki Sinyalin GND'ye Çekilmesiyle Tetiklendi
  cli(); //Bu Interrupt İçindeki İşlemleri Tamamlayana Kadar Yeni bir Interrupt Meydana Gelmemesi İçin Tüm Interrupt'ları Durdurduk
  Sayac1+=1; //Rotary Encoder Button'u Kullanılarak İle Sayac1 Değişkenini Artırıyoruz
  delay(DebounceSuresi); //Kesmeye Kontrolümüz Dışında Fazla Kesme Meydana Gelmemesi İçin Bir Nevi Yazılımsal Bir DEBOUNCE Uyguluyoruz
  Oldu = 1; //Kesme Olduğu Bilgisini Değişkene Atadık
  sei(); //İşlemleri Tamamlandığı İçin Yeni Interrupt Beklemek Üzere Tüm Interrupt'ları Aktive Ettik
}

void loop() {
  if (Oldu) {//Kesme Oldu İse Verilerimizde Değişiklik Meydana Geleceğinden Verileri Bu Durumda Yazdırıyoruz
              // Böylece Serial Ekrandan Sürekli Bir Akış Nedeniyle Anormallikleri Kaçırmış Olmayacağız
    Serial.print(Yon);
    Serial.print("; Sayac: ");
    Serial.println(Sayac);
    Serial.print("Button: ");
    Serial.println(Sayac1);
    Oldu = 0; //En Son Kesme Nedeniyele Verilerimizde Meydan Gelen Değişikliği Ekrana Yazdık Yeni Bir Değişikliğe Kadar Ekrana
              //Veri Yazmamak İçin Kontrol Değişkenini Değiştiriyoruz
  }
}
 

Forum istatistikleri

Konular
6,168
Mesajlar
105,287
Üyeler
2,564
Son üye
Levcho

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