Arduino ya PS2 TÜRKÇE KLAVYE BAĞLAMA

Daha önce ESP32 ile USB kablosuz HID klavye yazımı yazmıştım.
ESP32_USB HID KLAVYE yazım buradadır. 

Bu yazımda ise Arduino ya ps2 klavye bağlayarak nasıl kullanabiliriz bunu anlatacağım.
Arduino UNO NANO gibi kartlar, HID özellikli HOST özellikli bir kart olmadığı için USB klavye bağlayamıyoruz. Fakat USB klavyeleri PS2 Adaptörlerle, PS2 klavye olarak bağlayabiliyoruz.

Öncelikle donanıma bakalım:
Donanım olarak arduino nano, Dişi ps2 soket, USB klavye kullanacaksanız USB den PS2 ye çevirici adaptör gerekmektedir.
Bu adaptörü kendiniz de yapabilirsiniz sadece kablolama, kolay olsun diye adaptör kullandım. Aşağıda bu adaptörün bağlantı şemasını göreceksiniz. ( bu konuda da tereddüttüm var. Eski USB klavyeler, PS2 olarak da çalışırken, yeni klavyeler USB PS2 ikili çalışmayı desteklemiyor olabilir)

Pin 5 ps2 data pin, pin 6 clock pin

Yukarıda gördüğünüz gibi Arduinoya 2 kablo bağlantısı yetiyor. Diğer 2 kablo ise Klavyenin çalışması için gerekli olan +5V ve GND kablolarıdır. Dişi PS2 soketinin bağlantısı da aşağıdadır. Buna göre bağlamanız gerek. Klavye adaptörü ya da ps2 klavye konektörü ERKEK olarak bağlantı şemasında bakılmalı ve kablolar karıştırılmamalıdır. FEMALE ve MALE olduğuna dikkat edin.

Donanım basit ama dikkat edilmeli. Ayrıca Adaptör ile çalışıyorsanız klavye RESET, programda olmasına rağmen 5V arduinodan alındığı için olabilir KLAVYE arduinoya enerji verildiğinde ledlerini yakamıyor. Sonradan USB klavye kablosunu çıkarıp takarsanız klavye ledleri yanıyor ve klavye çalışmaya başlıyor. Bu arduino nanodan olabilir, usb klavyeden olabilir adaptörle çalıştığı için ama ps2 klavye kullanırsanız sorun olmayabilir. Yani sizde sorun çıkmayabilir.

Kütüphane kullanmayacağı  ben kendim sinyali yakalarım diyorsanız da bu bilgiler lazım olacaktır.
Öncelikle 11 bitlik sinyal göreceksiniz.

1 bit START
8 bit VERİ
1 bit ODD PARITY
1 bit STOP
Olmak üzere 11 bittir. Burada PARITY ODD kullandığımız için Parity kontrol biti verilerdeki 1 olanların toplamına göre hesaplanır. verilerdeki 1 olan bitler çift sayı ise o zaman PARİTY biti =1 durumunda olacaktır. Tek olursa ise PARITY =0 olacaktır. Bu sadece ODD parity kullandığı için.
sonrasında ise stop biti gelmektedir.
Aşağıdaki sinyal, klavye sinyalini göstermektedir. Siz de bu şekilde klavye sinyalini yakalayabilirsiniz. Tarama kodunu elde edebilirsiniz. Tabii ki bir sonraki sinyale bakarak arduinodan klavyeye gidecek olan bilgi içinde çalışma yapmanız lazım. Burada ACK sinyali için ayrı bir inceleme yapmanız lazım.
Kullandığım kütüphane sadece tarama kodunu gösterdiği için zaten bu çalışmayı yapmanıza gerek kalmayacaktır.

Klavyeden gelen sinyal

 

Arduinodan klavyeye gidip gelen sinyaller

 

Programlamaya bakacak olursak.
Bu konuda bir çok kütüphane bulabilirsiniz. Kendiniz de program yapabilirsiniz.
Fakat benim yazımda, bu programlamaya başladığınızda karşınıza çıkacak sorunlara çözüm bulunduğunu göreceksiniz.

