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

Şu sayfa sana yardımcı olabilir. Tüm kütüphanelerin linki var.

bu hazır enkoder modülleri ile ütopik birşey denemiştik.
Sana demiştim ya çizgi izleyen robot.
Sarı 6 volt plastik rediktörlü motorların mili 2 tarafına da çıkıyor bi tarafa tekerlek diğer tarafına japonla 1.5mm tek tel kablo ile bu enkodere bağladık pistte 2. turunu attığında bizim enkoder kabak çekirdeği gibi açılmıştı
 
Şu sayfa sana yardımcı olabilir. Tüm kütüphanelerin linki var.

benim kütüphane linkini aramama gerek yok ki abi kütüphane adını görsem yetiyor adını yazıp sonuna github yazıp buluyorum kütüphane dosyalarını
 
Konunun hepsini takip edemedim. Daha önce arduino ile incremental rotary encoder saydım ve hiç sorun çıkmadı.

Neyse aklımdakini söyleyyim. Kesme içerisinde bir kod yazıp düzgün sayamıyorsan dobunce olduğunu düşünürüm. Benim saydığım optik olduğu için böyle bir sıkıntım yoktu. Uygun kapasite ile tatminkar sonuç alman gerek diye düşünüyorum...
 
Konunun hepsini takip edemedim. Daha önce arduino ile incremental rotary encoder saydım ve hiç sorun çıkmadı.

Neyse aklımdakini söyleyyim. Kesme içerisinde bir kod yazıp düzgün sayamıyorsan dobunce olduğunu düşünürüm. Benim saydığım optik olduğu için böyle bir sıkıntım yoktu. Uygun kapasite ile tatminkar sonuç alman gerek diye düşünüyorum...
Çırpındıkça batar durumdayım şuan. O kadar çok kurcaladım ki kodları. Artık sağlıklı düşünemiyorum bile.
Yarın hazır bir encoder alıp onunla deneyeceğim. Birde geçen bulmuştum, şimdi bulamadım, opamplı encoderler var. Kendi üzerinde debounce yapıyor. Onlardan almayı düşünüyorum.
 
Kod:
/*Optik encoderle çalışması için yazıldı
 *encoder çıkışları schmit triggerli ve bounce sorunu yok kodda da debounce yok
 *Bounce durumunda birkaç kere çalışsa da nihai durumda doğru değeri alması lazım
 *Hız yükseldiğinde adım kaçırmasına karşı düzeltme var
 *
 */
 
#define ENCDEBUG

#define YON_AC  1   // 1 veya -1 enkoderin artış yönü tayini için
#define encA  2
#define encB  3


int konum,artis,k,enc,enc1;

int encoder(void);

void setup() {
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(encA), encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encB), encoder, CHANGE);
 
  pinMode(encA,INPUT_PULLUP);
  pinMode(encB,INPUT_PULLUP);
  // encoder başlangıç durumu
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  enc1=enc;
  Serial.println("start");
  sei();
}

void loop() {
 
 
 
}

int encoder(void)
{
  // encoder durumunu binary olarak enc değişkenine atama
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  if (enc1 != enc) // encoder değişmişse işlem yap
  {
 
    switch (enc1)// son okunan encoder değerine göre işlem yap
    {
    case 0b00:
      switch (enc)
      {
      case 0b01:
        artis = k * YON_AC; // yon aç önceden tanımlanmış artış yönü "1" veya "-1"
        k = 1; // olağan çalışma durumu katsayıyı düzelt
        break;
      case 0b10:
        artis = k * -YON_AC;
        k = 1;
        break;
      default: // adım kaçırıldığında çalışır
        enc1 = enc;
        k = 2; // adım kaçırıldıysa sonraki encoder okumasının katsayısını 2 yapar
        break;
      }
      break;
    case 0b01:
      switch (enc)
      {
      case 0b11:
        artis = k * YON_AC;
        k = 1;
        break;
      case 0b00:
        artis = k * -YON_AC;
        k = 1;
        break;
      default: // adım kaçırıldığında çalışır
        enc1 = enc;
        k = 2;
        break;
      }
      break;
    case 0b11:
      switch (enc)
      {
      case 0b10:
        artis = k * YON_AC;
        k = 1;
        break;
      case 0b01:
        artis = k * -YON_AC;
        k = 1;
        break;
      default: // adım kaçırıldığında çalışır
        enc1 = enc;
        k = 2;
        break;
      }
      break;
    case 0b10:
      switch (enc)
      {
      case 0b00:
        artis = k * YON_AC;
        k = 1;
        break;
      case 0b11:
        artis = k * -YON_AC;
        k = 1;
        break;
      default: // adım kaçırıldığında çalışır
        enc1 = enc;
        k = 2;
        break;
      }
      break;
    default:
      enc1 = enc;
      break;
    }
    #ifdef ENCDEBUG
    if(k==2) // eğer adım kaçırdıysa
    {
      Serial.println("H");
    }
    
    Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
 
    #endif
    enc1 = enc;
    konum += artis;
    
  }
  //return enc;
  //return artis;
  return konum;
}

