Rotary enkoder kontakt atlaması (contact bounce)

@Gokrtl , senin konuna gönderdiğim kod debounce yapıyordu ve delay içermiyordu. kodda bir sorun mu vardı? encoder pozisyonunu yazdırmayan bir versiyonunu ekliyorum.

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
      break;
    case 0b01:
      switch (enc)
      {
      
      case 0b11:
        if(adimBayrak)
        {
          // Azalış yönüne yazılacak kod.
          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)
        {
          // atış yönüne yazılacak kod
          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;
}

Bu encoderdeki bounce sorununu kondansatörün çözmemesinin sebebinin birbirine sürterek çalışan kontaklardan kaynaklandığını düşünüyorum kontaklar sürtmeye devam ettikçe encoder içindeki toz vb. maddeler makul debounce süresinden daha uzun sürede tekrar kontak yapıyor olmalılar diye düşünüyorum.

Bu kodla ilgili sorun var mıdır? Ben de yakın zamanda başladım encoder kullanmaya, öğrenmekte olan biri olarak soruyorum...
 
Şimdi bir RC filtre ekleyince durum nasıl oluyor görelim. Maksimum bounce süresini 10 ms kabul ederek ve belli bir marj da bırakarak zaman sabiti 20 ms olacak şekilde bir RC filtre koyalım. Aslında burada kondansatör şarj olurken 94 k deşarj olurken 47 k görüyor, ama neyse.

16633 eklentisine bak
Düzeneği bozmadıysan r2 yi kaldırıp R1 10k, c1 100nf ile test edebilir misin?
 
Tuşlu enkoderle kullanıyorum, A ve B girişlerini Arduino dahili pullup'larla 5 volta çekip kullanıyorum.

IMG20220413202212.jpg
 
Herhalde benim bir eksik bilgim var. Ben bu mekanik enkoderlerin farklı bir sinyal protokolü olduğunu biliyordum. Mesela benimkinde CLK ve DT yazıyor, yani birisi sayıyor diğeri yönü belirtiyor diye düşündüm ben. Şunu bir inceleyeyim bakalım.
 
Ayrı bir protokol değilmiş. Bu mekanik enkoder de A B sinyallemesi kullanıyor. A high iken B düşerse bir yön, B high iken A düşerse diğer yön.

a.png
 
@Gokrtl , senin konuna gönderdiğim kod debounce yapıyordu ve delay içermiyordu. kodda bir sorun mu vardı? encoder pozisyonunu yazdırmayan bir versiyonunu ekliyorum.

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
      break;
    case 0b01:
      switch (enc)
      {
     
      case 0b11:
        if(adimBayrak)
        {
          // Azalış yönüne yazılacak kod.
          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)
        {
          // atış yönüne yazılacak kod
          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;
}

Bu encoderdeki bounce sorununu kondansatörün çözmemesinin sebebinin birbirine sürterek çalışan kontaklardan kaynaklandığını düşünüyorum kontaklar sürtmeye devam ettikçe encoder içindeki toz vb. maddeler makul debounce süresinden daha uzun sürede tekrar kontak yapıyor olmalılar diye düşünüyorum.

Bu kodla ilgili sorun var mıdır? Ben de yakın zamanda başladım encoder kullanmaya, öğrenmekte olan biri olarak soruyorum...

Kodu denedim. Biraz da basitleştirdim. Gayet güzel çalışıyor. Çok nadiren, çok hızlı çevirince bazan adım kaçırdığı oluyor, ama birçok uygulama için bu hiç sorun değil. Ancak bir CNC makinanın eksen bilgisi okunuyorsa o zaman sorun olurdu.

Kod:
#define encA  2
#define encB  3

static unsigned int period = 0xffff;
int konum, enc, enc1, adimBayrak;

void encoder(void)
{
  enc = digitalRead(encB) + (digitalRead(encA) << 1);

  if (enc1 != enc)
  {
    switch (enc1)
    {
    case 0b00:
      adimBayrak=1; // debounce için bayrak değişken
      break;

    case 0b01:
      if (enc == 0b11)
      {
        if (adimBayrak)
        {
          --konum;
          adimBayrak = 0;
        }
      }
      break;

    case 0b10:
      if (enc == 0b11)
      {
        if (adimBayrak)
        {
          ++konum;
          adimBayrak = 0;
        }
      }
      break;
    }
 
    enc1 = enc;
  }
}

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

  attachInterrupt(digitalPinToInterrupt(encA), encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encB), encoder, CHANGE);
 
  pinMode(encA,INPUT_PULLUP);
  pinMode(encB,INPUT_PULLUP);

  enc = enc1 = digitalRead(encB) + (digitalRead(encA) << 1);
}

