TIBBİ ENSTRUMANTASYON TASARIM ve UYGULAMALARI DERSİ VISUAL C++ İLE ADC VERİSİNİN GÖRÜNTÜLENMESİ Ayhan Yüksel http://web.itu.edu.tr/~bdogan/dersler/tetu1213/tetu.htm
AMAÇ ADC ile sayısallaştırılan analogişaretlerin bilgisayar ekranında görüntülenebilmesi gerekmektedir. Geliştirilecek program mikro denetleyiciden gönderilen ADC verilerini ekranda gösterecek, ayrıca analiz için dosyaya kaydedecektir. ADC ADuC 841 UART ADM 3202 Rx Tx COMPORT PC Analog Sinyal
YAPILACAKLAR PC üzerindeki yazılım, Visual C++ 6.0 ie geliştirilecektir. Yazılım şu işlemleri gerçekleştirecek: Seri Port u veri geldikçe okuyacak Sayısal olarak kodlanmış veriden anlamlı işareti ortaya çıkaracak Elde edilen işaret sürekli olarak ekranda görüntülenecek Gelen işareti ayrıca çıkış dosyasına kaydedecek Program yazarken kullanılacak tüm fonksiyonlar hakkında bilgi http://msdn.microsoft.com adresinden elde edilebilir.
PROGRAM ÇALIŞMA BLOKLARI PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ
PROGRAMIN BAŞLATILMASI Visual C++ Çatı Programı ("Dibit.c"), aşağıdaki biçimde çalışmaktadır MAIN InitApplication InitInstance (Program açılırken gerekli işlemleri gerçekleştirilir. Pencereler oluşturulur, Program Windows a kaydedilir,vs.) Get Message (Windows Mesajı alınır) Translate Message (Alınan Windows Mesajı programın anlayacağı biçime dönüştürülür) Dispatch Message (Alınan mesaj pencereye iletilir) İletilen Mesaj MainWndProc Pencerenin ana programıdır. Gönderilen mesajın türüne ve içeriğine göre program gerekli işlemleri yapar Mouse hareketi ve tıklamalar; Menü Seçimi; Klavyeden bir tuşa basma; TIMER Mesajları;
PROGRAMIN BAŞLATILMASI Menü öğelerinin oluşturulması Menü mesajlarının eklenmesi HANDLE kavramı Pencere parametrelerinin ayarlanması
PROGRAMIN BAŞLATILMASI Menü Öğelerinin Eklenmesi 1. ResoruceWiew sekmesinde DIBIT MENU seçilir 2. Menü düzenlenir, Menü öğesi için bir "ID" alınmış olur.
PROGRAMIN BAŞLATILMASI Menü Mesajlarının Eklenmesi 1. "MainWndProc fonksiyonu içinde WM_COMMAND "case i içinde ID_FILE_DENEME adında yeni bir "case" oluşturulur.
PROGRAMIN BAŞLATILMASI Handle Kavramı Tutacak, bir nesnenin tutulmasına kaldırılmasına ya da kullanılmasına yarayan parçasıdır. Object(nesne) Handle(tutacak) Nesneye dayalı programlamada (Object oriented programming), nesneler handle (tutacak) denilen kimliklerle kullanılır. Oluşturulan her nesnenin (pencere, çizim alanı, dosya, vs..) bir tutacağı vardır. Visual C++ fonksiyonları bu tutacakları kullanarak program yazımını kolaylaştırır.
PROGRAMIN BAŞLATILMASI Pencerenin Oluşturulması InitInstancefonksiyonu içinde CreateWindowfonksiyonu çağrılır, Fonksiyonun parametreleri ile pencerenin bazı özellikleri değiştirilebilir. Fonksiyon çalıştırıldığında, hwnd tutacağı, pencereyi temsil edecektir. NOT: Ws ve Hs değişkenleri Pencere boyutlarını belirtir, program kodunun başında 512 olarak belirlenmişlerdir
PROGRAMIN BAŞLATILMASI Handle Kavramı Tutacak, bir nesnenin tutulmasına kaldırılmasına ya da kullanılmasına yarayan parçasıdır. Object(nesne) Handle(tutacak) "Give Me a Handle, and I'll Show You an Object Ruediger Asche Microsoft Developer Network Technology Group Nesneye dayalı programlamada (Object oriented programming), nesneler handle (tutacak) denilen kimliklerle kullanılır. Oluşturulan her nesnenin (pencere, çizim alanı, dosya, vs..) bir tutacağı vardır. Visual C++ fonksiyonları bu tutacakları kullanarak program yazımını kolaylaştırır.
hwnd PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ
Gelen Verinin Gösterilmesi Pencere Koordinatları (0,0) (W,0) x (0,H) y
Gelen Verinin Gösterilmesi Ekranda çizim yapmak için gerekli fonksiyonlar Ekrana çizim fonksiyonları için tutacak (HANDLE) belirleme: GetDC() Kullanım: hwnd: Çizim nesnesi elde edilecek olan pencerenin Handle ı HDC : Çizim fonksiyonları için gerekli Handle. Penceredeki bir pixelin renk değerini değiştirme : SetPixel() Kullanım: hdc: Pencereye ait çizim nesnesinin tutacağı X,Y: Pixelin X-Y koordinatları crcolor: Pixel Rengi Örnek: SetPixel(HdcScreen, 100,100, RGB(255,0,0))
Gelen Verinin Gösterilmesi Ekranda çizim yapmak için gerekli fonksiyonlar Pencerede iki nokta arasına bir çizgi çizme: MoveToEx ve LineTo Kullanım (MoveToEx) X,Y: Çizginin başlangıç konumu Ayarlamadan önceki başlangıç konumunun alınması için kullanılır. NULL olabilir Kullanım (LineTo) X,Y: Çizginin bitiş konumu Örnek: (100,120) konumundan (200,240) konumu arasında bir çizgi çizme hdcscreen=getdc(hwnd); MoveToEx(hdcScreen, 100,120, NULL) LineTo(hdcScreen, 200,240)
Gelen Verinin Gösterilmesi Ekranda çizim yapmak için gerekli fonksiyonlar Pencereye bir metin ekleme :TextOut Kullanım X,Y: Yazının başlangıç konumu Yazdırılacak olan yazı Yazdırılacak yazının uzunluğu Örnek: TextOut(hdcScreen, 100,200, merhaba, 7) Pencereyi temizleme: BitBlt Kullanım Temizlenecek olan ekranın tutacağı Temizlemeye başlanacak koordinat Temizlenecek alanın genişlik ve yüksekliği NULL 0,0 WHITENESS (beyaz renge boyar pencereyi)
Gelen Verinin Gösterilmesi Çizim Örneği ÖRNEK: f(x)=sin(2*pi*x/25)+cos(2*pi*x/40) fonksiyonunu çizim isimli menü seçeneğine tıklandığında x=0~511 için ekrana çizdiren bir program yazınız. 1. Menünün oluşturulması: Menü elemanı önceki kısımda anlatıldığı gibi eklenir ve menü elemanı için atanan case içi aşağıdaki gibi doldurulur: SinOlustur() ve Ciz() fonksiyonları Sinüs işaretini oluşturmak ve ekranda çizmek içindir, sonraki adımlarda bu fonksiyonlar oluşturulacaklardır.
Gelen Verinin Gösterilmesi Çizim Örneği 2. SinOlustur() fonksiyonunun oluşturulması: Bu fonksiyon, global olarak tanımlanmış, 512 uzunluklu, floating sayı dizisine istenilen fonksiyonun değerlerini hesaplayarak kaydeder. Fonksiyon aşağıdaki gibi oluşturulmuştur: Program kodunun başında aşağıdaki tanımlamalar yapılmıştır:
Gelen Verinin Gösterilmesi Çizim Örneği (0,0) Mantıksal Koordinatlar (W,0) (ymax,0) (0,0) (0,0) Ekran Koordinatları (W,0) x Mantıksal Koordinatlar Ekran Koordinatları Xe = x Ye = H ( y y max max y y min ) (0, ymin) (0,H) Ekranda çizim yapabilmek için mantıksal koordinatların ekran koordinatlarına uygun bir dönüşüm fonksiyonu ile dönüştürülmesi gereklidir. y
Gelen Verinin Gösterilmesi Çizim Örneği 3. Ciz() fonksiyonunun oluşturulması: Ciz() fonksiyonu, sinyal isimli dizi içindeki 512 adet işaret değerini ekrana çizdirecektir. Çizim fonksiyonları kullanılmadan önce koordinatlar ekran koordinatlarına dönüştürülmelidir. Fonksiyon aşağıdaki gibi oluşturulmuştur:
Gelen Verinin Gösterilmesi Çizim Örneği SONUÇ:
hwnd PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ hwnd sinyal[]
SERI PORTUN KULLANIMA AÇILMASI Giriş, Seri Port un Açılması Seri Port aşağıdaki işlem sırasıyla kullanılacaktır: 1. COM Port u CreateFile() komutu ile açma 2. COM Port ayarlarını uygun biçimde değiştirme CreateFile: Bu fonksiyon bir dosyaya ya da bir giriş-çıkış aygıtına bağlanır. Fonksiyon çağrıldıktan sonra çıkış olarak dosya Handle ını verir. Kullanım: ÖRNEK:
SERI PORTUN KULLANIMA AÇILMASI Seri Port Ayarlarının Yapılması Güncel Seri Port ayarlarının alınması: GetCommState hserial DCB türünde değişken işaretçisi DCB ayarlarının değiştirilmesi Yeni DCB değerinin kaydedilmesi SetCommState
SERI PORTUN KULLANIMA AÇILMASI ComAc: ComPort Açma Fonksiyonu COM1 istenildiği biçimde açılırsa 1, açılmazsa 0 olarak çıkış verir. hserial tutacağı programın başında tanımlanmıştır.
hwnd hserial PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ hwnd sinyal[]
SERI PORTUN OKUNMASI ReadFile() Fonksiyonu ReadFile() fonksiyonu, Bir dosya ya da giriş-çıkış aygıtından istenilen miktarda okuma yapar. Fonksiyonun kullanımı için önceden CreateFile() fonksiyonu ile açılıp bir tutacak alınmalıdır. Giriş parametresi olarak verilen bir dizi ya da değişken işaretçisine istenilen miktarda byte yazılarak okuma tamamlanır. Dosya/aygıt tutacağı (hserial) Okunan verinin saklanacağı bellek bölgesi Okunacak byte sayısı Okunan byte sayısı
SERI PORTUN OKUNMASI BirKarakterOku() Fonksiyonu BirKarakterOku() fonksiyonu, hserialtutacağı ile temsil edilen seri porttan1 byteokur, çıkış olarak okuduğu karakteri verir.
hwnd hserial hserial PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ hwnd sinyal[]
ADC DEĞERİNİN ELDE EDİLMESİ VERI YAPISI ADC VERİSİ Bir okuma değeri iki byte olarak aktarılacaktır. VisualC++ programı, seri porttanverileri byte-byteokuyacaktır. Daha sonra ADC değerinin elde edilmesi için bu iki byte birleştirilmelidir. İki bytebirleştirilirken yüksek ve düşük anlamlı olan byte larınbilinmesi gereklidir. Bunun için bir kontrol algoritmasına gerek vardır.
ADC DEĞERİNİN ELDE EDİLMESİ VERI YAPISI Örnek 1: Seri Port tansürekli olarak okunan byte laraşağıdaki gibiyken bir ADC verisinin başlangıç ve bitiş byte larının hatasız elde edilmesi çok zordur. 04 05 03 05 05 0C 0A E8 07 A9 0B 33 0A A0 05 00 04 02 04 49. Örnek 2: Eğer mikrodenetleyicitarafından her ADC verisine ek olarak bir ayırma karakteri eklenirse, verinin okunması oldukça kolay olacaktır. FF 04 05 FF 03 05 FF 05 0C FF 0A E8 FF 07 A9 FF 0B 33 FF 0A A0 FF 05 00 FF 04 02 FF 04 49 Mikro-denetleyiciden gönderilen ADC verisi yapısı aşağıdaki gibi olabilir: 1 1 1 1 1 1 1 1 0 0 0 0 FFH ADCDATAH ADCDATAL
ADC DEĞERİNİN ELDE EDİLMESİ SERİ PORTTAN GÖNDERİLEN VERİNİN AYIKLANMASI X=BirKarakterOku() X==FF? h Mikro denetleyiciden belirli bir şekilde biçimlendirilmiş veriyi alan bilgisayar programı, ADC verilerini düzgün biçimde ayıklayabilmelidir. Bunun için yandaki gibi bir algoritma gerçeklenebilir. ADCH=BirKarakterOku() ADCH<16? h ADCL=BirKarakterOku() ADC=256*ADCH+ADCL Return ADC
hwnd hserial hserial PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI Bir byte ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ hwnd sinyal[]
THREAD FONKSİYONU GİRİŞ Thread, bir programın eşzamanlı olarak olarak çalıştırdığı görevlerden her biridir. Çok çekirdekli yapılarda threadgörevleri tam anlamıyla eş zamanlı çalışabilirken, Tek çekirdekli yapılarda bu işlem zaman dilimleme (time division) ile gerçekleştirilebilir. Thread lerbirbirinden bağımsız olarak çalışırken programa ait aynı kaynakları (açılmış dosya, global değişken, vs..) paylaşabilirler. Threadile çalışan bir sistemde threadlar den biri çok yavaş olsa bile programın çalışmasını yavaşlatmaz. Örneğin pencereler kullanıcı isteklerine kolayca cevap verir.
THREAD FONKSİYONU GİRİŞ Programda Threadkullanarak seri portsürekli okunacak ve ekrana çizim yapılacaktır. Thread, çalışma zamanının çoğunda seri porttanveri bekleyeceğinden, ana program bu sırada cevapsız kalmamalıdır. Threadçalıştırılırken, program aynı zamanda mesajlaşma işlemlerini gerçekleştirecek, düzgün bir çalışma sergileyecektir. ThreadProc" Thread ı görevleri ADC verisi okuma Veriyi Sinyal[] değişkenine saklama Belirli sayıda işaret alındığında ekrana bunu görüntüleme
THREAD FONKSİYONU THREAD FONKSIYONUNUN OLUŞTURULMASI Threadfonksiyonu, DWORD WINAPI ile tanımlanmış bir fonksiyondur. ThreadFonksiyonu, bir kere başlatıldığında, fonksiyon çıkış (return) yapana kadar sürekli olarak çalışacaktır. Thread fonksiyonu otomatik olarak yeniden başlamaz.
THREAD FONKSİYONU Çıkış Dosyasını Aç N=0 THREADPROC() FONKSIYONU ThreadProc görevi, sürekli olarak seri port üzerinden veri okuyacak ve bunu ekranda gösterecektir. Thread dançıkılmaması için Threadsonsuz döngü içinde çalışmalıdır. ADC=BirADCVerisiOku() ADC verisini çıkış dosyasına kaydet Sinyal[N]=ADC N=N+1 N==512? h Sinyal i Ekrana çizdir N=0
THREAD FONKSİYONU THREAD BAŞLATMA: CreateThread() CreateThread() fonksiyonu, bir WINAPI fonksiyonunu thread olarak çalışması üzere başlatır. Kullanım: 0 NULL 0 (default) &dwthrdparam &dwthreadid ThreadProc (dwthrdparam ve dwthreadid değişkenleri program kodunun başında tanımlanmışlardır)
THREAD FONKSİYONU THREAD SONLADIRMA: TerminateThread() TerminateThread() fonksiyonu, çalışmakta olan bir thread ibitirir. Kullanım: SeriPort tutacağının kapatılması
hwnd hserial hserial PROGRAMIN BAŞLATILMASI SERI PORT UN KULLANIMA AÇILMASI SERI PORT UN OKUNMASI Bir byte ADC DEĞERİNİN ELDE EDİLMESİ THREADPROC GELEN VERİNİN EKRANDA GÖSTERİLMESİ sinyal[] hwnd sinyal[]
UYGULAMA-3 ÖN ÇALIŞMA 1. Seri Port açma yerine CreateFile fonksiyonu ile verilen işaret dosyası* açılacaktır. 2. Dosyadaki işaretin formatı, sunumda belirtildiği gibidir (FF-ADCDATAH-ADCDATAL). 3. OKU menüsünde 2 seçenek olacak: Okumaya başla, OkumayıBitir. 4. Program aynı zamanda okunan ADC değerlerini bir.txtdosyasına satır satır yazacaktır. 5. VC++ ile hazırladığınız Projenizi klasörü ile beraber (DEBUG klasörünü silerek) 1 hafta içinde bdogan@itu.edu.tr adresine mail ile ulaştırın (Konu: TIPLAB) 6. Dosyadan okuma yapacağınız için, okuma çok hızlı olacaktır, uygun bir yere gecikme amacıyla for döngüsü koyabilirsiniz: for(i=0;i<10000;i++); gibi NOT: Programa görsel öğeler eklemeniz ve gelştirmeniz (grid, genlik bilgisi, farklı renkte çizim, ekran boyutlarına göre ölçekleme vs ) artı puan olarak değerlendirilecektir. Projenizi mutlaka kişisel olarak hazırlayın. İşaret Dosyası ve çatı programı, dersin web sayfasından indirilebilir. http://web.itu.edu.tr/~bdogan/dersler/tetu1213/tetu.htm