Bahsini ettiğim kodu paylaşayım. Bunda debounce için delay yok, yalnız çözünürlük 4 katı. elimdeki tuşlu encoderle denediğimde tutarsız değerler almadım.
Bendeki enkoderin duraklardan birinde farklı değer aldığını farkettim.

Bu kodu tuşlu enkoderde çalışacak şekilde düzenledim ve debounce için bir ekstra kod yazmadan çalışırdurumda

Kod:
#define ENCDEBUG

#define YON_AC  1   // 1 veya -1 enkoderin artış yönü tayini için
#define encA  2
#define encB  3


int konum,artis,k,enc,enc1;

int encoder(void);

void setup() {
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(encA), encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encB), encoder, CHANGE);
 
  pinMode(encA,INPUT_PULLUP);
  pinMode(encB,INPUT_PULLUP);
  // encoder başlangıç durumu
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  enc1=enc;
  Serial.println("start");
  sei();
}

void loop() {
 
 
 
}

int encoder(void)
{
  // encoder durumunu binary olarak enc değişkenine atama
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  if (enc1 != enc) // encoder değişmişse işlem yap
  {
 
    switch (enc1)// son okunan encoder değerine göre işlem yap
    {
    case 0b01:
      switch (enc)
      {
      case 0b11:
        konum-=YON_AC ;
        #ifdef ENCDEBUG
        if(k==2) // eğer adım kaçırdıysa
        {
          Serial.println("H");
        }
        
        Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
    
        #endif
        break;
      
      default:
        break;
      }
      break;
    case 0b10:
      switch (enc)
      {
      case 0b11:
        konum+=YON_AC ;
        #ifdef ENCDEBUG
        if(k==2) // eğer adım kaçırdıysa
        {
          Serial.println("H");
        }
        
        Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
    
        #endif
        break;
      default:
        break;
      }
      break;
    default:
      enc1 = enc;
      break;
    }
    
    enc1 = enc;
    
    
  }
  //return enc;
  //return artis;
  return konum;
}

Arduino unoyla denedim interruptlar 2 ve 3 nolu pinlerle çalışıyor pico için pin farketmiyor sanırım
 
Bendeki enkoder bounce yapmıyor herhalde, kodu incelediğimde masamdaki uygulamada adımları nizami saysa da sekme yapması gerekiyor.
Bende adım sonrası hafifçe, yarım adımdan da az geri çevirip tekrar encoderin durak noktasına bıraktım. Bu durumda bounce durumunda olması gerektiği gibi ekstra adım saydı.

Kodu tekrar düzenleyip ara geçiş noktasında bir bayrak değişkeni 1 yaparak adım saymak için bayrak değişkenin 1 olması şartını ekledim.

encoder 0b11 ( A=1 B=1) değerinde durakta kalıyor ve bazen 0b01 veya 0b10 oluyor. Atılan adımın tam ortasında 0b00 ( A=0 B=0) oluyor.

Düzeltilmiş kodu tekrar denediğimde kod tekrar çalışsa da artış sinyali kaydetmiyor

Kod:
#define ENCDEBUG

#define YON_AC  1   // 1 veya -1 enkoderin artış yönü tayini için
#define encA  2
#define encB  3


int konum,artis,k,enc,enc1,adimBayrak;

int encoder(void);

void setup() {
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(encA), encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encB), encoder, CHANGE);
 
  pinMode(encA,INPUT_PULLUP);
  pinMode(encB,INPUT_PULLUP);
  // encoder başlangıç durumu
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  enc1=enc;
  Serial.println("start");
  sei();
}

void loop() {
 
 
 
}

int encoder(void)
{
  // encoder durumunu binary olarak enc değişkenine atama
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  if (enc1 != enc) // encoder değişmişse işlem yap
  {
 
    switch (enc1)// son okunan encoder değerine göre işlem yap
    {
    case 0b00:adimBayrak=1; break;// debounce için bayrak değişken
    case 0b01:
      switch (enc)
      {
      
      case 0b11:
        if(adimBayrak)
        {
          konum-=YON_AC ;
          adimBayrak=0;
        }
      
        #ifdef ENCDEBUG
        Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
        #endif
      
        break;
    
      default:
        break;
      }
      break;
    case 0b10:
      switch (enc)
      {
      case 0b11:
        if(adimBayrak)
        {
          konum+=YON_AC ;
          adimBayrak=0;
        }
      
        #ifdef ENCDEBUG
        Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
        #endif
      
        break;
      default:
        break;
      }
      break;
    default:
      enc1 = enc;
      break;
    }
  
    enc1 = enc;
    Serial.print("enc: ");Serial.println(enc,BIN);
  
  }
  //return enc;
  //return artis;
  return konum;
}

