Yarın bakalım. Yattım artık. Bu hafta sabahçıyım. 7 de kalkıcam.ben millis komutundan şüphelendim ama earlephilhower abi şu şekilde yazmış bunları.
16484 eklentisine bak
/// Rotary Encoder Fonksiyonu /////////////
void encoder(int ifSay, float carpan, boolean clk, boolean dt){
if (millis() - oncekiZaman > 1) {
if (clk != oncekiDurum) {
if (clk == LOW) {
if (dt == HIGH) {
kursorSayac++;
if (kursorSayac <= ifSay || kursorSayac >= 0) {
voltaj_akim = kursorSayac * carpan;
Serial.print(kursorSayac);
Serial.println(" : sag");
}
} else {
kursorSayac--;
if (kursorSayac <= ifSay || kursorSayac >= 0) {
voltaj_akim = kursorSayac * carpan;
Serial.print(kursorSayac);
Serial.println(" : sol");
}
}
}
}
oncekiDurum = clk;
oncekiZaman = millis();
}
}
/// Rotary Enkoder İle İşlem Yapma /////////////
if (kursor_konum == 0) {
encoder(3,10.0,b,a);
} else if (kursor_konum == 1) {
encoder(9,1.0,b,a);
} else if (kursor_konum == 2) {
encoder(9,0.1,b,a);
} else if (kursor_konum == 3) {
encoder(9,0.01,b,a);
}
acaba interrput kullanma zamanımız geldi mi.Enkoder kodlarını fonksiyon içine alıp kursor adımına göre işlem yaptırmak istedim.
Ama hem doğru atlamıyor, hem ilk haneyi 30v'u aşmaması için 3 ile sınırlandırmama rağmen 4-5-6 diye gidiyor, hemde yan rakama atladığımda ilk rakamı sıfırlıyor. Böyle parça parça uğraşınca odaklanamıyorum. Kodda benim görmediğim bir sıkıntı var mı?
Kod:/// Rotary Encoder Fonksiyonu ///////////// void encoder(int ifSay, float carpan, boolean clk, boolean dt){ if (millis() - oncekiZaman > 1) { if (clk != oncekiDurum) { if (clk == LOW) { if (dt == HIGH) { kursorSayac++; if (kursorSayac <= ifSay || kursorSayac >= 0) { voltaj_akim = kursorSayac * carpan; Serial.print(kursorSayac); Serial.println(" : sag"); } } else { kursorSayac--; if (kursorSayac <= ifSay || kursorSayac >= 0) { voltaj_akim = kursorSayac * carpan; Serial.print(kursorSayac); Serial.println(" : sol"); } } } } oncekiDurum = clk; oncekiZaman = millis(); } } /// Rotary Enkoder İle İşlem Yapma ///////////// if (kursor_konum == 0) { encoder(3,10.0,b,a); } else if (kursor_konum == 1) { encoder(9,1.0,b,a); } else if (kursor_konum == 2) { encoder(9,0.1,b,a); } else if (kursor_konum == 3) { encoder(9,0.01,b,a); }
loop içinde sadece 70ms delay var. onarda if koşulu sağlanırsa çalışıyor. Çok etki edeceğini sanmam. interrput kullanmayı bilmiyorum. Önce bi ne olduğunu anlamam lazım.acaba interrput kullanma zamanımız geldi mi.
senin program içindeki delaylar sapıtttırıyor sanırım intterpt kullanırsak enkoderi döndürüğümüzde kesip saydırıp devam eder
benimde bir yandan pico ile nası kullandığını öğrenmem lazım.loop içinde sadece 70ms delay var. onarda if koşulu sağlanırsa çalışıyor. Çok etki edeceğini sanmam. interrput kullanmayı bilmiyorum. Önce bi ne olduğunu anlamam lazım.
Anladım ama benim programıma göre delayı kesmesi de sıkıntı olabilir. Detaylı bakmak lazım.benimde bir yandan pico ile nası kullandığını öğrenmem lazım.
şöyle özet geçeyim picoyu boşver 328 ile çalışıyoruz 2. çekirdek falan yok
yazdın 20 saniye delay 20 saniye dolana kadar başka bir işlem yapamazssın mecbur o delayı tamamlayacak.
birde butonun var butona ne zaman basacağın belli değil basınca bir led yanıyor ve basar basmaz yansın istiyorsun ama program içinde 20 saniye beklemen var.
butonu bir intterpt pininden okuyup interrpt olarak okuma yaparsan 20 saniye delayın içindeyken interrpt tetiklenirse delayı bırakır gider interrpt'da işlem yapar geri gelir
Bunu ben kullandığım kadarıyla bu şekilde öğrendim daha başka detayları varsa bilmiyorumAnladım ama benim programıma göre delayı kesmesi de sıkıntı olabilir. Detaylı bakmak lazım.
if (kursorSayac <= ifSay || kursorSayac >= 0) {
Evet. iki koşulunda sağlanması lazım. (OR)a da yanılmışımBurada OR (||) yerine and (&&) olması gerekiyor gibime geldi.
Sayın @Gokrtl, rotary encoder uygulamasını bir nevi USB, UART, SPI, I2C haberleşmesi gibi düşünün. Meydana gelmiş bir hareket rotary encoder vasıtasıyla dijital bir dataya dönüştürülüyor. Doğal olarak da bu dijital datanın okunabilirliği CLOCK palsinin varlığına bağlı... CLOCK palsinin başka herhangi bir kesintiye maruz kalmadan takip edilmesi şart; bunun yolu da bir donanım kesmesi yani interrupt kullanmak... Ancak bu sayede CLOCK palsi uygulandığında DATA pininin durumu sağlıklı olarak okunabilir. Çünkü encoder yoluyla DATA pini hızla değişebilir, bu değişim elde etmek istediğiniz sonucu belirsizleştirir.Anladım ama benim programıma göre delayı kesmesi de sıkıntı olabilir. Detaylı bakmak lazım.
void encoder(int ifSay, float carpan, boolean clk, boolean dt, float basamakBir, float basamakIki, float basamakUc, float basamakDort){
if (millis() - oncekiZaman > 1) {
if (clk != oncekiDurum) {
if (clk == LOW) {
if (dt == HIGH) {
kursorSayac++;
if (kursorSayac <= ifSay && kursorSayac >= 0) {
voltaj_akim = kursorSayac * carpan;
voltaj_akim = basamakBir * 10.0 + basamakIki * 1.0 + basamakUc * 0.1 + basamakDort * 0.01;
Serial.print(kursorSayac);
Serial.println(" : sag");
}
} else {
kursorSayac--;
if (kursorSayac <= ifSay && kursorSayac >= 0) {
voltaj_akim = kursorSayac * carpan;
voltaj_akim = basamakBir * 10.0 + basamakIki * 1.0 + basamakUc * 0.1 + basamakDort * 0.01;
Serial.print(kursorSayac);
Serial.println(" : sol");
}
}
}
}
oncekiDurum = clk;
oncekiZaman = millis();
}
}
Tamam ozaman yarın bu interrupt ile ilgili biraz video izleyeyim. Madem şart oldu, öğrenelim.Sayın @Gokrtl, rotary encoder uygulamasını bir nevi USB, UART, SPI, I2C haberleşmesi gibi düşünün. Meydana gelmiş bir hareket rotary encoder vasıtasıyla dijital bir dataya dönüştürülüyor. Doğal olarak da bu dijital datanın okunabilirliği CLOCK palsinin varlığına bağlı... CLOCK palsinin başka herhangi bir kesintiye maruz kalmadan takip edilmesi şart; bunun yolu da bir donanım kesmesi yani interrupt kullanmak... Ancak bu sayede CLOCK palsi uygulandığında DATA pininin durumu sağlıklı olarak okunabilir. Çünkü encoder yoluyla DATA pini hızla değişebilir, bu değişim elde etmek istediğiniz sonucu belirsizleştirir.
İnterrupt ile kesilen akışa hızla dönmeyi sağlayacak bir kod yapısı, sizin ana programınızda işleyen delay i soruna uğratmayacaktır.
Redmi Note 8 Pro cihazımdan Tapatalk kullanılarak gönderildi
Bak ben onun bu gün linkine bakacaktım unuttum yav.@Gokrtl earlephilhower abim bunu da yapmış çok kral adam ya.
Bak ben onun bu gün linkine bakacaktım unuttum yav.
attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T> userFunc, PinStatus mode, T& param)
attachInterrupt(digitalPinToInterrupt(2), gireceği void adı, ne durumda kesecği);
Bu gün biraz inceledim. Arduino için gerçekten kolay görünüyor. Aynı senşn yazdığın koddaki gibi.Kod:attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T> userFunc, PinStatus mode, T& param)
Böyle bir kullanımı var ama kafamı karıştırdı bu şekil
Ben bunu 328 için yazarken interrupt olarak kullandığım pini kesme olacağında gireceği voidi hangi koşulda keseceğini yazıyordum(0 olunca ,1 olunca, değişince, yükselen kenar,düşen kenar olunca vs.)
328 örn
Kod:attachInterrupt(digitalPinToInterrupt(2), gireceği void adı, ne durumda kesecği);
dur abi nereye daha interupt kestirecektikNeyse sen bir kurda linuxu. Zamanla ne demek istediğimi anlayacaksın. Bende bir virtualbox a kurayım bari. Sayende depreşti linux duygularım yine. Azıcık kurcalayayım.
O iş cepte.dur abi nereye daha interupt kestirecektik
Sayın @Gokrtl Interrupt vasıtasıyla bir Rotary Encoder uygulamasına örnek olmak üzere aşağıdaki kodları hazırladım.Tamam ozaman yarın bu interrupt ile ilgili biraz video izleyeyim. Madem şart oldu, öğrenelim.
int RE_B = 7; //(DATA Pini Olarak:) Arduino UNO'nun 7. Pinini Rotary Encoder'ın B Pinine Atadık
int RE_A = 2; //(CLK Pini Olarak:) Arduino UNO'nun 2. Pinini (0 Nolu Yani 1. İnterrupt Pinini) Rotary Encoder'ın A Pinine Atadık
int RE_Bt = 3; // Arduino UNO'nun 3. Pinini (1 Nolu Yani 2. İnterrupt Pinini) Rotary Encoder'ın Button Pinine Atadık
int PinB; //PinB RE_B Pininin Durumunu Kaydetmek İçin PinB Değişkenini Tanımladık
int Sayac1 = 0; //Rotary Encder Buttonu'nun Hareketini Saymak İçin Sayac1 Değişkenini Tanımladık
int Sayac = 0; //Rotary Encder Dönüş Hareketini Saymak İçin Sayac Değişkenini Tanımladık
int DebounceSuresi = 100;
String Yon="Bos"; //Rotary Encder Dönüş Yönünü Belirlemek İçin Yon Değişkenini Tanımladık
boolean Oldu = 0; //Kesme Meydana Gelip Gelmediği Bilgisini Bazı İşlemlerde Kullanmak Üzere Tutmak İçin "Oldu" Değişkenini Tanımnladık
void setup() {
cli();//Kurulum Tamamlanana Kadar Tüm Interrupt'ları Durdurduk
pinMode (RE_A,INPUT_PULLUP); //RE_A Pinini INPUT ve PULLUP Olarak Ayarladık
pinMode (RE_B,INPUT_PULLUP); //RE_B Pinini INPUT ve PULLUP Olarak Ayarladık
pinMode (RE_Bt,INPUT_PULLUP); //RE_Bt Pinini INPUT ve PULLUP Olarak Ayarladık
attachInterrupt(0, Encoding, FALLING);
//Arduino UNO 2. Pinine Bağlı 0 Nolu Interrupt'a Encoding Fonksiyonunu Atadık. Kesme Tetiklenince Bu Fonksiyona Dallanacak
//Pin PULLUP Olarak Ayarlandığı İçin FALLING İle Sinyalin GND'ye Çekildiğinde Kesmenin Aktif Olmasını Ayarladık
attachInterrupt(1, Bt_Pushed, FALLING);
//Arduino UNO 3. Pinine Bağlı 1 Nolu Interrupt'a Bt_Pushed Fonksiyonunu Atadık. Kesme Tetiklenince Bu Fonksiyona Dallanacak
//Pin PULLUP Olarak Ayarlandığı İçin FALLING İle Sinyalin GND'ye Çekildiğinde Kesmenin Aktif Olmasını Ayarladık
Serial.begin (9600);
//Burada Değişkenlerimizin Taşıdıkları Değerleri Herhangi Bir Kesme Meydana Gelinceye Kadar Gözleyebilmemiz İçin Kontrol Amacıyla Ekrana Yazdırıyoruz
Serial.print(Yon);
Serial.print("; Sayac: ");
Serial.println(Sayac);
Serial.print("Button: ");
Serial.println(Sayac1);
sei();//Kurulum Tamamlandığı İçin Tüm Interrupt'ları Aktive Ettik
}
void Encoding(){//0 Nolu Interrupt Arduino UNO 2. Pinindeki Sinyalin GND'ye Çekilmesiyle Tetiklendi ve Buraya Dallandı
cli(); //Bu Interrupt İçindeki İşlemleri Tamamlayana Kadar Yeni bir Interrupt Meydana Gelmemesi İçin Tüm Interrupt'ları Durdurduk
PinB=digitalRead(RE_B); //Kesme Meydana Geldiği Anda DATA Pini Durumunu Bu Komutla PinB Değişkenine Atadık
//Rotary Encoder Herbir Tık Hareketinde CLK (Yani A Pini) ve DATA (Yani B Pini) Pinlerini Sıralı Olarak Tetikler.
//Bu Pinler Tıpkı Binary Sayılar Gibi 0 (LOW) ve 1 (HIGH) Durumlar Aldığı İçin 2 Bitlik/Basamaklı BINARY Bir Sayı Gibi Okunabilir
//Soldan İlk Bit/Basamak CLK Pini ve Diğer Bit/Basamak DATA Pini Değerini Tutar
//Pinler PULLUP Olduğu İçin Kesme Öncesi İlk Durumlarının Karşılığı 11 Olacaktır. CLK Pini GND'ye Çekildiğinde Interrupt Tetiklenir
//Encoder'in SAĞ'a (Saat Yönünde) Dönüşünde:
/*------------------------------
0- CLK: 1, DATA: 1 => BINARY: 11 Burası Kesme Meydana Gelmeden Hemen Önceki Durum
1- CLK: 0, DATA: 1 => BINARY: 01 Burası Kesme Meydana Geldiği Andaki Durum
2- CLK: 0, DATA: 0 => BINARY: 00
3- CLK: 1, DATA: 0 => BINARY: 10
4- CLK: 1, DATA: 1 => BINARY: 11
--------------------------------*/
//Şeklindeki Akışla Bir Tık Tamamlanır
//Encoder'in SOL'a (Saatin Tersi Yönde) Dönüşünde:
/*------------------------------
0- CLK: 1, DATA: 1 => BINARY: 11
1- CLK: 1, DATA: 0 => BINARY: 10 Burası Kesme Meydana Gelmeden Hemen Önceki Durum
2- CLK: 0, DATA: 0 => BINARY: 00 Burası Kesme Meydana Geldiği Andaki Durum
3- CLK: 0, DATA: 1 => BINARY: 01
4- CLK: 1, DATA: 1 => BINARY: 11
--------------------------------*/
//Şeklindeki Akışla Bir Tık Tamamlanır
//Bu Tetikleme Esnasında Pinlerin Birbirbiri İle Olan Durumlarına Göre Dönüş Yönünü Belirlenir.
//Interrupt, CLK Pininin LOW'a Çekilmesiyle Tetikleneceğinden Yukarıdaki BINARY Verilerden CLK Pininin 0'a Döndüğü Anlar Kesmenin Meydana Geldiği Anlar Olacaktır.
//***** EĞER Interrupt FALLING Yerine RISING Olarak Yani CLK Pininin LOW'dan HIGH'a (0'dan 1'e) Döndüğünde Tetiklenecek Olsaydı Bu Akışlar Tersine Dönecekti.*****
//Buna Göre:
//SAĞ Yönde CLK Pininin 1'den 0'a Dönmesiyle Kesmenin Tetiklendiği 1. Durumda DATA Pininin 1
//SOL Yönde CLK Pininin 1'den 0'a Dönmesiyle Kesmenin Tetiklendiği 2. Durumda DATA Pininin 0 Değerinde Olduğu Görülecektir.
//CLK Pininin 1'den 0'a Dönüşü Kesmeyi Tetiklerken DATA Pininin 1 veya 0 Oluşu Dönüş Yönünü Göstermektedir
//Biz de Aşağıdaki IF-ELSE Yapısı İle DATA Pininin İki Durumunu Karşılaştırarak Dönüş Yönünü Tespit Edecğiz
if (PinB) {
Yon="Sag"; //PinB Kesme Anında 1 Durumunda İSE Dönüşün SAĞ Yönde Olduğunu Tespit Ediyoruz
Sayac++; //PinB Kesme Anında 1 Durumunda İSE Sayac Değişkenini Artırıyoruz
} else {
Yon="Sol"; //PinB Kesme Anında 1 Durumunda DEĞİL İSE Dönüşün SOL Yönde Olduğunu Tespit Ediyoruz
Sayac--; //PinB Kesme Anında 1 Durumunda DEĞİL İSE Sayac Değişkenini Azaltıyoruz
}
delay(DebounceSuresi); //Kesmeye Kontrolümüz Dışında Fazla Kesme Meydana Gelmemesi İçin Bir Nevi Yazılımsal Bir DEBOUNCE Uyguluyoruz
Oldu = 1; //Kesme Olduğu Bilgisini Değişkene Atadık
sei(); //İşlemler Tamamlandığı İçin Yeni Interrupt Beklemek Üzere Tüm Interrupt'ları Aktive Ettik
}
void Bt_Pushed(){//1 Nolu Interrupt Arduino UNO 3. Pinindeki Sinyalin GND'ye Çekilmesiyle Tetiklendi
cli(); //Bu Interrupt İçindeki İşlemleri Tamamlayana Kadar Yeni bir Interrupt Meydana Gelmemesi İçin Tüm Interrupt'ları Durdurduk
Sayac1+=1; //Rotary Encoder Button'u Kullanılarak İle Sayac1 Değişkenini Artırıyoruz
delay(DebounceSuresi); //Kesmeye Kontrolümüz Dışında Fazla Kesme Meydana Gelmemesi İçin Bir Nevi Yazılımsal Bir DEBOUNCE Uyguluyoruz
Oldu = 1; //Kesme Olduğu Bilgisini Değişkene Atadık
sei(); //İşlemleri Tamamlandığı İçin Yeni Interrupt Beklemek Üzere Tüm Interrupt'ları Aktive Ettik
}
void loop() {
if (Oldu) {//Kesme Oldu İse Verilerimizde Değişiklik Meydana Geleceğinden Verileri Bu Durumda Yazdırıyoruz
// Böylece Serial Ekrandan Sürekli Bir Akış Nedeniyle Anormallikleri Kaçırmış Olmayacağız
Serial.print(Yon);
Serial.print("; Sayac: ");
Serial.println(Sayac);
Serial.print("Button: ");
Serial.println(Sayac1);
Oldu = 0; //En Son Kesme Nedeniyele Verilerimizde Meydan Gelen Değişikliği Ekrana Yazdık Yeni Bir Değişikliğe Kadar Ekrana
//Veri Yazmamak İçin Kontrol Değişkenini Değiştiriyoruz
}
}