void loop() {
  if (period == 0)
  {
    period = 0xffff;
    Serial.print(konum); Serial.print('\n');
  }
  else
  {
    --period;
  }
}
 
@Gokrtl , senin konuna gönderdiğim kod debounce yapıyordu ve delay içermiyordu. kodda bir sorun mu vardı?
Senin kodunu ne yaptımsa picoya tanıtamadım. O arada birden fazla kodla uğraştığım için beynim yanmıştı.
 
Kodu denedim. Biraz da basitleştirdim. Gayet güzel çalışıyor. Çok nadiren, çok hızlı çevirince bazan adım kaçırdığı oluyor, ama birçok uygulama için bu hiç sorun değil. Ancak bir CNC makinanın eksen bilgisi okunuyorsa o zaman sorun olurdu.

Kod:
#define encA  2
#define encB  3

static unsigned int period = 0xffff;
int konum, enc, enc1, adimBayrak;

void encoder(void)
{
  enc = digitalRead(encB) + (digitalRead(encA) << 1);

  if (enc1 != enc)
  {
    switch (enc1)
    {
    case 0b00:
      adimBayrak=1; // debounce için bayrak değişken
      break;

    case 0b01:
      if (enc == 0b11)
      {
        if (adimBayrak)
        {
          --konum;
          adimBayrak = 0;
        }
      }
      break;

    case 0b10:
      if (enc == 0b11)
      {
        if (adimBayrak)
        {
          ++konum;
          adimBayrak = 0;
        }
      }
      break;
    }
 
    enc1 = enc;
  }
}

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

  attachInterrupt(digitalPinToInterrupt(encA), encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encB), encoder, CHANGE);
 
  pinMode(encA,INPUT_PULLUP);
  pinMode(encB,INPUT_PULLUP);

  enc = enc1 = digitalRead(encB) + (digitalRead(encA) << 1);
}

void loop() {
  if (period == 0)
  {
    period = 0xffff;
    Serial.print(konum); Serial.print('\n');
  }
  else
  {
    --period;
  }
}
Abi FANUC diye bir markanın cnc tezgahında lineer bir hareketli dişlinin dişlerini sayan temassız bir enkoderi vardı değişimine servisi 10bin tl almıştı 1 yıl önce.
Bu japonlar temassız kaç diş gitmiş nasıl okuyor onu anlamış değilim.
 
Abi FANUC diye bir markanın cnc tezgahında lineer bir hareketli dişlinin dişlerini sayan temassız bir enkoderi vardı değişimine servisi 10bin tl almıştı 1 yıl önce.
Bu japonlar temassız kaç diş gitmiş nasıl okuyor onu anlamış değilim.

Mıknatıslı hall sensör kullanıyor olmalılar, abs sensörleri gibi. Metal diş sensöre yaklaşınca manyetik akı yoğunlaşıyor.
 
Mıknatıslı hall sensör kullanıyor olmalılar, abs sensörleri gibi. Metal diş sensöre yaklaşınca manyetik akı yoğunlaşıyor.
Abi nasıl çalıştığını bilmiyorum fanuclar çok karışık servis eline gazeteden büyük şemalar seriyordu.
ben ilk gördüğümde enkoder olacağı aklımın ucundan geçmedi aklımdaki enkoder yapısı motorun arkasına takılan redüktör ucuna takılan küçük dc motorlara benzeyenlerdi.

