avatar_elektro77

rotary encoder dönüş yönü belirleme

Başlatan elektro77, 20 Eylül 2018, 12:08:26

elektro77

Aşagıdaki tip rotary encoderle bir step motoru encoderin döndüğü yönü tespit edip motoruda o yönde döndürmek istiyorum.
Yıllardır disko robotları tamir ederim ve amatörce kod yazarım ama bir türlü bu disko robotlarındaki (resimdeki gibi) olan encoderlerinin yön algılama mantığı konusunu anlamış ve bir kod yazabilmiş değilim. Mantığını bir türlü çözemiyorum.
Youtube da bir sürü video izledim ve bir sürüde kaynak okudum fakat döndüğü yönü nasıl tespit edebileceğime dair bir sonuca ulaşamadım. Yada ben anlamadım.Örnek bir video linkini aşağıya ekledim.
Pic basic proda bunu nasıl yaparız kod örneğiyle açıklayarak gösterebilirmisiniz lütfen.Resimdeki gibi bir lcd de bunu kurup sayaçta görmek istiyorum. Örneğin saga döndürdüğümde sayaç artacak sola döndürdüğümde sayaç azalacak. sayacın değerine görede aynı anda step motora yön vermek asıl amacım. Sadece mantığını anlamaya çalışıyorum ticari bir amacım yok. Yıllardır tamirini yaptığım ve kafamı kurcalayan  rotary encoder in yazılımsal olarak mantığını anlamak istiyorum.
Yardımcı olacak arkadaşlarıma Şimdiden teşekkür ederim.

bilmediğim bir dilde yazılmış ki C ye benziyor kod örnkleride aşağıdadır.
//Source & info: www.HomoFaciens.de

// include the library code:
#include <LiquidCrystal.h>
#include <util/delay.h>

int sensorStatus = 0;
int sensorStatusOld = 0;
int count = 0;
int stepTemp = 0;
int stepTempOld = 0;
int step = 0;
int stepOld = 0;
unsigned long millisStart = 0;
unsigned long millisNow = 0;
unsigned long sensorStatusVolt = 0;
unsigned long sensorStatusVoltOld = 0;

#define LCD_RS   2
#define LCD_EN   3
#define LCD_D4   4
#define LCD_D5   5
#define LCD_D6   6
#define LCD_D7   7

#define SENSOR  A0

#define BOUNCE_TIME     5
#define VOLTAGE_ERROR  61

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('X');   // send a capital X
    delay(300);
  }
}


void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Turn sensor     ");
  lcd.setCursor(0, 1);
  lcd.print("to start...     ");

  pinMode(SENSOR, INPUT);

  count = 0;
  sensorStatus = 0;
  sensorStatusOld = 0;
  step = 0;
  stepOld = 0;
  stepTemp = 0;
  stepTempOld = 0;
}

void loop() {

  sensorStatus = analogRead(SENSOR);


  millisNow = millis();
  if(millisNow < millisStart){
   millisStart = millisNow;
  }

  stepTemp = -1;

  if(sensorStatus < 367 + VOLTAGE_ERROR && sensorStatus > 367 - VOLTAGE_ERROR){
    stepTemp = 1;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 1;
      millisNow = millis();
    }
  }

  if(sensorStatus < 512 + VOLTAGE_ERROR && sensorStatus > 512 - VOLTAGE_ERROR){
    stepTemp = 2;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 2;
      millisNow = millis();
    }
  }

  if(sensorStatus < 703 + VOLTAGE_ERROR && sensorStatus > 703 - VOLTAGE_ERROR){
    stepTemp = 3;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 3;
      millisNow = millis();
    }
  }

  if(sensorStatus < VOLTAGE_ERROR){
    stepTemp = 4;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 4;
      millisNow = millis();
    }
  }

  if(stepTemp != stepTempOld){
    millisStart = millis();
    stepTempOld = stepTemp;
  }

  if(sensorStatus > 1023 - VOLTAGE_ERROR){
    stepTemp = 0;
    millisStart = millis();
  }

  if(step != stepOld){
    if(step == 1 && stepOld == 4){
      count++;
    }
    if(step == 2 && stepOld == 1){
      count++;
    }
    if(step == 3 && stepOld == 2){
      count++;
    }
    if(step == 4 && stepOld == 3){
      count++;
    }


    if(step == 1 && stepOld == 2){
      count--;
    }
    if(step == 2 && stepOld == 3){
      count--;
    }
    if(step == 3 && stepOld == 4){
      count--;
    }
    if(step == 4 && stepOld == 1){
      count--;
    }
    stepOld = step;
    lcd.setCursor(0, 0);
    lcd.print("R=");
    lcd.print(step);
    lcd.print(", count=");
    lcd.print(count);
    lcd.print("   ");
  }

  sensorStatusVolt = (double)(5.0 * (double)(sensorStatus))/1.023;


  if(abs(sensorStatusVoltOld - sensorStatusVolt) > 100){
    lcd.setCursor(0, 1);

    lcd.print("A0 = ");
    if(sensorStatusVolt < 1000){
      lcd.print(" ");
    }
    if(sensorStatusVolt < 100){
      lcd.print(" ");
    }
    if(sensorStatusVolt < 10 && sensorStatusVolt > 0){
      lcd.print(" ");
    }
    lcd.print(sensorStatusVolt);
    lcd.print("mV ");
    sensorStatusVoltOld = sensorStatusVolt;
  }


}