Tüm ps2 kütüphanelerinin neredeyse mantığı aynı. Klavye tarama kodlarını alır. Karşılık olarak gelen ASCII kodlarını da bir tablodan alır. Ekrana yazdırır.
Bu yabloda dikkat edilmesi gereken bu tip tablolarda ilk karakterin sıfır dan başlamasıdır. bundan dolayı satır sonunda 31 yazar. 0-31 arası her satırda 32 karakter vardır. 31 yazılmasının sebebi budur. buna göre kaçıncı karakteri değiştirecekseniz onu bulmanız kolay olacaktır. Siz de tarama koduna göre karakter değiştirebilirsiniz. Benim klavyemde (“) işareti bu tabloya göre doğrudur ama ya da virgül işareti doğrudur fakat sizin klavyenizde farklı bir tarama koduna gelebilir. Bu durumda tablodaki o karakteri değiştirip kendinize göre uyarlayabilirsiniz.

"Program adı: ARDUINO PS2 KLAVYE BAĞLAMA ";
char ScancodeToASCII[2][128] = {// 2 farklı dizilim var 127 karakterden oluşur. 
                                // birincisi SHIFT basılmadan. İkincisi ise SHIFT basıldığında okunur. 
  { 0,0,0,0,0,0,0,0,0,0,0,0,0,9,34,0,0,0,0,0,0,113,49,0,0,0,122,115,97,119,50,0,//31 kod
0,99,120,100,101,52,51,0,0,32,118,102,116,114,53,0,0,110,'b',104,103,121,54,0,0,0,109,106,117,55,56,0,//32 kod
0,44,107,0,111,48,57,0,0,46,46,108,148,112,42,0,0,0,132,0,129,45,0,0,0,0,13,43,0,44,0,0,//32 kod
0,60,0,0,0,0,8,0,0,49,0,52,55,0,0,0,48,46,50,53,54,56,27,0,0,43,51,45,42,57,0,0  },// 32 kod
  { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,0,81,33,0,0,0,90,83,65,87,34,0,//31 kod
0,67,88,68,69,36,94,0,0,0,86,70,84,82,37,0,0,78,'B',72,71,89,38,0,0,0,77,74,85,47,40,0,//32 kod
0,59,75,73,79,61,41,0,0,0,58,76,153,80,63,0,0,0,142,0,154,95,0,0,0,0,0,42,0,59,0,0,//32 kod
0,62,0,0,0,0,0,0,0,49,0,52,55,0,0,0,48,46,50,53,54,56,0,0,0,43,51,45,42,57,0,0  } //32 kod
 };

 char altgrcodeToASCII[128] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,'£',0,
  0,0,0,0,0,36,35,0,0,0,0,0,0,0,'½',0,0,0,0,0,0,0,0,0,0,0,0,0,0,123,91,0,
  0,0,0,0,0,125,93,0,0,0,0,0,0,0,92,0,0,0,0,0,0,0,0,0,0,0,0,126,0,92,0,0,
  0,124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 };
// bu karakter tablolarında shift tuşu ile basılma
 shift tuşu olmadan basılma ve ALTGR ile basılma durumunda ekrana gelmesi gereken
 karakterlerin ASCII kodları yer almaktadır.

 

Türkçe karakterleri yazdırmak için UTF-8 kodlarını Serial.Write komutuyla verebilirsiniz.

Tüm mantık bu olsa da Türkçe karakter sorun çıkarabiliyor. Ya da bazıları tarama kodunu vermiyor herşeyi kütüphanede halledip sadece ASCII kodunu veriyor değiştirmek için kütüphanede değişiklik yapmanız gerekiyor.

