Robotik Kodlama

Robotik Kodlama
Ana Sayfa

İLGİNİZİ ÇEKEBİLECEK LİNKLER :

4 Mayıs 2021 Salı

Rotary Encoder Nasıl Çalışır ve Arduino

 

Rotary Encoder Nasıl Çalışır ve Arduino

Döner kodlayıcı, bir düğmenin açısal konumunu (dönüşünü), düğmenin hangi yönde döndürüldüğünü belirlemek için kullanılan bir çıkış sinyaline dönüştüren bir tür konum sensörüdür.

Sağlamlıkları ve hassas dijital kontrolleri sayesinde; robotik, CNC makineleri ve yazıcılar dahil birçok uygulamada kullanılmaktadır.

İki tür döner kodlayıcı vardır - mutlak ve artımlı. Mutlak kodlayıcı bize topuzun derece cinsinden tam konumunu verirken artımlı kodlayıcı milin kaç artım hareket ettiğini bildirir.Bu eğitimde kullanılan döner kodlayıcı artımlı tiptedir.

Rotary Enkoderler Vs Potansiyometreler

Döner Kodlayıcılar, potansiyometrenin modern dijital eşdeğeridir ve bir potansiyometreden daha çok yönlüdür.Potansiyometre dairenin yalnızca 3 / 4'ünü dönerken, uç durdurucular olmadan tamamen dönebilirler.Potansiyometreler, düğmenin tam konumunu bilmeniz gereken durumlarda en iyisidir. Bununla birlikte, döner kodlayıcılar, kesin konum yerine konumdaki değişikliği bilmeniz gereken durumlarda en iyisidir.

Rotary Enkoderler Nasıl Çalışır?

Kodlayıcının içinde, aşağıda gösterildiği gibi, ortak toprak pimi C'ye ve iki kontak pini A ve B'ye bağlı yarıklı bir disk bulunur.

döner kodlayıcı iç yapısı

Düğmeyi çevirdiğinizde, A ve B, düğmeyi çevirdiğiniz yöne göre belirli bir sırada ortak toprak pimi C ile temas eder.Ortak zemine temas ettiklerinde sinyaller üretirler. Bir pim diğer pinden önce temas ettiğinden, bu sinyaller birbirleriyle 90 ° faz dışına kaydırılır. Buna karesel kodlama denir .

döner kodlayıcı çalışan animation.gif

Düğmeyi saat yönünde çevirdiğinizde, önce A pini, ardından B pini bağlanır. Düğmeyi saat yönünün tersine çevirdiğinizde, önce B pini, ardından A pini bağlanır.Her bir pimin ne zaman toprağa bağlandığını ve bağlantısını kestiğini izleyerek, düğmenin hangi yönde döndürüldüğünü belirlemek için bu sinyal değişikliklerini kullanabiliriz. Bunu, A durumu değiştiğinde B'nin durumunu gözlemleyerek yapabilirsiniz.

A durumu değiştiğinde:

  • B! = A ise, düğme saat yönünde çevrilmiştir.
    saat yönünde dönüşte döner kodlayıcı çıkış darbeleri
  • B = A ise, düğme saat yönünün tersine çevrildi.
    saat yönünün tersine dönüşte döner kodlayıcı çıkış darbeleri

Döner Kodlayıcı Pin Çıkışı

Döner kodlayıcının pimleri aşağıdaki gibidir:

döner kodlayıcı modülü pin çıkışı

GND Toprak bağlantısıdır.

VCC pozitif besleme voltajıdır, genellikle 3,3 veya 5 Volttur.

SWaktif düşük basmalı düğme anahtarı çıkışıdır. Düğmeye basıldığında voltaj DÜŞÜK olur.

DT (B Çıkışı)CLK çıkışı ile aynıdır, ancak CLK'yi 90 ° faz kayması ile geride bırakır. Bu çıktı, dönüş yönünü belirlemek için kullanılabilir.

CLK (Çıkış A)dönüş miktarını belirlemek için birincil çıkış darbesidir. Düğme her iki yönde de bir kilit (tıklama) döndürüldüğünde, 'CLK' çıkışı bir döngüde YÜKSEK ve ardından DÜŞÜK konuma geçer.

Kablolama - Döner Kodlayıcıyı Arduino ya Bağlama