Şu halde debounce kondansatörü kullanmadan uygun çalışıyor ama yine de gereksiz yere interrupt kodunu çağırıp işlemciyi meşgul etmemek için makul bir kondansatör koymak uygun olabilir.

1649718190498.png


düzeltme : " case 0b00:adimBayrak=1; break; " break eklememişim.
 
Son düzenleme:
Kod:
#define ENCDEBUG

#define YON_AC  1   // 1 veya -1 enkoderin artış yönü tayini için
#define encA  2
#define encB  3


int konum,artis,k,enc,enc1,adimBayrak;

int encoder(void);

void setup() {
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(encA), encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encB), encoder, CHANGE);
 
  pinMode(encA,INPUT_PULLUP);
  pinMode(encB,INPUT_PULLUP);
  // encoder başlangıç durumu
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  enc1=enc;
  Serial.println("start");
  sei();
}

void loop() {
 
 
 
}

int encoder(void)
{
  // encoder durumunu binary olarak enc değişkenine atama
  enc = digitalRead(encB) + (digitalRead(encA) << 1);
  if (enc1 != enc) // encoder değişmişse işlem yap
  {
 
    switch (enc1)// son okunan encoder değerine göre işlem yap
    {
    case 0b00:adimBayrak=1; // debounce için bayrak değişken
    case 0b01:
      switch (enc)
      {
       
      case 0b11:
        if(adimBayrak)
        {
          konum-=YON_AC ;
          adimBayrak=0;
          #ifdef ENCDEBUG
          Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
          #endif
        }
       
       
       
        break;
     
      default:
        break;
      }
      break;
    case 0b10:
      switch (enc)
      {
      case 0b11:
        if(adimBayrak)
        {
          konum+=YON_AC ;
          adimBayrak=0;
          #ifdef ENCDEBUG
          Serial.println(konum);// metin yazdırmıyorum gecikmeye sebep olmamak için
          #endif
        }
       
       
       
        break;
      default:
        break;
      }
      break;
    default:
      enc1 = enc;
      break;
    }
   
    enc1 = enc;
    Serial.print("enc: ");Serial.println(enc,BIN);
   
  }
  //return enc;
  //return artis;
  return konum;
}

Serial.println kodunu adım artış döngüsünün içine aldığımda aşağıdaki gibi elle simüle ettiğim bounce durumunda adım artışının kaydedilmediği daha kolay görülüyor.

Bu kodlara tekrar bakınca kayar kapıda tutarsız çalışmasına sebep olan bir hatamı da farketmiş oldum. adım kaçırmayı düzeltmesini umduğum kısım bozukmuş.

1649718782689.png


düzeltme : " case 0b00:adimBayrak=1; break; " break eklememişim.
 
Son düzenleme:
WhatsApp Image 2022-04-12 at 08.17.13.jpeg

Enkoderi oto-teyp'den söküp delikli plakete adaptör yaptım.
Çok çok yavaş şekilde 1 tık dönecek kadar çevirip ledlerle test yaptım puls kaçırma göremedim sağlam sanırım bir test programı bulalım.
 
16597 eklentisine bak
Enkoderi oto-teyp'den söküp delikli plakete adaptör yaptım.
Çok çok yavaş şekilde 1 tık dönecek kadar çevirip ledlerle test yaptım puls kaçırma göremedim sağlam sanırım bir test programı bulalım.
Serial monitörden de bak ve hızlı çevirmede yap.
Bir bende sıkıntı demekki. Bu gün gidip hazır modül alıcam.
 
Serial monitörden de bak ve hızlı çevirmede yap.
Bir bende sıkıntı demekki. Bu gün gidip hazır modül alıcam.
EN.png

Şuanlık kararlı çalışıyor programı biraz dolduralım bakalım neler olucak interup falan yok direkt digital read ile okuma last minute enginner sitesinin enkoder test programı
 
programa gp25'e bağlı lede pwm ekledim sapıtmaya başladık
ennn.png

sürekli aynı yöne çevirdiğimde aldığım çıktı bir yandan da pwm yapıyor lede
 
WhatsApp Image 2022-04-12 at 09.09.57.jpeg

