Pic Kontrolörde, Tact Buton Okumaları İçin, Tavsiyeye ihtiyacım var.

Başlatan picmanya, 17 Haziran 2024, 23:10:43

picmanya

Pic kontrolör kullanarak, pcb üzerindeki;  6 adet tact buton ve 4 digit seven segment display ile, bir menü programı yapmam gerekiyor.
 
Programda çeşitli değişkenlerin içeriğini (10 adet int tipinde değişken var.), butonlarla displayden görerek, değiştirmem-ayarlamam gerekiyor.

4 digit displeyi, timeri ayarlayarak, timer kesmesi aracılığıyla, tarama şeklinde digit-digit sürekli sürmeyi planlıyorum.

Butonları 2 şekilde okuyabilirim;

1-) main() içindeki while() döngüsü içerisinde, normal port girişleri olarak algılayıp-okumak. (kesmesiz olarak butonları okuma.)
2-) CN Giriş Pin Interrupt-Kesmesi ile; Giriş pinlerini bir kesme ile, main() dışında bir kesme fonksiyonunu içinde okuyup işlemleri, kesme içinde yapmak. (kesme içinde butonları işlemek.)

Buton girişlerini okumak için, hangisini kullanmalıyım. Bu türden bir işte hangi yöntemi kullanmak gerekir. Kısaca butonlar kesme ilemi,  yoksa normal olarak mı okunup-değerlendirilse iyi oluyor.

sifirzero

sifirzero.blogspot.com [email]sifirrzero@gmail.com[/email] iman hem nurdur hem kuvvettir

picmanya

Güzel uygulama yapmışsınız. Bu türden bir çalışma yapmak için, bundan kısa ve öz olanı da pek mümkün olmaz herhalde.
Herşey tıkır tıkır yerinde okunaklı ve sade olmuş.

Yalnız ben display sürmeyi sormamıştım.! Pcb mi kısaca özetleyerek,
Butonları nasıl okumalıyım, buton kodlarını nereye yazmalıyım diye sormuştum.!
Butonlar kesmeli ve kesmesiz okunup değerlendirilebiliyor. Hangisini yapmak gerekir demek istemiştim.

Tagli

Bouncing (zıplama?) problemi olduğu için normalde butonları kesmeye bağlamak iyi bir fikir değil. Bence bu konudaki en doğru yöntem bir timer kesmesi içinde butonları hızlıca okuyup sonra da butonun değerine karar vermek için bu okumalar içinde oy birliğine bakmak.

Okuma ne kadar sık olmalı emin değilim, epeydir buton uygulaması yapmadım ama ben olsam 1 ms periyodla başlardım. Bu süre uzatılabilir ama daha kısası işlemci için yorucu olacaktır. Her buton için uint8_t bir değişken oluşturup, her yeni okumayı bu değişkenin bir ucuna ekleyip sonra da 1 bit kaydırma yapardım. Değişken 0 ise buton 0, 0xff ise buton 1 demektir. Diğer değerleri bouncing durumunu göstereceği için göz ardı ederdim.
Gökçe Tağlıoğlu

picmanya

Ufak çaplı başlangıç denemesi yaparken; Buton okumalarının başına 1-2 msn. gecikme vererek, bubouncing problemini aşmayı başarabildim. Butona çıkışına kondansatör bağlamakda iş görebiliyor.
Siz buton giriş kesmesini öenrmiyorsunuz. timer kesmesi içinde butonları sürekli okurken butona tek tıklamalı veya sürekli basılı tutmayı halletmek zor oluyormu? Tek tıklamalı buton okumak,
görebildiğim kadarıyla, kesme girişleri ile iyi oluyor gibi duruyor. Buton basılı kalsada problem olmuyor. Yalnız butona uzun süre sürekli basıldığınıda anlamak gerekebiliyor budurumda hangi yöntem avantajlı olur.?

hasankara

Belki işine yarayabilir esp32 de çalışan bir kod. Normalde hem timer kesmesi, hem de input kesmesi ile kullanılabilecek şekilde yazdığım bir kod, yalnız esp32 kaynaklı bir problemden dolayı input kesmesi sürekli hatalı sonuç sebep oluyor, zaten daha önceleri başkalarınında mcu kaynaklı bu problemi duyduğum için üzerinde durmayıp yalnız timer ile çalışacak şekilde kullandım.