Bu programda ise kütüphane size sadece tarama kodunu veriyor siz bu kod ile istediğiniz gibi programınızı yapabiliyorsunuz. Daha fazla hakimiyet ve Türkçe karakter gibi diğer dillerdeki standart olmayan karakterleri de yazdırabilirsiniz.
Hatta klavyenizi mesleğe yönelik bir klavye olarak kullanabilirsiniz. Ya da bir OYUN kontrolünde rahatlıkla Klavyeyi kullanabilirsiniz.
Demek istediğim şu. ASCII kod tablosunu siz oluşturuyorsunuz. Bu şekilde ekrana basılabilecek ilk 127 ASCII karakteri ekrana bastırabiliyorsunuz. Şayet istediğiniz karakter Ş gibi Türkçe karakterse ya da Hz gibi bir UNİCODE, UTF-8 karakteri olsun istiyorsanız, bu programla bunu yapabilirsiniz. Diğerleriyle bu zor görünüyor. Ama imkansız değil.

Program üzerinde zaten açıklamaları yaptım ve videoda da açıklamalarını yapacağım. Fakat işin mantığı dediğimizde bunu algılamanız lazım. Sadece tarama kodunu alırım. Tablodan kodu yazdırırım. dediğinizde bu işin bu kadar olmadığını göreceksiniz.
Öncelikle tarama kodlarına bakalım.
Klavyelerde mesela sol CTRL var. Sağ CTRL var. Bu ikisi aynı kodu üretiyorsa O zaman şöyle bir yol bulmuşlar E0 gibi bir kodu öne koyarak Sanki EKSTRA bir kod gibi gösteriliyor.
Bunun yanı sıra Tuşa basıldığında tuş kodu üretiliyor bu kod el kaldırılasıya kadar devam ediyor elinizi kaldırdığınızda bu F0 gibi bir kod ile kullanıcıya bildiriyor. Aynı zamanda E0 ile başlamışsa Tuşu bıraktığımızda E0 bir kez daha geliyor kaldırıldığını gösteriyor.
Tabii ki sadece bu ayrımlar yok. programınızda shift tuşu ayrımı da olacak. SHİFT basılsa da basılmasa da aynı tuş için aynı tarama kodu geliyor. Bundan dolayı shift tuşuna basılmışsa 2. tabloyu kullanarak a yerine A harfi basılıyor.
Sol SHIFT tuşu Hex12 kodunu verirken sağ SHIFT tuşu Hex59 kodunu veriyor. Bunun yanısıra CAPSLOCK basıldığında SHIFT tuşu devamlı basılmış gibi oluyor. Bundan dolayı büyük harf yazdırılıyor. Bunların da ayrılması gerek. Nasıl ayıracağımızı zaten programdan kolaylıkla anlayabileceksiniz.
Bunun yanısıra aynı kodlu tuşlar var dediğim gibi bunların başına E0 koyarak ayırıyor. Bir de tuş birleşimleri var. ALTGR+Q gibi. Benim klavyede @ işareti yapıyor. bu işareti de algılamanız lazım. aşağıdaki resme bakarsanız tarama kodları tek tek geldiği için gelen kod aralarında yeterli zaman gecikmesi olduğundan gelen koda göre program farklı işlevler yapabiliyor. Mesela ALTGR geldi hemen ALTGR değişkenini 1 yapıyor. sonrasında ise basılan karakterin kodu geliyor. Bu karakter bulunuyor. Sonrasında tuştan elimizi çektiğimizde F0 ile bunlar sonlandırılıyor ALTGR de sıfırlanıyor. Siz de bu kod aralarında istediğiniz işlemi yapabiliyorsunuz.

 

burada ALTGR+Q tuş bileşimi görünüyor. her kod geldiğinde o gelen kod işleniyor hazırlık yapılıyor sonrasında gelen karakterde belli olduğunda tablodan hangi karakter geldiyse o ekrana yazılıyor.

Şimdi de Türkçe karakter ya da diğer deyişle Unicode UTF-8 karakterini nasıl yazdırdığımıza bakalım.
Yukarıdaki türkçe karakter tablosundan HEX kodlarını öğrenebilirsiniz

Shift tuşuna basılmadıysa ş harfi basıldıysa Ş harfi yazılır.
Bu başlangıç ekranıdır. ilk satırdaki türkçe karakterler Serial.print ile yazdırıldı. 2. satırdaki ise Serial.write komutu ile türkçe karakter tablosundaki UTF-8 kodu ile yazdırıldı. bunun için komut: Serial.write (0xc5);Serial.write(0x9E); UTF-8 kodu 2 ye ayrılarak arka arkaya verildi.

