Pages

3 Mart 2013 Pazar

I/O Portlarını Kullanarak Bir Ledi Yakıp Söndürmek.

Yeni edindiğim Fez Panda II ile ilk uygulamamı yayınlamakta geç kaldığımın farkındayım ancak son iki haftadır verilen yeni bir projenin üzerinde yoğun bir biçimde çalışmak zorunda kaldım. Ki benim için heyecan verici bir proje olduğunu itraf etmeliyim. Süt ölçüm projesi üzerine 2 ay kafa yorup bir alay prototip üretip hayal kırıklığına uğradıktan sonra hava ve sütün birlikte 4 atmosfer basınçla bir borudan geçerken doğru bir biçimde ölçülmesini amaçlayan projede thermal mass sensör uygulama ayağını fez panda II ile yapmaya karar vererek kolları sıvadık. Proje nihayete erdiğinde genel hatları ile burada sizlerle paylaşacağım.


Tabi ki bu proje sırasında Fez Panda II nin pek çok özelliğinide yoğun bir biçimde kullanmak durumunda kaldığımızdan pek çok küçük uygulama ile sizlerin FEZ Panda ve .NET MICRO FRAMEWORK'e hızlı bir giriş yapmanızı sağlamış olacağım.

Lafı fazla uzatmadan ilk ve temel uygulama olan I/O port ları kullanarak bir ledi yakıp söndüreme konusuna dönelim.

İlk olarak BC547 ile kuracağımız devremizin ISIS ile tasarımını yaparak simülasyonunu gerçekleştirelim.

Şekil 1
Şekil 1'de gördüğümüz devrede NPN bir transistör olan BC547'yi tercih ettim. Bu tarz devrelerde hem sürme kolaylığı nedeniyle hemde devreye bağlanacak işlemci portlarını korumak amaçlı olarak genellikle NPN tipi yarı iletkenleri tercih ediyorum. Ama siz PNP bir transistörlede led'i sürebilirsiniz.

BC serisi transistörlerde genellikle beyz gerilimi 0.7V eşiğini aşana kadar Collector Emiter arası iletim sözkonusu olmamaktadır.

Devrede de  4k7 Beyz'in doğru yönde polarılması için ve hattın boş kaldığı zamanlarda 47K'lık direnç üzerinden toprak polarmasının sağlanarak beyz ucunda kararsız durum oluşturmaması için kullanılmıştır, 47K lık Toprak - beyz arası direnç ise I/O porttan  veri gelene kadar geçen zamanda beyz polarmasının 0,7V'un altında kalmasını garantilemek için kullanılmakta ve yine kararsız durumları engellemektedir.

Temel transistör polarma bilgisinden sonra devremize dönelim.

Şekil 2

Devrede buttona her bastığınızda, Şekil 2'de de göreceğiniz gibi Q1(B) probundaki voltaj değerinin 0,8V'un üzerine çıktığı, böylelikle beyz polarmasının ve eşik geriliminin sağlanarak emiter - collector arasında transistörün ileri yönde iletime geçtiğini ve led'in yandığını takip edebilirsiniz. Buttondan parmağınızı çektiğinizde ise Q1(B) probundaki Beyz voltajının 0,7 voltun altına düşerek transistörü kesime götürdüğünü ve emiter - collector arası akımın kesildiğini dolayısıyla ledin söndüğünü gözlemleyebilirsiniz (BKZ Şekil 1).

Şimdi devrede gördüğünüz button 'un görevini Fez Panda'nın I/O portunun üstleneceği ve ledi her 1 sn de bir yakıp söndüreceği bir uygulama geliştirelim.



using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace ExternalButtonAndLedTutorial
{
    public class Program
    {
        // Fez Panda'ya digital pin #5'in LED'e bağlı olduğunu bildirelim.
        static readonly OutputPort _led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di5, false);
        private static InterruptPort interruptPort;
        public static void Main()
        {
            // AN0'ı button girişi olarak ayarlayıp Interrup ayarlarını yapalım
            interruptPort =  new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.An0, true,
                Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
            // GlitchFilterTime ile button'un debouncing süresini ayarlıyor ve kararsız durum oluşmasını     engelliyoruz.
            Cpu.GlitchFilterTime = new TimeSpan(TimeSpan.TicksPerSecond / 4);     // 1 Tick = 100 nano saniye
            // Interrupt için olay günlüğü oluşturuyoruz.
            interruptPort.OnInterrupt += new NativeEventHandler(InterruptPort_OnInterrupt);
            Thread.Sleep(Timeout.Infinite);
        }
        // Interrupt oluştuğunda çalışacak rutini yazalım
        private static void InterruptPort_OnInterrupt(uint port, uint state, DateTime time)
        {
            bool bilgi; // Boolean tipinde bir değişken tanımlayalım
            bilgi = _led.Read(); // Bu değişkenin değerini buttonun o anki durumunu atıyoruz
            if (bilgi) // Eğer Led Yanıyorsa
            {
                _led.Write(false);       // LED'i Söndür
                interruptPort.ClearInterrupt();
                Debug.Print("Kapandı !");
            }
            else // Eğer Led Yanmıyorsa
            {
                _led.Write(true);      // LED'i Yakar
                interruptPort.ClearInterrupt();
                Debug.Print("Açıldı !");
            }
        }
        }
}

Yukarıdaki kod da ne yaptık ?

Hemen satır satır üzerinden geçelim...