Rotary Encoder'ı Arduino'ya bağlayalım. Bağlantılar oldukça basit. Modül üzerindeki + V pinini Arduino'daki 5V'a ve GND pinini toprağa bağlayarak başlayın.Şimdi CLK ve DT pinlerini sırasıyla dijital pin # 2 ve # 3'e bağlayın. Son olarak, SW pinini 4 numaralı dijital pime bağlayın.Aşağıdaki çizim bağlantıyı göstermektedir.

arduino uno ile döner kodlayıcı kablolama

Arduino Kodu - Döner Kodlayıcıları Okuma

Aşağıdaki çizim, kodlayıcının ne zaman döndürüldüğünü algılar, hangi yöne döndürüldüğünü ve düğmeye basılıp basılmadığını belirler.Krokiyi deneyin; ve sonra onu biraz ayrıntılı olarak inceleyeceğiz.

// Rotary Encoder Inputs
#define CLK 2
#define DT 3
#define SW 4

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);
}

Her şey yolundaysa, aşağıdaki çıktıyı seri monitörde görmelisiniz.

seri monitörde döner kodlayıcı çıkışı

Rapor edilen dönüş beklediğinizin tersi ise, CLK ve DT hatlarını değiştirmeyi deneyin.

Kod Açıklaması:

Taslak, kodlayıcının CLK, DT ve SW pinlerinin bağlı olduğu Arduino pinlerinin bildirimi ile başlar.

#define CLK 2
#define DT 3
#define SW 4

Daha sonra birkaç tam sayı tanımlanır. counterDeğişken topuzu döndürülmüş bir tetik (tıklama) olduğunu her seferinde değiştirilmiş olacaktır sayımı temsil eder.

currentStateCLKVe lastStateCLKdeğişkenler CLK çıkış durumunu tutmak ve dönme miktarını belirlemek için kullanılır.

currentDirSeri monitörde geçerli dönüş yönü yazdırılırken çağrılan bir dizi kullanılacaktır.

lastButtonPressDeğişken bir anahtarı sektirilmesini için kullanılır.

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

Şimdi Kurulum bölümünde, önce enkodere olan bağlantıları giriş olarak tanımlıyoruz, ardından SW pininde giriş pullup direncini etkinleştiriyoruz. Seri monitörü de kurduk.

Sonunda CLK pininin o anki değerini okur ve lastStateCLKdeğişkende saklarız .

pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);

Serial.begin(9600);

lastStateCLK = digitalRead(CLK);

Döngü bölümünde CLK durumunu tekrar kontrol edip lastStateCLKdeğer ile karşılaştırıyoruz Farklılarsa, bu, düğmenin döndüğü ve bir nabızın meydana geldiği anlamına gelir. currentStateCLKÇift sayımı önlemek için tek bir durum değişikliğine tepki vermek için değerinin olup olmadığını da kontrol ederiz .

currentStateCLK = digitalRead(CLK);

if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

İf ifadesinin içinde dönüş yönünü belirleriz. Bunu yapmak için, kodlayıcı modülündeki DT pinini okur ve CLK pininin mevcut durumu ile karşılaştırırız.Farklı olmaları, düğmenin saat yönünün tersine döndürüldüğü anlamına gelir. Daha sonra sayacı azaltıyoruz ve currentDir"CCW" olarak ayarlıyoruz.İki değer aynı ise, düğme saat yönünde döndürülmüş demektir. Daha sonra sayacı artırıyoruz ve currentDir"CW" ye ayarlıyoruz .

if (digitalRead(DT) != currentStateCLK) {
    counter --;
    currentDir ="CCW";
} else {
    counter ++;
    currentDir ="CW";
}

Daha sonra sonuçlarımızı seri monitöre yazdırıyoruz.

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

İf ifadesinin dışında lastStateCLKmevcut CLK durumuyla güncelliyoruz.

lastStateCLK = currentStateCLK;

Ardından, basmalı düğmeyi okuma ve geri alma mantığı gelir. Önce mevcut düğme durumunu okuruz, DÜŞÜK ise, basma düğmeyi geri almak için 50 ms beklenir.Düğme 50 ms'den daha uzun süre DÜŞÜK kalırsa, "Düğmeye basıldı!" seri monitörde mesaj.

int btnState = digitalRead(SW);

if (btnState == LOW) {
    if (millis() - lastButtonPress > 50) {
        Serial.println("Button pressed!");
    }
    lastButtonPress = millis();
}