Özünde state machine bulunan bir kod bloğu ve iki buton gibi mcu a bağlanan rotary encoder handle ediyor.
int deb_cnt,deb_stt;
/* state 0->1->2->3 ise arttirilir*/
/* state 3->2->1->0 ise arttirilir*/
static uint8_t rtr_pos[4] = {1, 3, 0, 2};
//uint8_t rtr_neg[4] = { 3, 0, 2, 1 };
static uint8_t rtr_neg[4] = {2, 0, 3, 1};
int32_t inp_taps[inp_max];
int32_t inp_stt[inp_max];
uint16_t rtr_stt;

int32_t rtr_val;
uint32_t us10_cnt;

static void   inputCallback(void* arg){

	if(deb_stt > 0 && deb_cnt++ < 10 )return;

	deb_stt = 0;
	deb_cnt = 0;
	uint32_t gpio_num;
	for (int i = 0; i < inp_max; i++)
	{
		gpio_num = inp_nums[i];
		/* result touch vals processing*/
		switch (inp_stt[i])
		{
			/* unpressed state*/
		case 0:
			if (!gpio_get_level(gpio_num))
			{
				inp_stt[i] = 1;
				inp_taps[i]++;
				deb_stt++;
				xEventGroupSetBits(InputEvents, gpio_num);
			}
			break;
			/* pressed state*/
		case 1:

			/* shut down sayaci resetlenir*/
			t_base_sdown = time_cnt;
			if (gpio_get_level(gpio_num))
			{
				inp_stt[i] = 0;
				deb_stt++;
				xEventGroupSetBits(InputEvents, gpio_num);
			}
			break;
		}
	}
	/* rotary encoder yon takibi yapilir*/
	rtr_stt = ((inp_stt[inp_rtr_prev] & 1) << 1) | (inp_stt[inp_rtr_next] & 1);
	if (rtr_stt_old != rtr_stt)
	{
		if (rtr_pos[rtr_stt_old] == rtr_stt)
		{
			rtr_val++;
		}
		else if (rtr_neg[rtr_stt_old] == rtr_stt)
		{
			rtr_val--;
		}
		else{
			rtr_val=0;
		}
		rtr_stt_old = rtr_stt;

	}
}

static void  deb_tick_task(void *arg)
{
	_enter_critical_fnc();
	us10_cnt++;
	inputCallback(0);
	_exit_critical_fnc();
}

M.Salim GÜLLÜCE

Button okumada bouncing problemini aşmayı donanımsal olarak halletmelisin.
Butonlar Pozitif mi negatifmi kontaklı olacak ona göre tasarlayabilirsin.
Hatta 2x3 mux okuyabilirsinki bir çok sistemde (Daha fazla buton durumunda) kullanılan bir yöntem.
Nasıl olsa 4 diğit Display çıktısı çıkışı veriyorsun. Oradaki çıkışlardan geridönüş okuyarak hangi butonun basıldığını 2 pin üzerinden okuyabilirsin. Ayrıca zaman kaybına da gerek kalmaz.
İyi bir algoritmayla işlemciyi de yormadan halletmiş olursun.








Bu 3 ünü birleştir melez bir keyboard ve display ortak giriş çıkış kullan.

picmanya

Salim Hocam,
Devrem kurulu belirli bir aşamaya getirdim, sadece birkaç noktası kaldı. Devrenizden notlarımı aldım. Nasipse ileride kullanırız. Güzel bir devre.

Genele şöyle bir sorum var;
Pic mikrokontrolörde, Change Notification (CN) Pinlerin Kesmesi içerisindeyken (kesmeden henüz çıkılmadan önce),
başka bir Timer Interrupt Kesmesi oluşup, program Timer Interrupt kesmenin fonksiyonuna gidip-dallanıp,
buradaki işlemler yapılıp bitirildikten sonra, Tekrar niye henüz tamamlanmayan CN Pinlerin Kesmesi içerisine dönmez.
Bu mümkün değil mi? Mümkünse.! Neyi atlıyor olabilirim? Timer Interruptu, Cn Interruptun içinde oluştuğunda,
Cn Interruptu yarıda bırakıp kaldığı yere geri dönmüyor. Bu saçma bir durum değilmi? İşleyiş nasıl oluyor burada?