Bu karakter kodlarına göre Serial.write(0x00);Serial.write(0x01); gibi art arda yolladığınızda bu karakter seri monitöre yazılıyor.
Ya da kod ezberlemeyeceğim derseniz de Serial.print(“Ş”); derseniz de arduino seri monitöre direkt UTF-8 olarak bu karakteri yazabilir. Seri monitör ile çalışırken kolaylık fakat başka bir ekrana yazdırıyorsanız HEX kodlarına ihtiyacınız olabilir. Mesela LCD ekran ise ona Yeni karakter hazırladıysanız O yeni karakterin hex kodunu vermeniz gerekebilir. ya da başka bir monitöre yazıyorsanız HEX kodu gerekebilir.
Bundan dolayı programda test yazısı yazıldığında sizin için 2 farklı yazılım şeklini de ekledim.
Türkçe karakter tarama kodu geldiğinde Tabloya gitmiyor. TURKCE alt programına giderek gelen kodun karşılığını ekrana yazdırıyor. Bunun nedeni ise Türkçe karakterler ASCII kodlamasının ilk 127 karakter içinde değil. Bu karakterler direkt olarak ekrana basılan karakterlerdir. Programın ayrı bir yerinde Türkçe karakter yazdırma alt programı vardır.

Bunun yanısıra NUMLOCK ve CAPSLOK tuşlarına bastınız mı basmandınız mı bunu gösteren LEDLER var. Bu ledlerin SET edilmesi de bu programda var. Bu şekilde numlock tuşuna bastığınızda Numkey değişkeni 1 olur ve Klavyedeki LED’in yanması için gerekli LEDAYAR alt programına giderek ledi yakar. Capslock için ve scroll lock için de bu ledlerin kodları var.

LED durumları 1 bytelık register içinde BİT leri ayarlayarak LED ler yakılıp söndürülüyor.
Bunu Yaparken BİT işlemlerinde Bitclear ve Bitset kullanılıyor. Şayet 1 4 7 gibi byte işlemi yapılsaydı o registerin diğer bitleri de değişecekti. Belki de başka problem olacaktı. Bundan dolayı sadece hangi bitler LED için ayrılmışsa onları değiştiriyoruz.

SCROLLOCK için 0. biti değiştiriyoruz. 0 sönük 1 yanık.
NUMLOCK için 1. biti değiştiriyoruz.
CAPSLOCK için 2. biti değiştiriyoruz.
Benim klavyeme göre bu. Sizler klavyenize göre bunları ayarlayabilirsiniz.

Ayrıca hem KEYPAD dediğimiz numara tuş takımları var hem de buradaki komutların tuşları ayrı olarak var. Mesela PAGE UP gibi ya da YÖN tuşları gibi. Bunlar da Karakter tablosunda yer almaz. Bunları da kod geldiğinde hızlı bir şekilde IF cümleleri ile kontrol eder ve PAGEUP yazar. fakat karakter tablosuna uğramaz. Keypad dediğimiz sağdaki numaraların 2 farklı şekilde kullanımı için NUMLOCK tuşu kontrol edilir. NUMLOCK 0 olduğunda PAGEUP gibi çalışır NUMLOCK 1 olduğunda 1,3 5 gibi numara tuşları çalışır. Hepsinin tarama kodu aynıdır. Fakat NUMLOCK basıldıysa siz bunu programdan ayırt edebiliyorsunuz. Ayrıca bu KEYPAD üzerindeki tuşların aynısı ayrı olarak da klavyede yer alır. PAGEUP veya YÖN tuşları gibi. Bu tuşlarında tarama kodları aynıdır. Fakat bunlar ekstra tuşlar olduğu için diğerlerinden ayrılması için başına E0 konmuştur. Yani kolaylıkla bu tuşları da ayırt edebiliyorsunuz.