piconun içindeki dirençler dandik @Gokrtl abi kendim 1k pull-up yaptım programdan direkt input seçtim led'e pwm yaparken hiçbir puls kaçırmadan ters yön okumadan 150ye kadar saydırdım
 
Kod:
// Rotary Encoder Inputs
#define CLK 16
#define DT 17
#define SW 4//kullanmadım

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;

void setup() {
    
    // Set encoder pins as inputs
    pinMode(CLK,INPUT);
    pinMode(DT,INPUT);
    pinMode(SW, INPUT_PULLUP);

    // Setup Serial Monitor
    Serial.begin(9600);

    // Read the initial state of CLK
    lastStateCLK = digitalRead(CLK);
}

void loop() {
    
    // Read the current state of CLK
    currentStateCLK = digitalRead(CLK);

    // If last and current state of CLK are different, then pulse occurred
    // React to only 1 state change to avoid double count
    if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

        // If the DT state is different than the CLK state then
        // the encoder is rotating CCW so decrement
        if (digitalRead(DT) != currentStateCLK) {
            counter --;
            currentDir ="CCW";
        } else {
            // Encoder is rotating CW so increment
            counter ++;
            currentDir ="CW";
        }

        Serial.print("Direction: ");
        Serial.print(currentDir);
        Serial.print(" | Counter: ");
        Serial.println(counter);
    }

    // Remember last CLK state
    lastStateCLK = currentStateCLK;

    // Read the button state
    int btnState = digitalRead(SW);

    //If we detect LOW signal, button is pressed
    if (btnState == LOW) {
        //if 50ms have passed since last LOW pulse, it means that the
        //button has been pressed, released and pressed again
        if (millis() - lastButtonPress > 50) {
            Serial.println("Button pressed!");
        }

        // Remember last button press event
        lastButtonPress = millis();
    }

    // Put in a slight delay to help debounce the reading
    delay(1);
}
 
ENNCODER5.png

Böyle bir tasarım yaptım ama ne kadar etkili olur denemek lazım
 
Kod:
// Rotary Encoder Inputs
#define CLK 16
#define DT 17
#define SW 4//kullanmadım

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;

void setup() {
  
    // Set encoder pins as inputs
    pinMode(CLK,INPUT);
    pinMode(DT,INPUT);
    pinMode(SW, INPUT_PULLUP);

    // Setup Serial Monitor
    Serial.begin(9600);

    // Read the initial state of CLK
    lastStateCLK = digitalRead(CLK);
}

void loop() {
  
    // Read the current state of CLK
    currentStateCLK = digitalRead(CLK);

    // If last and current state of CLK are different, then pulse occurred
    // React to only 1 state change to avoid double count
    if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

        // If the DT state is different than the CLK state then
        // the encoder is rotating CCW so decrement
        if (digitalRead(DT) != currentStateCLK) {
            counter --;
            currentDir ="CCW";
        } else {
            // Encoder is rotating CW so increment
            counter ++;
            currentDir ="CW";
        }

        Serial.print("Direction: ");
        Serial.print(currentDir);
        Serial.print(" | Counter: ");
        Serial.println(counter);
    }

    // Remember last CLK state
    lastStateCLK = currentStateCLK;

    // Read the button state
    int btnState = digitalRead(SW);

    //If we detect LOW signal, button is pressed
    if (btnState == LOW) {
        //if 50ms have passed since last LOW pulse, it means that the
        //button has been pressed, released and pressed again
        if (millis() - lastButtonPress > 50) {
            Serial.println("Button pressed!");
        }

        // Remember last button press event
        lastButtonPress = millis();
    }

    // Put in a slight delay to help debounce the reading
    delay(1);
}
Senin kodları hiç değişiklik yapmadan boş picoya yükledim.
Sağada çevirsem, solada çevirsem hep sola sayıyor.

encoder.png


20220412_102527.jpg
 
Sizin kodlar bende hata veriyor.

semih.png
 

Forum istatistikleri

Konular
7,413
Mesajlar
125,129
Üyeler
3,012
Son üye
BenMuhsin

Son kaynaklar

Son profil mesajları

Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
Freemont2.0 posta Freemont2.0 wrote on posta's profile.
Merhabalar :)
az bilgili çok meraklı
Prooffy semih_s Prooffy wrote on semih_s's profile.
Merhaba, sizden DSO2C10 hakkında bilgi rica ettim. Yanıtlarsanız sevinirim...
Unal taydin Unal wrote on taydin's profile.
Timur Bey, Arduino kontrollü bir akü şarj cihazı yapmaya çalışıyorum. Aklımdaki fikri basit bir çizim olarak konu açmıştım. Özellikle sizin fikirlerinizi çok önemsiyorum.
Back
Top