Tagli

Hangi PIC modelinden bahsediyoruz? Güncel modelleri takip etmedim ama eski PIC16'larda kesme öncelikleri yoktu. Bu da bir kesmenin işlenmesi bitmeden bir diğerine başlanamayacağı anlamına geliyor. Zaten kesme vektörü de sadece 1 tane idi, yazılımsal dallanma gerekiyordu. Sonradan gelen kesme kaybolmaz, ancak birincinin işlenmesi bittikten sonra işlenir.

Eski PIC18'lerde ise 2 adet kesme önceliği ve 2 adet kesme vektörü vardı, tabi eğer bu özellik etkinleştirilirse. Bunlarda yüksek öncelikli bir kesmenin düşük öncelikli bir kesmeyi kesmesi mümkün.

Bu arada CN kesmesinin zaten hızlıca bitirilip çıkılması gerekir. Program akışı kesme içinde kesme beklemeye göre tasarlandıysa tasarımda bir hata var demektir.
Gökçe Tağlıoğlu

Okan AKÇA

Sadece timer kesmesi ile halledilir özel bir duruma gerek yok. Timer de sadece görev zamanları belirlenir ana döngüde kontrolleri yapılır.

M.Salim GÜLLÜCE

Alıntı yapılan: picmanya - 18 Haziran 2024, 17:32:52Salim Hocam,
Devrem kurulu belirli bir aşamaya getirdim, sadece birkaç noktası kaldı. Devrenizden notlarımı aldım. Nasipse ileride kullanırız. Güzel bir devre.

Genele şöyle bir sorum var;
Pic mikrokontrolörde, Change Notification (CN) Pinlerin Kesmesi içerisindeyken (kesmeden henüz çıkılmadan önce),
başka bir Timer Interrupt Kesmesi oluşup, program Timer Interrupt kesmenin fonksiyonuna gidip-dallanıp,
buradaki işlemler yapılıp bitirildikten sonra, Tekrar niye henüz tamamlanmayan CN Pinlerin Kesmesi içerisine dönmez.
Bu mümkün değil mi? Mümkünse.! Neyi atlıyor olabilirim? Timer Interruptu, Cn Interruptun içinde oluştuğunda,
Cn Interruptu yarıda bırakıp kaldığı yere geri dönmüyor. Bu saçma bir durum değilmi? İşleyiş nasıl oluyor burada?
Umarım kesme rutininde uzun programlar yazmıyorsunuzdur.
Yeni bir kesme zamanı geldiğinde tekrar kesme rutinine düşeceğinden asla çıkamaz.
O yüzden kesmelerde bazı değerler set edilir çıkılır. Uzun uzun kod yazılmaz. En fazla birkaç formül icra edilir.
Mesela clock tan Saniye yada milisaniye ye indigemek gibi. Milisaniye ataması yapılır çıkılır.
Diğer işlemlerin tamamı ana döngü ve altındaki rutinlerde yapılır.

picmanya

Tagli,
30F ler de durum belirttiğiniz gibi değil. Farklı çalışıyor olmalılar. En yüksek öncelikli kesme içinde en düşük öncelikli kesmede oluşsa ona dallanılıyor.
Belki ayarlamaları vardır, ama defaultunda durum böyle görünüyor. Kesme öncelik sırası, iki kesme aynı anda tetiklendiğinde, öncelik sırası ilk hangisinin fonksiyonuna gidilecek kısmında olabilir belki.

Alıntı yapılan: Okan AKÇA - 19 Haziran 2024, 12:29:16Sadece timer kesmesi ile halledilir özel bir duruma gerek yok. Timer de sadece görev zamanları belirlenir ana döngüde kontrolleri yapılır.
Zaten bir timer kesmesi 4 dijit seven segment dipleyleri sürüyor. CN kesmesini komple bırakıp, ayrı bir timer kesmesi ile butonları oku ve kontrollerini gerçekleştirmi demek istediniz.