İlk olarak sistemin tanımlama kısmını ele alacak olursak aşağıdaki namespacelerin'den System ve System.Threading sistem mesajları, olay günlükleri için gerekli komutlar için, Microsoft.Spot ve Spot.Hardware ile GHIElectronics.NETMF.FEZ namespaceleri ise donanımsal işlemler için yazılımın başında tanımlammalıdır. 

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

Bu tanımlar yapılmadığı taktirde bol hata mesajlı ve .Net Micro için hiç bir anlam ifade etmeyen bir kod yığınınız olur ki sanırım hiç birimiz çalışmayan bir kod yazmak istemeyiz.

Bu kısımla ilgili tüm namespace'ler için .net Micro Framework 4.1 SDK lerini detaylıca incelemenizi tavsiye ederim.

Kodumuza geri dönelim...


namespace ExternalButtonAndLedTutorial
{
    public class Program
    {

Tanımlamalarıyla program gövdesini yazmaya başladığımızı ifade ettikten sonra ;Fez Panda'ya digital pin #5'in LED'e bağlı olduğunu bildirelim.
     
                static readonly OutputPort _led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di5, false);

Bu kod cümleciğinde Programın genelinde kullanılmak üzere _led ismi verilen değişkene, Fez Panda II'nin dijital portu D5 numaralı pinin çıkış portı olduğunu ve default değerinin False olduğu tanımını yapıyoruz.Bu tanımlama sayesinde      

private static InterruptPort interruptPort;

Burada da interrupPort'u Microsoft.Spot.Hardware.InterruptPort olay günlüğünün inheritance yoluyla kullanabileceğimiz bir temsilcisi haline getirdikten sonra programımızı şekillendirmeye başlayabiliriz.
  
 public static void Main()
        {

Cümleciği ile programımızın ana gövdesini tanımladığımızı sisteme bildirdik.

Şimdi AN0'ı button girişi olarak ayarlayıp Interrup ayarlarını yapalım
            interruptPort =  new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.An0, true,
                Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);

Cümlesi ile interrupPort ile çağırmış olduğumuz class'a Microsoft.Spot.Hardware clasının pin tanımlamalarını GHIElectronics.NETMF.FEZ clasının pin out tanımlamalarından AN0 pinine atadığımızı, bu pinin ön tanımlı durumunun True yani  "1" veya High olduğunu Port pullup direncinin aktive edildiğini ve interrupt olay günlüğünün düşen kenarda oluşması gerektiğini bildiriyoruz.

Sonrasında ise An0 pinine bağlanacak button'un tuşlanması sırasında oluşacak ve debouncing tanımlaması ile bilinen parazitik girdilerinin interrupt'ı erken tetiklemesi için GlitchFilterTime ile button'un debouncing süresini ayarlıyor ve kararsız durum oluşmasını engelliyoruz.

            Cpu.GlitchFilterTime = new TimeSpan(TimeSpan.TicksPerSecond / 4);     Burada  1 Tick, 100 nanosaniye olarak hesaplanmalıdır.

Button tuş sekansındaki parazitik girdileri de engelledikten sonra  Interrupt için olay günlüğü oluşturuyoruz.

            interruptPort.OnInterrupt += new NativeEventHandler(InterruptPort_OnInterrupt);

ve aşağıda kod cümleciğiyle programımızı bir olay günlüğü oluşana kadar Fezimizi Uyutuyoruz.

            Thread.Sleep(Timeout.Infinite);


Gelelim programımızın en önemli kısmına şimdi Interrupt oluştuğunda çalışacak rutini yazalım

        private static void InterruptPort_OnInterrupt(uint port, uint state, DateTime time)
        {

InterruptPort olay günlüğü rutinini tanımladıktan sonra;

            bool bilgi;

kod cümlesi ile Boolean tipinde bir değişken tanımlayalım ve bu değişkenin değerine


            bilgi = _led.Read();

kodu ile _led portumuzun o anki durumunu atayalım

sonrasında yapılacaklar ise eğer led değeri "True" ise yani led yanıyor ise
         
        if (bilgi) // Eğer Led Yanıyorsa
            {
                _led.Write(false);       // LED'i Söndür
                interruptPort.ClearInterrupt(); //Interrupt Portunu Sıfırla
                Debug.Print("Kapandı !"); // Led'e kapanma sinyalinin gönderildiğinin takibi için emülatör ekranına led durumunu yaz
            }
         
        else // Eğer Led Yanmıyorsa
            {
                _led.Write(true);      // LED'i Yak
                interruptPort.ClearInterrupt();  //Interrupt Portunu Sıfırla
                Debug.Print("Açıldı !");// Led'e kapanma sinyalinin gönderildiğinin takibi için emülatör ekranına led durumunu yaz
            }


Böylece programımızı tamamladık.

Bu sitede yayımladığım tüm uygulamalar ya bredboard üzerinde devre kurularak, yada baskılı devre üzerinde oluşturularak tarafımca mutlaka denenmektedir.

Bu uygulamada tarafımca Fez Panda II deneme bordunda denenmiştir.

Kodları ve devre şemalarını link halinde paylaşmamamın yegane sebebi ise siz değerli meslekdaşlarımı devreleri çizmek ve yazılımları elle kodlamak zorunda bırakmak ve bu sayede öğreniminizi hızlandırmak  ve el pratiğinizi geliştirmekten öde değildir.

Hepinize sabrınız için teşekkür eder bir sonraki uygulamamızda görüşmek üzere Fez Pandanızla eğlenceli günler dilerim.

Hiç yorum yok:

Yorum Gönder