//Source & info: www.HomoFaciens.de

// include the library code:
#include <LiquidCrystal.h>
#include <util/delay.h>

int sensorStatus = 0;
int sensorStatusOld = 0;
int count = 0;
int stepTemp = 0;
int stepTempOld = 0;
int step = 0;
int stepOld = 0;
unsigned long millisStart = 0;
unsigned long millisNow = 0;
unsigned long sensorStatusVolt = 0;
unsigned long sensorStatusVoltOld = 0;

#define LCD_RS   2
#define LCD_EN   3
#define LCD_D4   4
#define LCD_D5   5
#define LCD_D6   6
#define LCD_D7   7

#define SENSOR  A0

#define BOUNCE_TIME     5
#define VOLTAGE_ERROR  61

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('X');   // send a capital X
    delay(300);
  }
}


void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Turn sensor     ");
  lcd.setCursor(0, 1);
  lcd.print("to start...     ");

  pinMode(SENSOR, INPUT);

  count = 0;
  sensorStatus = 0;
  sensorStatusOld = 0;
  step = 0;
  stepOld = 0;
  stepTemp = 0;
  stepTempOld = 0;
}

void loop() {

  sensorStatus = analogRead(SENSOR);


  millisNow = millis();
  if(millisNow < millisStart){
   millisStart = millisNow;
  }

  stepTemp = -1;

  if(sensorStatus < 367 + VOLTAGE_ERROR && sensorStatus > 367 - VOLTAGE_ERROR){
    stepTemp = 1;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 1;
      millisNow = millis();
    }
  }

  if(sensorStatus < 512 + VOLTAGE_ERROR && sensorStatus > 512 - VOLTAGE_ERROR){
    stepTemp = 2;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 2;
      millisNow = millis();
    }
  }

  if(sensorStatus < 703 + VOLTAGE_ERROR && sensorStatus > 703 - VOLTAGE_ERROR){
    stepTemp = 3;
    if(millisNow - millisStart > BOUNCE_TIME){
      step = 3;
      millisNow = millis();
    }
  }
  if(stepTemp != stepTempOld){
    millisStart = millis();
    stepTempOld = stepTemp;
  }

  if(sensorStatus > 1023 - VOLTAGE_ERROR){
    stepTemp = 0;
    millisStart = millis();
  }

  if(step != stepOld){
    if(step == 1 && stepOld == 3){
      count++;
    }
    if(step == 2 && stepOld == 1){
      count++;
    }
    if(step == 3 && stepOld == 2){
      count++;
    }

    if(step == 1 && stepOld == 2){
      count--;
    }
    if(step == 2 && stepOld == 3){
      count--;
    }
    if(step == 3 && stepOld == 1){
      count--;
    }
    stepOld = step;
    lcd.setCursor(0, 0);
    lcd.print("R=");
    lcd.print(step);
    lcd.print(", count=");
    lcd.print(count);
    lcd.print("   ");
  }

  sensorStatusVolt = (double)(5.0 * (double)(sensorStatus))/1.023;


  if(abs(sensorStatusVoltOld - sensorStatusVolt) > 100){
    lcd.setCursor(0, 1);

    lcd.print("A0 = ");
    if(sensorStatusVolt < 1000){
      lcd.print(" ");
    }
    if(sensorStatusVolt < 100){
      lcd.print(" ");
    }
    if(sensorStatusVolt < 10 && sensorStatusVolt > 0){
      lcd.print(" ");
    }
    lcd.print(sensorStatusVolt);
    lcd.print("mV ");
    sensorStatusVoltOld = sensorStatusVolt;
  }


}


örnek video linki: https://www.youtube.com/watch?v=dPBKTZw_xi4
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

MB_77

#1
bu mesaj tarafımdan silinmiştir.

elektro77

#2
Alıntı yapılan: MB_77 - 20 Eylül 2018, 14:01:37
işin temeli mekaniği iyi anlamakta yatıyor. mekanik konusu videoda ölçülere varana kadar detaylı anlatılmış.
sensörler ve metal kısımın ölçüleri öyle ayarlanmalı ki, bir noktaya gelince iki sensör de high olmalı. programda tam da bu noktada bir karar mekanizması olmalı. şöyle ki, bu noktadan sonra hangi taraftaki sensörün önce low olduğuna bakılmalı. işte önce low olan sensörün bulunduğu tarafın aksi yönünde dönme oluyor demektir.