Sonra her şeyi yeniden yapıyoruz.

Arduino Kodu - Kesmeleri Kullanma

Döner kodlayıcının çalışması için DT ve CLK sinyallerindeki değişiklikleri sürekli izlememiz gerekir.Bu tür değişikliklerin ne zaman gerçekleştiğini belirlemek için, onları sürekli olarak sorgulayabiliriz (önceki taslakta yaptığımız gibi). Ancak, aşağıdaki nedenlerden dolayı bu en iyi çözüm değildir.

  • Bir değerin değişip değişmediğini görmek için yoğun bir şekilde kontrol yapmak zorundayız. Sinyal seviyesi değişmezse döngü israfı olacaktır.
  • Olayın gerçekleştiği andan kontrol ettiğimiz ana kadar gecikme olacaktır. Derhal tepki vermemiz gerekirse, bu gecikmeyle gecikeceğiz.
  • Değişiklik süresi kısaysa, sinyal değişikliğini tamamen kaçırmak mümkündür.

Yaygın olarak benimsenen bir çözüm, bir kesintinin kullanılmasıdır .Kesintilerle belirli bir olayı sürekli olarak sorgulamanıza gerek yoktur. Bu, olayı kaçırmadan başka işler yapmak için Arduino'yu serbest bırakır.

Bağlantılar

Çoğu Arduino (Arduino UNO dahil) yalnızca iki harici kesintiye sahip olduğundan, yalnızca DT ve CLK sinyallerindeki değişiklikleri izleyebiliriz. Bu yüzden önceki bağlantı şemasından SW pimi bağlantısını kaldırdık.

Şimdi kablolama şuna benziyor:

arduino uno ile kesmeleri kullanarak döner kodlayıcıyı kontrol edin

Bazı kartlar (Arduino Mega 2560 gibi) daha fazla harici kesintiye sahiptir. Bunlardan birine sahipseniz, SW pin bağlantısını koruyabilir ve düğme kodunu dahil etmek için taslağın altına uzatabilirsiniz.

Arduino Kodu

Döner kodlayıcı okurken kesintilerin kullanımını gösteren taslak burada.

// Rotary Encoder Inputs
#define CLK 2
#define DT 3

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";

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

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

	// Read the initial state of CLK
	lastStateCLK = digitalRead(CLK);
	
	// Call updateEncoder() when any high/low changed seen
	// on interrupt 0 (pin 2), or interrupt 1 (pin 3)
	attachInterrupt(0, updateEncoder, CHANGE);
	attachInterrupt(1, updateEncoder, CHANGE);
}

void loop() {
	//Do some useful stuff here
}

void updateEncoder(){
	// 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;
}

Bu programın ana döngüsünün boş tutulduğuna dikkat edin, böylece Arduino hiçbir şey yapmakla meşgul olacak.Bu arada, bu program dijital pin 2'yi (kesinti 0'a karşılık gelir) ve dijital pin 3'ü (kesinti 1'e karşılık gelir) bir değer değişikliği için izler. Başka bir deyişle, düğmeyi çevirdiğinizde HIGH'dan LOW'a veya LOW'dan HIGH'a giden bir voltaj değişikliği arar.

Bu olduğunda, işlev updateEncoder(genellikle kesme hizmeti rutini veya yalnızca ISR olarak adlandırılır) çağrılır. Bu işlev içindeki kod çalıştırılır ve ardından program daha önce yaptığı şeye geri döner.

Tüm bunlardan iki satırın altında sorumludur. İşlev attachInterrupt(), Arduino'ya hangi pinin izleneceğini, kesinti tetiklendiğinde hangi ISR'nin çalıştırılacağını ve ne tür bir tetikleyicinin aranacağını söyler.

attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);

Döner Enkoderli Kontrol Servo Motor

Bir sonraki projemizde, bir servo motorun konumunu kontrol etmek için bir döner kodlayıcı kullanacağız.

Bu proje, birçok durumda çok yararlı olabilir, örneğin, bir robot kolu çalıştırmak istediğinizde, kolu ve tutuşunu tam olarak konumlandırmanıza izin vereceği için.

Bağlantı şemasının gösterdiği gibi bir servo motora ihtiyacınız olacak. Servo motorun Kırmızı kablosunu harici 5V beslemeye, Siyah / Kahverengi kabloyu toprağa ve Turuncu / Sarı kabloyu PWM etkin pim 9'a bağlayın.