Genele
Butona uzun basıldığını, nerede nasıl algılayıp ne yapmam gerekir, işlemler sırasını açıkça anlatacak birisi varmı?
Mevcuttaki haliyle; butonların basıldığının algılanmasının ve tüm kontrollerinin, yalnızca CN kesmesi içinde olduğunuda bilinmesi gerekir.
Şu anda tüm buton işlemleri, yalnızca CN kesmesi içinde bulunuyor. Butona uzun basıldığını nasıl-nerede algılamalıyım? Tane tane anlatılabilirse,
anlatılanları aynen uygulayabilirim. Koda gerek yok, metodu bilmem yeterli olur.

Tagli

Alıntı yapılan: picmanya - 19 Haziran 2024, 12:57:0230F ler de durum belirttiğiniz gibi değil. Farklı çalışıyor olmalılar. En yüksek öncelikli kesme içinde en düşük öncelikli kesmede oluşsa ona dallanılıyor.
Bunun olması mümkün değil. Üzerinden yıllar geçtiği için bilgilerim çok taze olmasa da daha önce dsPIC30F2010 ile çalışmıştım. Farklı kesme öncelikleri ve her bir kesme için ayrı vektör olduğunu hatırlıyorum. Zaten tek çekirdekli hiçbir mimaride düşük öncelikli bir kesme yüksek öncelikli bir kesmeyi kesemez. Önce yüksek öncelikli kesmenin işlenmesinin tamamlanması gerekir.

Alıntı yapılan: picmanya - 19 Haziran 2024, 12:57:02Kesme öncelik sırası, iki kesme aynı anda tetiklendiğinde, öncelik sırası ilk hangisinin fonksiyonuna gidilecek kısmında olabilir belki.
Bu mümkün ancak dsPIC30F'lerde bu özelliğin olup olmadığını veya nasıl çalıştığını hatırlamıyorum. ARM Cortex M'lerde "priority grouping" diye bir kavram var. Uygun şekilde ayarlandığında kesme önceliklerinin, kesmelerin birbirini kesmesinde bir etkisi olmayıp sadece bir sonra işlenecek olan kesmenin hangisi olacağını belirlemede etkili olmasını sağlamak mümkün.


Gökçe Tağlıoğlu

picmanya

Tesadüf bende dsPIC30F2010 ile çalıştığımdan sadece gördüğümü yazdım.
Derleyicim C XC16, düşük öncelikli kesme, büyük öncelikli kesmeyi kesebilir olarak görünüyor.
Belki ayarlamalardan bu isteğe göre düzenleniyor olabilir. Interrupt nesting diye bir ayar falan vardı.
Ayarların fazlasıda varsa, ben bu türden ayarlamalara hiç müdahale etmeden kullandım.
Priority 1-7 arası kesme öncelik sıralamaları var.
Kesmeler hakkindeki bilgiler, genelde eski 8 bit işlemcilerden beri aynı telaffuz ediliyor gibi duruyor.

Çeşitli Varyasyonlar var:
Aynı priortiy kesme derecesine sahip iki kesme, aynı anda tetiklenirse ne olur? (Burda kesin birşey oluyor olmalı. Ama ne olur. Priortiden hariç bunlarında kendi içinde bir hiyararşisi olabilir.)
Yüksek öncelikli kesme içindeyken, düşük öncelikli kesme olursa ne olur? (Benim gördüğüm düşük öncelikli kesmede işleme alınıyor. Yine kendi hiyerarşisi devreye giriyorda olabilir.)
Yüksek öncelikli kesme içindeyken, düşük öncelikli kesme oluşursa dikkate alınmaması için hangi ayara müdahale etmek gerekir?
Tezgahım kurulu, öneri varsa deneyebilirim.

Tagli

Sayısal bir karışıklık veya yanlış anlaşılma olabilir mi? ARM'da örneğin öncelik numarası küçüldükçe öncelik artar. Önceliği 0 olan kesme en yüksek önceliklidir. Belki PIC'te de öyledir, dokümana bir bakmak gerek.

Aynı öncelikli kesmelerin aynı anda gelmesi durumunda genelde vektör numarasına göre içlerinden biri daha yüksek öncelikli kabul edilir.
Gökçe Tağlıoğlu