bu mantıkla videoyu izlerseniz daha net anlaşılacaktır.
peki durağan pozisyon low high durumunda veya high low durumunda veya low low durumunda ise yön tayininde nasıl bir karar mekanizması aranmalı ve tüm bunlar bir döngü içinde nasıl kullanılmalı 
bu durumu basit bir kaç satırlık kod örneği ile kod açıklamalı olarak anlatabilirseniz sevinirim. Bu şekilde daha iyi anlayabileceğimi düşünüyorum.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

MB_77

#3
bu mesaj tarafımdan silinmiştir.

elektro77

yardımcı olursanız minnettar olurum. yıllardır kafamı kurcalayan bu mantığı anlamak istiyorum artık.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

MB_77

#5
bu mesaj tarafımdan silinmiştir.

elektro77

Cok tesekkur ederim . Yarin ilk is bu kodlari deneyip mantigini anlamaya calisacagim.
Emeginiz icin cok minnettarim.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

MB_77

#7
bu mesaj tarafımdan silinmiştir.

elektro77

#8
Kodların ne işe yaradığını anlamak adına değişiklikler yapıp simülasyonda ne değiştiğini görmek istedim fakat derlemede resimdeki gibi hatalar aldım. bendeki mcs veya pbp 16f1827 yi desteklemiyor olabilirmi. Siz 64 bit kullanıyorsunuz ben ise 32. sigorta ayarlarını kapatıp denedim yine aynı hataları aldım.
İkincisi:
Bu haliyle denedim program güzel çalışıyor.Fakat dediğiniz gibi çok taşma var. Bu durum ileride senaryoma göre ana döngüye  ekleyeceğim kodlar açısından sorun teşkil edecek gibi görünüyor.
senaryomun ve konunun aşağıdaki kaydettiğim videoda daha iyi anlaşılabileceğini düşünüyorum.
video linki:
https://www.youtube.com/watch?v=zIjJ_SZ4nFg&feature=youtu.be
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

elektro77

birde bir şey farkettim belki yazacağım bu durum yön tayininde yazılımı daha pratik hale getirmenizde yol gösterebilir.
Gerçek bir cihazda fazlar arasındaki farkı ölçerken göreceli ikinci optonun çıkış sinyali dönme yönünü her değişiminde göreceli birinci optonun sinyalinden 90 derece öne geçiyor. tekrar yön değişiminde 90 derece geç kalıyor.başka bir anlatımla Birinci opto çıkş sinyali heran aynı yerde sabit.  ama osiloskopun 2.kanalına bağladığım opto çıkışında yön değişimlerinde çıkış 90 derece bir öne bir arkaya geçiyor.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

MB_77

#10
bu mesaj tarafımdan silinmiştir.

MB_77

#11
bu mesaj tarafımdan silinmiştir.

elektro77

#12
Tasma dan kastim kesmedeki sismeden bahsetmenizdi. Simulqsyon sirasinda calisiyor ama arka arkaya her bir saniyede hatalar verip 1 kac dakika sonra 1000 leri buluyor. Puls sinyal frekansini 1 hz den 100 herze cikardigimda ise  bu hatalar aliyor basini gidiyor. Ama simulasyon kusursuzca sayiyor palsleri. Neden oldugunu bilmiyorum. Kastettiginiz sisme olabilecegini dusundum.
Yaziliminizdaki Kisaltmalarinizi ve dusunce seklinizi anlamaya calisiyorum. Ete hocaya alisinca biraz farkli geldi acikcasi. Sonucta sizin beyninizle dusunemem.
2 encoder la kesme dahada siseceginden bende uygun bir yolda ilerlemedigimizi az cok anladim.
Adim adim da gitsek dogru ve kestirme yoldan gitmek gerek.
Bu nedenle isin mantigini tam olarak kavramaniz icin size video hazirlayip gonderdim. Bu size tüme varim konusunda yardimci olmali.
Bir video daha gondericem.
1.optonun cikis sinyalinin sabit, ikincisinin ise birinciye gore 90 derece  ileri ve geri yer degistirmesi konusunda Osiloskop videosunuda gondericem.
Saygilarimla.
Aslinda bir bakima temel olarak cnc gibi bir sey galiba.
Cnc de duzlem olarak bunda ise dairesel olarak yol aliniyor.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

elektro77

Yaptığım bir kayıt daha:
https://youtu.be/JkIF6Ug2PDQ
Anlatımdadaki sorunlar ile ilgili şimdiden özür dilerim.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

MB_77

#14
bu mesaj tarafımdan silinmiştir.

Powered by EzPortal