Bu yazımda sizlere
C# kullanarak internet üzerinden Adım moturu(step motor) kontrolünün ve elektriksel
veri toplama işleminin nasıl yapıldığını aktaracağım.
Uygulamaları indirmek için aşağıdaki bağlantıları tıklayınız.
İstemci(Client) Uygulama
Sunucu(Server) Uygulama
Çoğunuz, internet üzerinden kontrol edilen mekanik aygıtlar hakkında bir şeyler
okumuşsunuzdur. Hatta, gün geçmiyor ki, “ bilmem hangi profesör, Amerika’da
bulunduğu klinikten, Londra’daki bir hastayı ameliyat etti “ diye, bir haber
okumayalım, gazetelerde. Bu nasıl gerçekleşiyor? Tamamen hasta yanında bulunan
otomatik olarak kontrol edilebilen aygıtların bir bilgisayarlar ağı üzerinden
kontrolüyle.. Bizim de burada yapacağımız ilke olarak hemen hemen aynı şey;bizim
ağımızı internete bağlı iki bilgisayar oluşturacak.
Yani, bu yazımızın
konusu daha önceki yazıda bahsettiğim gibi, internet üzerinden elektronik veya
elektromekaniksel bir aygıtın kontrolu olacaktır. Örnek olarak , elektronik
aygıtı ledler, elektromekaniksel aygıtı ise bir adım motor(step motor) oluşturacaktır.
Aygıtlarımız, geçen
yazıda anlatılan türde bir arabirim aracılığıyla sunucunun paralel portuna takılı
olmalıdır.
Bu
arada bir konuyu hatırlatayım:
Paralel portla ilgili ilk yazımdan sonra birçok arkadaştan özel e-posta aldım.
Çoğu konuyu oldukça ilginç bulmuştu, fakat devreleri yapacak derecede veya hiç
elektronik bilgileri yoktu. Dolayısıyla şöyle bir şey düşündüm:Daha sonraki
bir yazıda, biraz çabayla herkesin takip edebileceği şekilde; resimlerle göstererek,
bir breadboard üzerine paralel porta takılacak bir arabirim devresi nasıl yapılır,
onu göstereceğim. Böylece bu konuya merak duyan herkes bir şekilde bu çalışmalara
katılabilsin.
Geçen yazıda, devremizin bu haliyle , dışarı vereceği akım, sadece küçük
ledleri yakmaktan başka bir şeye yaramayacak diye bahsetmiştim. Bu bölümde,
data portununa bağlı küçük ledler deneyimiz için yeterli olacaktır. Fakat, step
motoru Control port çıkışına takmak istiyorum. Bu portun 2 kanalını kullanacağız.
Normal olarak, bir step motoru sürmek için 4 kontrol kanalına gereksinimiz olur,
fakat burada özel tümleşik devre gerektirmeyen , sadece çıktı kanalllarına normal
transistör ve koruma diyotları bağlayarak gerekli akımı oluşturup, bir adım
motorunu sürme devre şeması da verecek olmama rağmen, ben elimdeki küçük step
motoru sürmeye yarayan, gerekli akım büyüklüğünü ve kontrol mantığını sağlayan
özel bir tümleşik devre kullanacağım.
Kaldı ki, bu devreyi
de edinmek zor değildir. İstenirse daha büyük motorlar da bu devrenin süreceği
2 güç transistörüyle kontrol edilebilir.
Neyse konumuz step
motor sürme konusunu ayrıntılarıyla işlemek değil, o burada sadece konu mankeni.
İsteyen ayrıntılı bilgi için web’de detaylı bilgi bulabilir.
Devre şemaları
ve bağlantılar aşağıdaki gibi yapıldıktan sonra gelelim internet üzerinden bunların
kontrolunu sağlamaya...
Şekil 1:Önce 4 adet FET transistörüyle step motor sürüş devresi:
INTENET
ÜZERİNDEN KONTROL:
Internet üzerinden
kontrol derken, önce bir ASP.NET sayfası üzerinden bu aygıtları kontrol etmeyi
düşündüm, fakat bunu yapmak oldukça basit geldi.. Çünkü tüm bilgi gidiş ve gelişleri
otomatik olarak ASP.NET tarafından sağlanacaktı ve de dolayısyla fazla cazibesi
olmayacaktı. Bunun yerine , geriye 2 seçenek kalmıştı. Birincisi System.Net
uzay alanındaki “Socket” sınıfını kullanarak, bir diğeri de .NET Remoting kullanarak
bu işi gerçekleştirmek...Sonra, Socket sınıfı üzerinden bu işi yapmaya karar
verdim. Remoting konusu ise bundan sonraki yazının konusunu oluşturacak.. Remoting
aracılığıyla, yine aynı arabirim devremize ekleyeceğimiz bir ADC(Analog-Digital
Convertör:Analog-Digital Çevirici) ile web termometresi yapacağız. Yani sunucunun
paralel porttan okuduğu etrafındaki havanın veya bir tas içersinde bulunan su
sıcaklığını , istemciye internet üzerinden ulaştıracağız. Doğaldır ki, bu konu
sadece sıcaklık ölçümüyle sınırlı değildir;istediğiniz fiziksel parametreyi
ölçüp istemciye ulaştırmak olanak içinde, yeter ki uygun bir sezici ve sinyal
düzenleyici kullanarak, fiziksel veriyi analog elektrik sinyallerine çevirip,
ADC’ye beslenebilecek hale getirelim.
Şekil 2:SAA1027(Philips marka) tümleşik devre ile 2 adet Control Port kanalı
kullanarak adım motor sürüş devre şeması:
Bu devrede Control
portunun 0.biti yön, 1.biti ise adım sinyalini besleyecek.
Bu çalışmada, bu
devreyi kullandım. Gerek bu devredeki, gerekse transistörlü devredeki parçaları
bulmak hiç de zor değil. Hatta SAA1027 yerine başka tümleşik devreler de kullanabilirsiniz.
Şekil 4: Internet üzerinden TCP/IP protokolü ile cihaz kontrol şeması:
Şekil 5 : Paralel port elektronik devresi, SAA1027 kontrol devresi ve de
adım motor resmi
İstemcinin bilgisayarında çalışacak program ön yüzü, yukarıda verilen programdaki
gibi olacaktır. Tek farkı, fakat önemli bir fark, aygıtların bu sefer aynı bilgisayar
paralel portuna değil de , bir sunucu bilgisayarın paralel portuna bağlı ve
her iki bilgisayarın da internete bağlı olması.. Fakat tek bilgisayarı olanlar
korkmasın..Bu çalışma tek bilgisayar üzerinde de yapılabilir;istemci ve sunucu
için yazılan programları aynı bilgisayarda iki ayrı Visual Studio.NET ortamı
açıp, çalıştırmak aracılığıyla...Yukarıdaki resim, kontrol mekanizmasının mantığını
göstermektedir.
İstemci
üzerinde çalışacak program tasarımı:
İstemcinin önce
bir port üzerinden(burada sanal bir porttan bahsetmekteyiz, paralel portla ilgisi
yok) bir sunucuyla iletişim kurması gerekir.. Sunucu ise sunduğu şeylerle ilgilenen
istemcileri aynı porttan dinlemek durumundadır. Bir diğer önemli nokta da ;istemci
, dinleyeceği sunucunun adresini bilmek zorundadır. Bu adres genellikle IP adresidir.
Dolayısıyla önce
istemcinin adresi belli bir sunucuya numarası belli bir porttan bağlamamız gerekir.
Burada yazdığım
programda aynı zamanda asenkron callback mantığını görmüş olacağız.
Önce programın,
ön yüzüne bir göz atalım:
Şekil 6:İstemci programı ön yüzü
Sunucuyla bağlanmak
için, sunucunun IP adresini ve dinlediği port kanalını girdiğimiz 2 textBox
kutusu bulunmaktadır. Bu verileri girdikten sonra sunucuya bağlan düğmesine
tıklamamız gerekmektedir. Fakat , öncesinde de, sunucu programımızı çalıştırmamız
gerekir ki, sunucuya istemci bağlanabilsin.
İstemci’de çalışan
programın kullanıcı önyüzünde, Dataport kanallarını temsil eden düğmelere tıklandığında
sunucu paralel portuna bağlı elektronik kartımızın Dataport bölümündeki ledleri
yakıp söndürmekteyiz. Düğmelerimiz, ilk yazımda olduğu gibi yine NewButton adıyla
yarattığımız , normal Button sınıfından türemiş fakat ondan 2 farklı özelliği
olan düğmelerin oluşturduğu ButtonArray sınıfıyla form üzerindeki Dataport “groupbox”’u
üzerine , kullanıcı ön yüz sayfası yüklenirken otomatik olarak yerleştirilmektedir.
Tüm düğmeler için tek bir “EventHandler” vardır. EventHandler, 8 kanala denk
gelen düğmelerden herhangi biri tıklandığında , düğmenin “Tag” özelliğini kullanılarak
hangi düğmenin tıklandığı saptar. Bir önceki yazıdaki NewButton düğmelerinden
tek farkı, burada türettiğimiz ButtonArray içindeki düğmelerin herbirinin aynı
zamanda bir de System.Net.Sockets alanından alınmış bir “Socket “ sınıfı tipli
bir özel alanının olmasıdır. Bu alan sayesinde, düğmelere tıkladığımızda , doğrudan
istemciden sunucuya mesaj gönderebilmekteyiz.
İstemci-Sunucu
arasında haberleşme için bir protokol belirlenmesi gerekir. Bu protokol , istemciyle
sunucu arasında yapılan haberleşmenin anlamlandırılabilmesi için önemlidir.Ben
burada şöyle bir protokol belirledim:
Elektronik kartımızdaki
3 grubu temsilen, hangi porta bilgi gönderilecekse , sunucu-istemci arasındaki
her gönderilen bilginin başına ve sonuna bir önek ve sonek bilgisi koymak. Bilgi
isteme durumunda ise sadece önek kullanmak.Böylece ilgili yerde alınan bilginin
hangi portla ilgili olduğu bilinsin.
Kabul edilen ekler
yerine göre şöyledir:
Data port için:
DPort
Control port : CPort
StatusPort : SPort
Örneğin, Data port
düğmelerinden birisi tıklandığında , , sunucuya göndereceğimiz bilginin başına
ve sonuna “DPort” yazısı getiriyoruz: “DPort”+düğme numarası+”DPort”; Diyelim
ki “1” numaralı kanalı toggle etmek istiyoruz,gidecek bilgi “DPort1DPort” olacaktır.
public
void ClickHandlerD(Object sender, System.EventArgs e)
{
int i=(int)((NewButton)sender).Tag;
string msg = Convert.ToString(i);
msg="DPort"+msg+"DPort";
//send the data in bytes;
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
if(((NewButton)sender).BSocket != null)
{
((NewButton)sender).BSocket.Send(byData);
}
if(((NewButton)sender).Status==false)
{
((NewButton)sender).Status=true
;
((NewButton)sender).BackColor=
System.Drawing.Color.Red;
}
else
{
((NewButton)sender).Status=false;
((NewButton)sender).BackColor=System.Drawing.Color.White;
}
}
|
Yukarıda verilen
“EventHandler” metodundan da görüleceği üzere tıklanan düğmenin numarası “DPort”
ekleri arasına konulmakta ve böylece oluşturulan veri tümcesi “byte[]” türünden
veriye dönüştürülüp, düğmenin Socket alanının “Send” metodu aracılığıyla sunucuya
gönderilmektedir. Doğal olarak , daha önceden, düğmeler form üzerine yerleştirilirken,
bu düğmelerin Socket tipi alanlarına, istemci programı ilk çalıştırıldığında
yaratılan “m_clientSocket” nesnesi (Programın genel yapısı aşağıda daha detaylı
anlatılacaktır) atanmaktadır. Bu veri sunucuya gittiğinde, oradaki kod, ön ve
sonekleri atıp, aradaki veriyi alıp, böylece gerekli veriyi dataporta gönderip,
istenen ışığı “toggle” edecektir.
Control portuna
bağlı step motoru çalıştırma:
İstemci tarafında
, kullanıcı ön yüzünde bulunan 1 adet “textBox” içerisine motorun kaç adım atması
gerektiğine dair rakam yazılacaktır ve sonra düğme tıklandığında şu kod çalışacaktır:
private void
btnDrive_Click(object sender, System.EventArgs e)
{
string msg="CPort";
msg=msg+txtStepNumber.Text+msg;
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
m_clientSocket.Send(byData);
} |
Görüldüğü gibi, motorun dönmesini istediğimiz adım sayısı “CPort” ön ve arka ekleri
arasına alınmakta , oluşan yeni tümce, byte[]’e çevirilip, sunucuya gönderilmektedir.
Sunucu ise, ön ve arka ekleri atıp aradaki sayı kadar motoru adımlatacaktır. Motor
kontrol devresi ve kodu Sunucu programı anlatılırken verilecektir.
Status portuna bağlı girdi kanallarını okutmak içinse, ilgili düğmeyi tıkladığımızda
sadece Sport yazısını sunucuya göndermekteyiz. Sunucu tarafına gelen mesaj “Sport”
ile başlıyorsa, sunucu bundan Status port girdi kanallarına ait bilgi istendiğini
anlar ve bu portun verisini okuyarak, istemciye gönderir. İstemci de zaten bu
veriyi beklemektedir, WaitForData() metoduyla..
private void
btnStatusPort_Click(object sender, System.EventArgs e)
{
string msg="SPort";
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
m_clientSocket.Send(byData);
WaitForData();
} |
Gelen veri , OnDataReceived() metoduyla işlenir. Sunucudan bu veri “SPort” ön
ve arka ekleriyle geldiğinden, bu metot içerisinde bu eklerden kurtulup StatusPort’tan
sunucunun okuduğu “byte” verisi deşifre edilir(herbir bit’e karşılık gelen bit
ağırlık değeriyle gelen veriyi “AND”leyip sonucu kontrol ederek) ve ilgili “checkbox”
, “checked” veya “unchecked” yapılır:
public
void OnDataReceived(IAsyncResult asyn)
{
SocketPacket theSocketId=(SocketPacket)asyn.AsyncState;
int dataReceived=theSocketId.thisSocket.EndReceive(asyn);
char[] chars=new char[dataReceived+1];
System.Text.Decoder decoder= System.Text.Encoding.UTF8.GetDecoder();
int charLen= decoder.GetChars(theSocketId.dataBuffer,0,dataReceived,chars,0);
System.String strData=new System.String(chars);
if(strData.IndexOf("SPort")>-1)
{
int
fIndex=strData.IndexOf("SPort");
int
lIndex=strData.LastIndexOf("SPort"); strData=strData.Substring(fIndex+5,lIndex-fIndex-5);
int
statusPortData=Convert.ToInt16(strData);
UncheckAll();
if
((statusPortData & 1)==1) chk1.Checked=true;
if
((statusPortData & 2)==2) chk2.Checked=true;
if
((statusPortData &4)==4) chk3.Checked=true;
if
((statusPortData &8)==8) chk4.Checked=true;
}
}
|
İstemci programının genel yapısı:
Önce, ön yüzdeki
ilgili kutulara bağlanmak istediğimiz sunucunun IP adresini ve sunucunun servis
verdiği port numarasını gireriz. Eğer denemeyi aynı bilgisayar üzerinde yapıyorsanız,
yani kullandığınız bilgisayar hem sunucu hem de istemci olarak çalışacaksa,
bilgisayarın IP adresini kendisi bulan bir metot bulunmaktadır, program içerisinde,
GetIP() adında.. Bu kod , IP numarasını bulup, ilgili kutuya yazar.
Yok eğer, sunucu
olarak internete bağlı farklı bir bilgisayar kullanılıyorsa, bu bilgisayarda
MS-DOS promptta C:/>ipconfig yazarak bilgisayarın IP adresini öğrenip, istemcideki
kutuya girmemiz gerekmektedir. Port numarası olarak 8000 alınmıştır. Sonra da
“Sunucuya bağlan” düğmesi tıklanmalıdır;sunucu programını çalıştırdıktan sonra...
Program çalışmaya
başlarken, önce bir “Socket” nesnesi yaratılır, Tcp protokolü kullanarak.
m_clientSocket=new
Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp
); |
IP adresi ve port
numarası kullanılarak IPEndPoint nesnesi yaratılır.
Yaratılan “Socket” nesnesinin Connect metoduna bu “IPEndPoint” nesnesi parametre
olarak verilirek, sunucuyla bağlantı sağlanır.
Sonra da WaitForData() metoduyla , sunucudan gelecek mesajlar dinlenilmeye başlanır.
Arka planda veriler gidip gelirken, bilgisayarın diğer işlemlerini yapabilmesi
için Asenkron haberleşme tekniği kullanılmaktadır. Bunun için, OnDataReceived
metodu, bir “AsyncCallback” metodu olarak tanımlanmıştır.
if(m_pfnCallBack==null)
{
m_pfnCallBack=new AsyncCallback(OnDataReceived);
} |
Verileri 1024 byte’lık büyüklükte bir tampon dizin aracılığıyla almaktayız. Bu
büyüklükte alanı olan, bir SocketPacket sınıfımız var, ayrıca. Bu sınıfın bir
diğer alanı da Socket nesnemizi atadığımız bir alan.
Socket nesnemizin
BeginReceive metoduyla , bu SocketPacket nesnesinin tampon veri alanını doldurmaya
başlarız.
AsyncCallBack nesnemizin
konumunu OnDataReceived() metodu içersinde yakalayıp, sonlandırarak, alınmış
verileri önce bir karekter dizini içersine sonra da String tipine dönüştürürüz.
Sonra da gelen bilginin içerisinde “SPort” yazısı var!
SUNUCU PROGRAMININ GENEL HATLARI
Burada , belirli bir port numarası üzerinden, yaratılan bir Socket nesnesi aracılığıyla
istemci dinlenir. Bağlantı sağlandığında çalıştırılmak üzere OnClientConnect
adlı Callback metodu bulunmaktadır.
Bu metot , bağlantı
sağlandıktan sonra istemciden gelen bilgileri WaitForData() metoduyla dinlemektedir.
Bunun içersinde de bir diğer callback metodu olan OnDataReceived() callback
metodu bulunmaktadır. Bu metot da , gelen bilgilerin tamamını yakalayıp, değerlendirmek
için yazılmıştır.
İstemciden gelen
verinin hangi paralel port gurubuyla ve/veya kanalıyla ilgili olduğunu anlamak
için başlangıçta belirlediğimiz protokol ön ve son eklerine bakılır bu metot
içersinde. Socket nesnesinin tampon alanından alınan veri önce karekter dizinine
sonra da String nesnesine çevrilir. Bu nesne içersinde sırasıyla DPort, CPort
ve SPort ön ve son eklerine bakılır. Bu ekler arasındaki bilgi alınarak ilgili
metoda parametre olarak geçirirlir.
Örneğin, DPort
ekleri bulunursa, bunların arasındaki numara(1-8 arası) , hangi portun “toggle”
edilmesi gerektiğini bildirir.
InpOut sınıfındaki(geçen
yazıda ayrıntılı bahsedildi) ToggleDataPortBit(adres,bit) metoduna verilen bu
numara sunucunun ilgili bit’i toggle etmesini sağlar.
Gelen bilgi, Control
Portu ile ilgili ise bu porta bağlı step motor kontrol devresini çalıştırmamız
gerektiği anlamını verir. Veri olarak CPort ekleri arasında bulunan adım sayısı
ele geçirilir; InpOut.StepMotorCont(controlportadres,beklemezamanı) metodu bu
sayı kadar for-next döngüsü içerisine alınır.
Step motorumuzu
control portunun 2 kanalı yardımıyla kontrol etmekteyim. Kanallardan birisi(0.bit>bit
ağırlığı:1) motorun dönüş yönünü diğeri(1.bit>bit ağırlığı:2) ise adımlama
işini gerçekleştirmektedir.
Kullandığım motor
Japan Servo Co Ltd KP3P8-701 stok numaralı küçük, her adımda 7.5 derece dönen,
maksimum 12V’la çalışan bir motordu. Kullanılmayan eski bir tarayıcıdan çıkardığınız
adım motor da pekala işinizi görür. Bunu kontrol etmek için ise , kontrol portundan
2 kanalın sürdüğü bir SAA1027 tümleşik devresi kullanılmıştır. Motor ve devresinin
fotoğrafı aşağıda verilmektedir. Daha altta da bu elektronik devre şeması verilmektedir.
SAA1027 devresinin
15 numaralı bacağına her yüksek-alçak-yüksek(5-0-5) sinyali gönderdiğimizde
bir adım atacaktır. 3 numaralı bacaktan ise sadece alçak veya yüksek vererek
motor dönme yönü saptamaktayız:Bu bacağa sürekli 0 değeri verdim, bu programda.
Şekil 7 : Sunucu Uygulama
public static
void StepMotorCont(int base_address,int t)
{
WriteControlPort(base_address+2,2*1+0);
delay(t);
WriteControlPort(base_address+2,2*0+0);
delay(t);
WriteControlPort(base_address+2,2*1+0);
delay(t);
} |
Bu devreye gönderilen herbir yazma işlemi sonrasında , bilgisayarınızın hızına
göre bir miktar bekleme süresi koymalıyız, yazılan verinin tam olarak yerine ulaşabilmesi
için. Bunun için bir delay(int t) metodu yazılmıştır;verilen parametre sayısı
kadar for-next döngüsü yapan bir metot. Kullandığım bilgisayar , Toshiba 1.7GHz
laptop ve benim için 10^7’lik bir for-next loop yeterli oldu.Siz de bilgisayarınızın
hızına göre bu rakamı azaltıp çoğaltarak istediğiniz etkiyi elde etmeye çalışınız.
Aslında bu rakam, motor hızını ayarlamak için de bir parametre olabilir.
Sunucuya gelen bilgi “SPort”
içeriyorsa, sunucu StatusPort’un byte değerini okur ve istemciye gönderir.
stPortData=InpOut.ReadStatusPort(0x378);
SendStatusPortData(Convert.ToString(stPortData),workerSocket); |
İstemciye veri,
aşağıdaki metot aracılığıyla gönderilir.
public void
SendStatusPortData(string msg,System.Net.Sockets.Socket soc)
{
// Convert the reply to byte array
msg="SPort"+msg+"SPort";
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Socket workerSocket = (Socket)soc;
workerSocket.Send(byData);
} |
Burada yazdığım
mantığı çok yerde kullanabilirsiniz. Örneğin Status port grubuna, evinizdeki
çeşitli alarm devrelerinin çıktılarını bağlayabilirsiniz;yangın, su baskını,
gaz kaçağı v.s. Gittiğiniz herhangi bir yerden, internete bağlanarak bu kanalların
durumunu kontrol edebilirsiniz. Uzaktan, örneğin, işten çıkmadan önce, evinizdeki
bilgisayara uygun bir devreyle bağlanmış elektrikli ısıtıcınızın veya kombinizi
istediğiniz anda çalıştırabilirsiniz. Kış günlerinde, evinize geldiğinizde,
ekonomik kalarak evinizi sıcak bulmaktan daha keyifli ne olabilir?. Ya da, kahve
veya çay suyunuzun kaynamış, sizi bekliyor olması...
Doğal olarak böyle
bir uygulamada bu kontrol programına sadece sizin ulaşabilmeniz için, gerekli
kimlik ve şifre doğrulama işlemlerini yapan kodları da programınıza eklemeniz
gereklidir. Yoksa eviniz yol geçen hanına dönebilir!
Çalışmalarınızda
bu yazıdan esinlenme durumu olursa ve bu çalışmanızı benimle veya tüm okuyucularla
paylaşırsanız sevinirim. Unutmayın, bilgi saklamak için değil paylaşmak için
vardır; ancak, paylaşıldığında anlam kazanır ve toplumda ilerleme sağlanabilir.
Not :ServerControl.zip
dosyasındaki ınpOut.cs sınıfının kullandığı Inpout32.dll’i için ilk yazıdaki
zip dosyasına başvurunuz.
Makale:
C# ile İnternet Üzerinden Elektronik Devre Kontrolü C#, Visual C# ve .NET Fevzi Özgül
|