Klavyedeki her tuşun tarama koduna göre işlevleri programda mevcut hatta SHIFT, CTRL,ALT,ALTGR tuş bileşimleri de çalışmaktadır. Bunlar bu tip tuşlar geldiğinde, hemen değişkenleri 1 yapılarak IF döngüsünde kontrol edilerek yapılır. Sonrasında TUŞ basılmadığında hepsi sıfırlanır.

Ayrıca Program başında KBD_INIT alt programında bu resetleme yapılıyor. Normalde 1 kez bile yapsanız yeterli ama ben 2 kez yaptırdım sorun olmasın diye.

Bununla birlikte Program içerisinde KARAKTER kodu diye ekrana yazılan yerlerden  tuş kodlarını alıp kendi PS2 bağlantılı programlarınızda kullanabilirsiniz. Tüm bu işlemler Sonsuz FOR işlemi içinde olduğundan sizler buradan karakter aldığınızda kendi alt programınıza gidebilirsiniz. işinizi yapıp tekrar FOR döngüsüne dönmeniz gerekir.
Bunu hızlı bir şekilde yapabilirsiniz.
Klavye 10khz – 16Khz hızında çalışıyor. Arduino 16Mhz hızında çalıştığından işleminizi yapıp geri dönecek süreniz olacaktır.

NOT: Program içerisinde SİZLER tüm ekranı anlayasınız diye bir çok SERİAL.PRINT satırı var. Bundan dolayı hafıza dolabilecektir. Sizler kendi programınıza adapte edecekseniz bu satırları silerek hafızadan kazanabilirsiniz.
Ayrıca Tabloları ise Program hafızasına aşağıdaki örnekteki gibi yerleştirebilirsiniz. O da data hafızasını rahatlatacaktır. Aşağıda kullanılan PROGMEM komutunun kullanılmasına bakmanızı öneririm. Benim programımla alakası yoktur. Hafıza kazanmanız için bir yol olarak verilmiştir.
Bu adreste PROGMEM kullanımı anlatılmaktadır.
Ayrıca yine hafıza kazanmak için Serialprint olarak yazdırılan karakterlerin sabit kısımları
F MACRO ile ÜST belleğe aktarılarak Data kısmından yer açılmış olacaktır.

Bu tip metotlarla  kendi yapacağınız programa eklemeniz daha kolay olacaktır. Program ve Data hafızanızdaki yeri uygun şekilde kullanabilirsiniz. 

"Program adı: örnek tablo_ PROGMEM kodu İsterseniz bu programdaki tabloyu progmem ile Program hafızasına taşıyabilirsiniz. buradaki tablo örnektir benim programımla alakası yoktur. ";
const PROGMEM PS2Keymap_t PS2Keymap_US = {
  // without shift
	{0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12,
	0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '`', 0,
	0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'q', '1', 0,
	0, 0, 'z', 's', 'a', 'w', '2', 0,
	0, 'c', 'x', 'd', 'e', '4', '3', 0,
	0, ' ', 'v', 'f', 't', 'r', '5', 0,
	0, 'n', 'b', 'h', 'g', 'y', '6', 0,
	0, 0, 'm', 'j', 'u', '7', '8', 0,
	0, ',', 'k', 'i', 'o', '0', '9', 0,
	0, '.', '/', 'l', ';', 'p', '-', 0,
	0, 0, '\'', 0, '[', '=', 0, 0,
	0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, ']', 0, '\\', 0, 0,
	0, 0, 0, 0, 0, 0, PS2_BACKSPACE, 0,
	0, '1', 0, '4', '7', 0, 0, 0,
	'0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/,
	PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0,
	0, 0, 0, PS2_F7 },
  // with shift
	{0, PS2_F9, 0, PS2_F5, PS2_F3, PS2_F1, PS2_F2, PS2_F12,
	0, PS2_F10, PS2_F8, PS2_F6, PS2_F4, PS2_TAB, '~', 0,
	0, 0 /*Lalt*/, 0 /*Lshift*/, 0, 0 /*Lctrl*/, 'Q', '!', 0,
	0, 0, 'Z', 'S', 'A', 'W', '@', 0,
	0, 'C', 'X', 'D', 'E', '$', '#', 0,
	0, ' ', 'V', 'F', 'T', 'R', '%', 0,
	0, 'N', 'B', 'H', 'G', 'Y', '^', 0,
	0, 0, 'M', 'J', 'U', '&', '*', 0,
	0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0,
	0, 0, '"', 0, '{', '+', 0, 0,
	0 /*CapsLock*/, 0 /*Rshift*/, PS2_ENTER /*Enter*/, '}', 0, '|', 0, 0,
	0, 0, 0, 0, 0, 0, PS2_BACKSPACE, 0,
	0, '1', 0, '4', '7', 0, 0, 0,
	'0', '.', '2', '5', '6', '8', PS2_ESC, 0 /*NumLock*/,
	PS2_F11, '+', '3', '-', '*', '9', PS2_SCROLL, 0,
	0, 0, 0, PS2_F7 },
	0
};

