iyi aksamlar picproje ailesi elimde enkoder var a ve b çıkışı olan ben bu enkoder saga veya sola dönderirken yön degişkeni sabit kalmıyor 0 1 arası değişiyor enkoder çevirirken yön değişkenin sabit kalması için ne yapmam lazım? xor yapıyorum.
rb kesmesi
yön=yeniA^eskiB
yeniA=eskiA yeniB=eskiB
Donanısal olarak yapmak en iyisi. D tipi bir FF kullanabilirsin bunun için
Encoderin A Sinyalini D tipi FF'in D girişine, B Sinyalini ise CLK girişine bağla, FF'in çıkışı 1 ise bir yöne 0 ise diğer yöne dönüyordur.
https://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/
bu siteye bakmanızı öneririm. O iki pinden birini clk olarak seçip diğerini yön olarak belirleyin. Çıkış veya iniş tetikleme seçebilirsiniz. Diyelim clk için çıkış tetikleme seçtiniz. Tetiklendiğinde yön pini 0 sa sağa, 1 se sola veya tam tersi bir mantıkla çalıştırabilirsiniz.
clk kesmesi{
if(0 == yon) rotation = CW
else rotation = CCW
}
veya
clk kesmesi{
if(0 == yon) cnt++
else cnt--
}
donanımsal olarak değilde yazılımsal yapmam lazım C de örnek algoritma buraya yazarsanız makbule gececek
Skopla inceleyerek kodu yazarsaniz daha iyi olur.
Ileri tanımladığınız yerde ince bi pals verin mesela, bunu da skoba baglayin, görün olayı..
rb kesmesi
yön=yeniA^eskiB
yeniA=eskiA yeniB=eskiB
kodun mantıgı yukardaki gibi a ve b nin farkını alarak yön değişkenine atıyorum enkoder pals üretirken bu yön değişkeni sabit kalmıyor 0 ile 1 arasında geziyor enkoder döndükce ben saga dönerken 0 sola dönerken 1 sabit oynamayan kod yazmak istiyorum onun için yardımcı olursanız cok ikrama gececek üstad.
Encoder teorik olarak A ve B çıkışlarından saat yönünde %11 - %01 - %00 - %10 - %11 şeklinde çıkış verir. Saatin tersi yönünde ise bu sıraalama sağdan sola doğru olur. Yani %11 - %10 - %00 - %01 - %11 şeklinde.
Öncelikle bir okuma yapılmalı Buna Eski diyelim. ESKI=%11 olsun. Ardından hemen bir okuma daha yapılır Bunada YENI diyelim. YENI=%11 ise encoder henüz dönmedi demektir. Değişiklik oluncaya kadar YENI okuması tekrarlanır. (programın burada takılıp kalmaması için birde sayaç eklenip belirli sayıda okumdan sonra okuma döngüsünden çıkılmalıdır ki buda zaten enkoderin dönmediği anlamına gelecektir).
YON=ESKI.Bit0 ile YENI.Bit1 XOR yapılır. Yukarıdaki örneğe göre yürürsek YON=1 XOR 0= 1 dir. Bu bize encoderin saat yönünde döndüğünü gösterir. Aynı hesabı saatin tersi yönünde dönüş için yapalım, YON=1 XOR 1=0 Buda encoderin ters yönde döndüğünü gösterecektir.
Sizin hesapta okunan değerler komple XOR yapılmış kusur buradan geliyor olsa gerek.
Birinin ilk biti ile diğerinin İkinci biti XOR yapılmalıdır.
Ete
Alıntı yapılan: ete - 20 Nisan 2018, 10:50:07Encoder teorik olarak A ve B çıkışlarından saat yönünde %11 - %01 - %00 - %10 - %11 şeklinde çıkış verir. Saatin tersi yönünde ise bu sıraalama sağdan sola doğru olur. Yani %11 - %10 - %00 - %01 - %11 şeklinde.
Öncelikle bir okuma yapılmalı Buna Eski diyelim. ESKI=%11 olsun. Ardından hemen bir okuma daha yapılır Bunada YENI diyelim. YENI=%11 ise encoder henüz dönmedi demektir. Değişiklik oluncaya kadar YENI okuması tekrarlanır. (programın burada takılıp kalmaması için birde sayaç eklenip belirli sayıda okumdan sonra okuma döngüsünden çıkılmalıdır ki buda zaten enkoderin dönmediği anlamına gelecektir).
YON=ESKI.Bit0 ile YENI.Bit1 XOR yapılır. Yukarıdaki örneğe göre yürürsek YON=1 XOR 0= 1 dir. Bu bize encoderin saat yönünde döndüğünü gösterir. Aynı hesabı saatin tersi yönünde dönüş için yapalım, YON=1 XOR 1=0 Buda encoderin ters yönde döndüğünü gösterecektir.
Sizin hesapta okunan değerler komple XOR yapılmış kusur buradan geliyor olsa gerek.
Birinin ilk biti ile diğerinin İkinci biti XOR yapılmalıdır.
Ete
erol abi merhaba uzun zamandır göremiyoruz seni :)
neyse konumuza gelince senin mantıgın ile yapıyorum lakin yön değişkeni 0 1 geziyor enkoder dönerken ben bunu sabitliyemedim bu konuda burda kücük bir kod paylaşabilirmisin abi?
yön=a^b bundan sonrası için nasıl yol izlemem lazım?
enkoder ile mcu nun bağlantısını görebilirmiyız
Alıntı yapılan: sadogan - 20 Nisan 2018, 11:20:17enkoder ile mcu nun bağlantısını görebilirmiyız
abi arasında uln2003 var enkoder 2003 giriyor 2003 cıkısı mcu b4 b5 portuna baglı rb kesmesi kullanıyorum savas abi :)
şema keşfedilmedi mi halen ?
Alıntı yapılan: Allegro - 20 Nisan 2018, 12:14:51şema keşfedilmedi mi halen ?
var üstad ama ben işteyim eve gecince aksam koyabilirim anca
Ben basic de kod yazarım örnek de basic'e göre verebilirim. Ama kolaylıkla adapte edilebilir sanırım.
Sıklıkla kullandığım şekil aşağıdaki şekildedir.
ENCODER:
ESKI=PORTB & %00000011 'PORTB.0 ve PORTB.1 de bağlı olduğunu farzediyorum.
YINE:
YENI=PORTB & %00000011
IF ESKI=YENI THEN YINE
YON=ESKI.Bit0 ^ YENI.Bit1
IF YON=1 THEN
SAYAC=SAYAC+1
IF SAYAC=xxxxx THEN SAYAC=0
ELSE
SAYAC=SAYA-1
IF SAYAC=xxxx THEN SAYAC=0
ENDIF
Nasıl bir encoder kullanıyorsun bilmiyorum. Pot tipi rotary encoder kullanıyor isen Orta uç GND ye bağlanmalı yanlardaki uçlar 4K7 ile Pullup yapılmalıdır. Bu tür encoderler de iki tık arasında encoder bütün çıkışlarını verir. Yani %11-%10-%00-%01 şeklinde her tıkta bu bilgileri gönderir. BU nedenle bir tıkta birden fazla saydırma yapılabilir. Yada tedbir alırsın her tıkta tek saydırma yaptırabilirsin. Tedbir dediğim yalnızca bir konumda iken artırma yada azaltma kabul edersin örnek olarak %11 iken gibi. Bu tür encoderlerin kontakları sürtünen uçlar şeklinde çalıştığı için kısa sürede deforme olabiliyor. Salınım bu sebepten olabilir.
Normal bir encoder kullanıyor isen salınım normal değil encoderde sorun vardır. Yada çıkışları farklıdır. Bunun Artımlı (incremental) , grey code veren çıkışlı olanları var. Skopla çıkışa bakmak en doğrusu.
Ete
Alıntı yapılan: ete - 20 Nisan 2018, 13:02:08Ben basic de kod yazarım örnek de basic'e göre verebilirim. Ama kolaylıkla adapte edilebilir sanırım.
Sıklıkla kullandığım şekil aşağıdaki şekildedir.
ENCODER:
ESKI=PORTB & %00000011 'PORTB.0 ve PORTB.1 de bağlı olduğunu farzediyorum.
YINE:
YENI=PORTB & %00000011
IF ESKI=YENI THEN YINE
YON=ESKI.Bit0 ^ YENI.Bit1
IF YON=1 THEN
SAYAC=SAYAC+1
IF SAYAC=xxxxx THEN SAYAC=0
ELSE
SAYAC=SAYA-1
IF SAYAC=xxxx THEN SAYAC=0
ENDIF
Nasıl bir encoder kullanıyorsun bilmiyorum. Pot tipi rotary encoder kullanıyor isen Orta uç GND ye bağlanmalı yanlardaki uçlar 4K7 ile Pullup yapılmalıdır. Bu tür encoderler de iki tık arasında encoder bütün çıkışlarını verir. Yani %11-%10-%00-%01 şeklinde her tıkta bu bilgileri gönderir. BU nedenle bir tıkta birden fazla saydırma yapılabilir. Yada tedbir alırsın her tıkta tek saydırma yaptırabilirsin. Tedbir dediğim yalnızca bir konumda iken artırma yada azaltma kabul edersin örnek olarak %11 iken gibi. Bu tür encoderlerin kontakları sürtünen uçlar şeklinde çalıştığı için kısa sürede deforme olabiliyor. Salınım bu sebepten olabilir.
Normal bir encoder kullanıyor isen salınım normal değil encoderde sorun vardır. Yada çıkışları farklıdır. Bunun Artımlı (incremental) , grey code veren çıkışlı olanları var. Skopla çıkışa bakmak en doğrusu.
Ete
abi benim kodum da şu şekilde
rb_kesmesi
yenia=input(port_b4)
yenib=input(port_b5)
yön=yenia^eskib
yenia=eskia
yenib=eskib
enkoder olarak hall sensorlü salınım vs yok lojik analizör cıkıslarına baktım cok temiz kare dalga var sorun yön bilgisi sabit kalmıyor enkoder döndükce 0 ile 1 arası değişiyor sürekli yön değişkenini sabitliyemedim sanırım algoritmada eksiklik var.
Merhaba, altaki kodu kendine göre uyarlayabilirsin.
Kolay gelsin
Mehmet
hardware.h icerigi.
// Rotary encoder
#define RE_A RB6
#define RE_B RB7
#define SWITCH0 RA2
// The following setting sets the speed of the timer0
// interrupt
#define TMR0_SPEED 0x00
// Overall hardware state
struct hardwareState {
// Internal counters
unsigned char pwmCounter;
int dimCounter;
// Rotary Encoder position
int encoderPosition;
unsigned char encoderState;
unsigned char encoderPreviousState;
int encoderDirection;
// Push button
unsigned char buttonState;
unsigned char buttonDebounce;
} hardware;
main icindeki kullanımı.
// High priority interrupt procedure
void interrupt()
{
if (RBIF)
{
// Rotary encoder -------------------------------------------------------------------------
hardware.encoderState = RB6 | RB7 << 1;
if(hardware.encoderPreviousState != 0xFF) // Check for first time check
{
if(hardware.encoderPreviousState == 0b00 && hardware.encoderState == 0b01)
{
// Going counter-clockwise
hardware.encoderDirection = -1;
hardware.encoderPosition--;
}
else if(hardware.encoderPreviousState == 0b01 && hardware.encoderState == 0b00)
{
// Going clockwise
hardware.encoderDirection = 1;
hardware.encoderPosition++;
}
}
// Save the current state
hardware.encoderPreviousState = hardware.encoderState;
// Our encoder has 24 ticks per rotation
if (hardware.encoderPosition > 23) hardware.encoderPosition = 0;
if (hardware.encoderPosition < 0) hardware.encoderPosition = 23;
RBIF_bit=0; // Clear the portB interrupt flag
} // if (RBIF)
}
Alıntı yapılan: M_B - 20 Nisan 2018, 14:06:23Merhaba, altaki kodu kendine göre uyarlayabilirsin.
Kolay gelsin
Mehmet
hardware.h icerigi.
// Rotary encoder
#define RE_A RB6
#define RE_B RB7
#define SWITCH0 RA2
// The following setting sets the speed of the timer0
// interrupt
#define TMR0_SPEED 0x00
// Overall hardware state
struct hardwareState {
// Internal counters
unsigned char pwmCounter;
int dimCounter;
// Rotary Encoder position
int encoderPosition;
unsigned char encoderState;
unsigned char encoderPreviousState;
int encoderDirection;
// Push button
unsigned char buttonState;
unsigned char buttonDebounce;
} hardware;
main icindeki kullanımı.
// High priority interrupt procedure
void interrupt()
{
if (RBIF)
{
// Rotary encoder -------------------------------------------------------------------------
hardware.encoderState = RB6 | RB7 << 1;
if(hardware.encoderPreviousState != 0xFF) // Check for first time check
{
if(hardware.encoderPreviousState == 0b00 && hardware.encoderState == 0b01)
{
// Going counter-clockwise
hardware.encoderDirection = -1;
hardware.encoderPosition--;
}
else if(hardware.encoderPreviousState == 0b01 && hardware.encoderState == 0b00)
{
// Going clockwise
hardware.encoderDirection = 1;
hardware.encoderPosition++;
}
}
// Save the current state
hardware.encoderPreviousState = hardware.encoderState;
// Our encoder has 24 ticks per rotation
if (hardware.encoderPosition > 23) hardware.encoderPosition = 0;
if (hardware.encoderPosition < 0) hardware.encoderPosition = 23;
RBIF_bit=0; // Clear the portB interrupt flag
} // if (RBIF)
}
bu kodda yön ile ilgi kısım neresi üstad?
Kesme kullanıyorsan kodu biraz daha hızlandırabilirsin. Mantıken düşünürsen en son kesme oluştuğunda almış olduğun YENI değerin bir sonraki kesmenin ESKI değeri olabilir ki öyledir zaten.
Kullandığın mantık kesme olmayan işler için iki defa okuma yaptırıyorsun.
rb kesmesi neye karşılık geliyor pek anlamadım ama muhtemelen PortB değişiklik kesmesidir. Zira INT kesmesi ile bu iş olmaz. İki pin bağlı ve iki pinden herhangi birisi kesme oluşturabilmelidir.
Sana Eski okumanın Eski_a sı ve Yeni okumanın da Yeni_b si lazım aslında diğerleri ile uğraşma.
Bu durumda ben olsam şöyle yapardım;
Kod Seç
rb_kesmesi
yenia=input(port_b4)
yenib=input(port_b5)
yön=yenia^eskib
Burada sayc değerini yöne bağlı artır yada eksil ve kesmeden çıkmadan önce de,
Eskia=Yenia
Eksib=Yenib
şeklinde yazıp kesmeden çık. Böylece bir sonraki kesmede encoder mutlaka konum değiştirmiş olacaktır. Konum değiştirmez ise zaten kesme olmayacaktır.
Çıkışta yeni alınmış değerler eskilere eşitlenir. Birsonraki kesmede okunan yeni değer yeni olarak kabul edilmiş olur.
Ancak hala ne tür bir encoder kullandığını açıklamamışsın. POT tipi mi yoksa motor tipi encodermidir.
Ete
Alıntı yapılan: ete - 20 Nisan 2018, 14:20:24Kesme kullanıyorsan kodu biraz daha hızlandırabilirsin. Mantıken düşünürsen en son kesme oluştuğunda almış olduğun YENI değerin bir sonraki kesmenin ESKI değeri olabilir ki öyledir zaten.
Kullandığın mantık kesme olmayan işler için iki defa okuma yaptırıyorsun.
rb kesmesi neye karşılık geliyor pek anlamadım ama muhtemelen PortB değişiklik kesmesidir. Zira INT kesmesi ile bu iş olmaz. İki pin bağlı ve iki pinden herhangi birisi kesme oluşturabilmelidir.
Sana Eski okumanın Eski_a sı ve Yeni okumanın da Yeni_b si lazım aslında diğerleri ile uğraşma.
Bu durumda ben olsam şöyle yapardım;
Kod Seç
rb_kesmesi
yenia=input(port_b4)
yenib=input(port_b5)
yön=yenia^eskib
Burada sayc değerini yöne bağlı artır yada eksil ve kesmeden çıkmadan önce de,
Eskia=Yenia
Eksib=Yenib
şeklinde yazıp kesmeden çık. Böylece bir sonraki kesmede encoder mutlaka konum değiştirmiş olacaktır. Konum değiştirmez ise zaten kesme olmayacaktır.
Çıkışta yeni alınmış değerler eskilere eşitlenir. Birsonraki kesmede okunan yeni değer yeni olarak kabul edilmiş olur.
Ancak hala ne tür bir encoder kullandığını açıklamamışsın. POT tipi mi yoksa motor tipi encodermidir.
Ete
portb değişiklik kesmesi erol abi enkoder motora baglı hall sensorlü enkoder sayac artıyorum motor saga dönerken sola dönerkende azaltıyorum burda sorun yok sorun yön değişkeni stabil deil motordan a ve b sinyalleri gelirken yön 0 ile 1 arasında değişiyor motor saga dönerken örnek yön değişkeni 1 olması gerekirken 0 ile 1 arasında devamlı değişiyor sabit kalmıyor.
Alıntı yapılan: bulut_01 - 20 Nisan 2018, 14:14:30bu kodda yön ile ilgi kısım neresi üstad?
encoderDirection
// Going counter-clockwise
hardware.encoderDirection = -1;
ve
// Going clockwise
hardware.encoderDirection = 1;
Alıntı yapılan: M_B - 20 Nisan 2018, 14:32:44encoderDirection
// Going counter-clockwise
hardware.encoderDirection = -1;
ve
// Going clockwise
hardware.encoderDirection = 1;
bu koddan bişey anlamadım üstad.
sorunu çözdüm bütün yardımcı olan arkadaslara tşk ederim saolun
problem enkoder b fazının yolu çatlakmıs iletmemesinden kaynaklanıyormus.