Servis hata koduna bakınca enkoder dedi söktüler bir yerleri bi çıktı hiçbir mekanik bağlantısı yok ortalama 1 santim bir mesafede dikilip duruyor ben mili varda kırıldı sanıyordum yenisi geldi yine öyle durdu ama makine milim kaydırmadan parça işliyor çok garibime gitti
 
CNC lerde de AB enkoder kullanılıyor. Ama orada bir tane de ilave sinyal var, o da Z sinyali. Yani ABZ enkoder denebilir. Z sinyali, enkoder bir tur attığında bir kere üretiliyor. Bu sinyali kullanarak kontrol kartı her turda bilinen belli bir konuma gelindiğini anlıyor.
 
Abi nasıl çalıştığını bilmiyorum fanuclar çok karışık servis eline gazeteden büyük şemalar seriyordu.
ben ilk gördüğümde enkoder olacağı aklımın ucundan geçmedi aklımdaki enkoder yapısı motorun arkasına takılan redüktör ucuna takılan küçük dc motorlara benzeyenlerdi.

Servis hata koduna bakınca enkoder dedi söktüler bir yerleri bi çıktı hiçbir mekanik bağlantısı yok ortalama 1 santim bir mesafede dikilip duruyor ben mili varda kırıldı sanıyordum yenisi geldi yine öyle durdu ama makine milim kaydırmadan parça işliyor çok garibime gitti
Belki de bir çeşit fail-safe işlevi görüyordur, hassas ölçümü başka bir yerden ölçüyor olabilir. Hareketi teyit etmek için gibi.
 
CNC lerde de AB enkoder kullanılıyor. Ama orada bir tane de ilave sinyal var, o da Z sinyali. Yani ABZ enkoder denebilir. Z sinyali, enkoder bir tur attığında bir kere üretiliyor. Bu sinyali kullanarak kontrol kartı her turda bilinen belli bir konuma gelindiğini anlıyor.
Abi daha önce 3 fazlı motorun arkasına takılan milli bir enkoder kullandım markası autonics'di dediğin gibi ABZ ve bunların tersleniği olarak A- B- Z- vardı.
Bunun amacı neydi anlamadım 8 kablo çıkıyordu 2si besleme kalan 6sı ABZ ve terslenikleri.
 
Kodu denedim. Biraz da basitleştirdim.
void loop içindeki kısmı anlamadım. Bu yapı burada sabit duracak mı? Ben encoderi kullanmak için sadece "period" değişkenini alsam yetiyor mu?

Kod:
if (period == 0)
  {
    period = 0xffff;
    Serial.print(konum); Serial.print('\n');
  }
  else
  {
    --period;
  }
 
void loop içindeki kısmı anlamadım. Bu yapı burada sabit duracak mı? Ben encoderi kullanmak için sadece "period" değişkenini alsam yetiyor mu?

Kod:
if (period == 0)
  {
    period = 0xffff;
    Serial.print(konum); Serial.print('\n');
  }
  else
  {
    --period;
  }
Sanırım "serial.print" kodunu kesme dışına alıp kesme içindeki gecikme etkisini ortadan kaldırmak ve kontak atlamasında ekstra adım atıp atmadığını sınamak için konumu loopta yazdrmış. looptaki kod enkoder işlevi için gerekli değil.
 
looptaki kodun tek amacı arada bir konumu serial monitöre yazmak.
 
Abi daha önce 3 fazlı motorun arkasına takılan milli bir enkoder kullandım markası autonics'di dediğin gibi ABZ ve bunların tersleniği olarak A- B- Z- vardı.
Bunun amacı neydi anlamadım 8 kablo çıkıyordu 2si besleme kalan 6sı ABZ ve terslenikleri.

Terslenik çıkışlar difransiyel olarak geçer teknik olarak ise line drive. Emf gürültüsü oluşsa da sinyal bozulmaz. Hayat kurtarır :) Aynı mantıkla servo step dürücü girişleride genelde bu şekildedir. dir+ dir- puls+ puls- gibi...

1649881479259.png
 

Forum istatistikleri

Konular
7,285
Mesajlar
123,214
Üyeler
2,939
Son üye
Cano

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