Aşağıda çeşitli tuş kodlarının örnek resimlerinin linki var. bu resimlerden hangi tuşa basılmış nasıl tepki vermiş görebilirsiniz.

Tuş çalışma resimleri buradadır. 

Tüm programlara da buradan ulaşabilirsiniz.

 

ARDUINO PS2 klavye simülatör.

Bu simülatörü sizlerin PS2 klavyeyi taklit edebilmeniz için yaptım. Bu şekilde çok sık kullanılan tuşları kendi klavyeniz olarak yapabilirsiniz ve normal klavye kullanmanıza gerek kalmaz. Hatta bir sonraki aşamada kablosuz klavye şekline bile çevirebilirsiniz. Bu şekilde uzaktan da istediğiniz tuşları kontrol edebileceğiniz avuç içi bir klavyeniz olabilecektir.

Program oldukça basit tutuldu. Çünkü sinyal gönderimini görmenizi istedim. Sinyal gönderirken tuş kodunu binary olarak tersten göndermeniz gerekiyor. Aynı zamanda PARITY bitini de ayarlamanız gerekiyor. yazıda bunu anlatım videoda da gösterdim bu şekilde ps2 klavyenin kullandığı ODD PARITY hesabını yaparak bulabilirsiniz.
Tüm zamanlamalara riayet ederseniz aynı arduino kütüphanesi normal klavyeyi algıladığı gibi sizin klavyenizi de algılayacaktır.

Aşağıdaki resimde 2 arduino göreceksiniz. Yukarıdaki arduino ana program yani normal klavye kodlarını elde eden programın aynısıdır.
aşağıdaki ise kendi klavyemizi yapabileceğimiz simülatör programıdır. Burada bulunan buton sayısını arttırabilirsiniz. tabii ki sinyal göndermeyi bu şekilde yapabileceğiniz gibi istediğiniz gibi kısaltarak da yollayabilirsiniz.
Sadece sürelere ve parity bitlerine dikkat edin.

Ayrıca videoda da dile getirdim. ana program başında klavye reset vardır. Bundan dolayı burada ACK sinyali beklemektedir. Sizler 3-4 defa tuşa basarsanız bu gecikme ve beklemenin önüne geçip normal çalışmaya başlayabilirsiniz. Çünkü klabvye reset ile led yakma kısmında klavyeye bilgi gidiyor ve sonrasında klavyeden aldım sinyali gitmesi gerekiyor.
Bunun yerine tuşa bir kaç kez basarsanız bu algılama yeterli olup normal çalışma moduna girecektir.

Proteus 8.6 versiyonu ile bunu hazırladım. sizler 8.6 veya daha yüksek versiyonla bunu açabilirsiniz. ya da pdf dosyasına göre bağlantı yapabilirsiniz. HEX dosyalarını ise arduino programında TASLAK menüsünden DERLENMİŞ BİNARY ÇIKAR seçeneğine basarak elde edebilirsiniz.

NOT: Yorumlarınızı yazının altına bırakırsanız sizden sonrakilerde faydalanacaktır.

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.