Elbette Arduino 5V çıkışını kullanabilirsiniz, ancak servonun Arduino'nun kullandığı 5V hattına elektriksel gürültüye neden olabileceğini unutmayın, ki bu istediğinizi olmayabilir.

Bu nedenle, harici bir güç kaynağı kullanmanız önerilir.

döner kodlayıcı ile servo motoru kontrol etmek için kablo

Arduino Kodu

Döner kodlayıcı ile servo motoru hassas bir şekilde kontrol etmek için çizim burada. Düğme her bir kilit (klik) döndürüldüğünde, servo kolun konumu bir derece değiştirilecektir.

// Include the Servo Library
#include <Servo.h>

// Rotary Encoder Inputs
#define CLK 2
#define DT 3

Servo servo;
int counter = 0;
int currentStateCLK;
int lastStateCLK;

void setup() {
	
	// Set encoder pins as inputs
	pinMode(CLK,INPUT);
	pinMode(DT,INPUT);
	
	// Setup Serial Monitor
	Serial.begin(9600);
	
	// Attach servo on pin 9 to the servo object
	servo.attach(9);
	servo.write(counter);
	
	// 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 --;
			if (counter<0)
				counter=0;
		} else {
			// Encoder is rotating CW so increment
			counter ++;
			if (counter>179)
				counter=179;
		}
		// Move the servo
		servo.write(counter);
		Serial.print("Position: ");
		Serial.println(counter);
	}
	
	// Remember last CLK state
	lastStateCLK = currentStateCLK;
}

Bu çizimi ilkiyle karşılaştırırsanız, birkaç şey dışında birçok benzerlik fark edeceksiniz.

Başlangıçta yerleşik Arduino Servo kitaplığını dahil ediyoruz ve servo motorumuzu temsil edecek bir servo nesnesi oluşturuyoruz.

#include <Servo.h>

Servo servo;

Kurulumda, servo nesnesini pin 9'a (servo motorun kontrol piminin bağlı olduğu) bağlarız.

servo.attach(9);

Döngüde, bir servo motor yalnızca bu aralık arasındaki bir değeri kabul ettiğinden, sayacı 0 ila 179 aralığına sınırlandırırız.

if (digitalRead(DT) != currentStateCLK) {
    counter --;
    if (counter<0)
        counter=0;
} else {
    counter ++;
    if (counter>179)
        counter=179;
}

Son olarak sayaç değeri servo motoru konumlandırmak için kullanılır.

servo.write(counter);

ANA SAYFAYA DÖN

Bahadır ÖZGEN
Electronic Robotic Coding Research and Development 1975 - ∞
Learn Forever
If you want, let's learn together...
https://roboticcode2020.blogspot.com/
bahadirozgen1975@gmail.com
facebook    robotic.code
instagram    @roboticcode


Sayfalarımı ziyaret ettiğiniz için teşekkür ederim.Bu sitede mevcut olan içerikler kendi oluşturduğum projeler yazı,resim ve videolardan oluşmaktadır.İçerik oluşturmak çok uzun sürdüğü için bazı projelerde yurtdışı kaynaklardan faydalandım.Buradaki amacım ticari değildir.Kaynağı belli olan ve bizim kaynağına ulaşabildiğimiz materyal (yazı, fotoğraf, resim, video v.b.) için ilgili konularda fotoğraflarda logo varsa v.b. not olarak gösterilecektir.Sitemizde yayınlanan tüm içerik, bizim tarafımızdan ve internet üzerinden youtube, facebook ve blog gibi paylaşıma sunulmuş kaynak sitelerden alındığı için, sitemiz yasal yükümlülüğe tabi tutulamaz. Sitemizde telif haklarının size ait olduğu bir içerik varsa ve bunu kaldırmamızı isterseniz, iletişim sayfamızdan bizimle iletişime geçtiğiniz takdirde içerik yayından kaldırılacaktır.Bu konu ve modüller ile uğraşarak, ileride çok güzel makine ve elektronik aletler yapabilirsiniz.

Hiç yorum yok:

Yorum Gönder

Yorum yazdığınız ve üye olduğunuz için Size teşekkür ederim.Burada olduğunuza göre hepimizin ilgi alanı Elektronik ve Programlama sonsuz bir dünyadayız.Hepimize Başarılar...

Not: Yalnızca bu blogun üyesi yorum gönderebilir.