Makale Özeti

Bu yazıda home easy ya da simple protokol olarak adlandırılan ev tipi uzaktan kumandalı iletişim kuralları ve .net microframework ile nasıl kullanılabilineceğine dair konular anlatılmaktadır.

Makale

Merhabalar, uzaktan kumandalar günümüzde vazgeçilmezler cihazlardandır. Bir çok kullanım alanı olmasına rağmen bu yazıda ev içinde kullanmaya yönelik tasarlanmış ve elektrik prizini açmak/kapatmak üzere tasarlanmış kumandaları inceliyor olacağız.

Wireless remote light switch olarak tabir edilen ve ev kullanımına yönelik bu sistem çok temelde devreyi aç / kapat prensibi üzerine kurgulanmıştır.


 

Yazının temel konusu olan home easy protokolünü hemen anlatmak istiyorum. Home Easy protokolü bu tür cihazlar için tasarlanmış temel düzey haberleşme protokolüdür. Yukarıdaki resimde görülen kumandanın 1 numaralı ON tuşuna basıldığında 1 numaralı (F0FFFF) anahtarı aç(F0) gibi bir yayın yapılıyor. Elektirik prizleri de eğer bu yayın kendilerine hitap ediyor ise (priz numarası, grup numarası gibi) işlemi yerine getiriyor. Elektirik prizinin numarası ve ayrıca grup numarası mevcuttur. Grup numarası aynı ortamda birden fazla kumanda ve/ya prizin varlığından kaynaklanan çakışmaları engellemek içindir. Grup kodu aynı zamanda kumanda üzerinde de vardır ve hem kumanda hem priz üzerindeki grup kodları ayarlanabilir yapıdadır. 1. grup ve 1. devreyi aç komutu gönderdiğinde 2. grupta olan bir priz bu mesajı dikkate almayacaktır.


Kumandadan yayınlanan kodları biraz daha irdeleyelim. Yukarıda bahsettiğim gibi ayarlanmış grubun kumandasından basılan numaralı devresine aç ya da kapat komutu gönderiliyor. Yani [GRUP_KODU][ANAHTAR_NUMARASI][/KAPAT][SENKRONLA] komutu gönderiliyor. [SENKRONLA] olarak yazdığım komut ise bu protokolde sonlandırma biti ya da syncronization bit olarak tabir ediliyor ve komutun bittiğini belirtmek için gönderiliyor.

Kod yayınında kullanılan başlıca komutlar:

Aç komutu: FF, Kapat Komutu: F0

Grup kodları ve anahtar numaraları için gönderilen kodlar aynı yapıdadır. 

1. Komutu = F0FFF
2. Komutu = FF0FF
3. Komutu = FFF0F
4. Komutu = FFFF0

Senkronlama Komutu = S

Bu bilgiler ışığında  4 numaralı grubun 2 numaralı anahtarını an mesaj [FFFF0FF0FFFFS] şeklinde olmaktadır.

Microframework destekli geliştirme kartı ile bilrlikte TX433 verici kullanıyorum. Vericinin frekansı ile kumandanınki aynı olmalıdır. Aksi halde iletişim kuramazsınız.  Geliştirme kartı ile verici arasındaki bağlantı aşağıdaki gibi olmalıdır. Resimde görünen kart arduino isimli başka bir karttır ancak bağlantı şekilleri itibari ile aynıdır. Benim kullandığım kart ise FEZ PANDA II dir.

Artık hardware moddan çıkıp software moda geçiş yapalım. 0,1,F ve S kodlamalarıyla yayın yapabilecek sınıfı aşağıdaki gibi tanımladım. SwitchOn ve SwitchOf ile istenilen grup numarası ve anahtar numarası açılıp kapatılıyor. Bu metotlar arkaplanda girilen grup numarasına ve anahtar numarasına göre GetCodeWord ve GetCodeWord2 metotlarıyla gönderilecek nihayi kodu oluşturuyor. (FFFF0F0FFFF0S gibi) ve ardından SendTriState ile kod yayınlanıyor.

 

namespace OMR.MF
{
    using System;
    using Microsoft.SPOT.Hardware;
    
    /// OMR
    public class RCSwitch
    {
        #region fields

        private OutputPort _pin;
        private int _delay;
        private int _repeat;

        #endregion

        #region ctor

        public RCSwitch(Cpu.Pin pin)
            : this(pin, 469, 10)
        { }

        public RCSwitch(Cpu.Pin pin, int delay, int repeat)
        {
            _repeat = repeat; // Tekrar sayısı
            _pin = new OutputPort(pin, false); // Sinyalin gönderileceği pin
            _delay = delay; // Gecikme miktarı
        }

        #endregion

        #region private

        // 0(sıfır) Sinyali 
        //  _      _
        // | |___| |___
        private void send0()
        {
            _pin.Write(true);
            delayMicroSeconds(_delay * 1);

            _pin.Write(false);
            delayMicroSeconds(_delay * 3);

            _pin.Write(true);
            delayMicroSeconds(_delay * 1);

            _pin.Write(false);
            delayMicroSeconds(_delay * 3);
        }

        // 1 (bir) Sinyali 
        //  __    __
        // |   |_|   |_
        private void send1()
        {
            _pin.Write(true);
            delayMicroSeconds(_delay * 3);

            _pin.Write(false);
            delayMicroSeconds(_delay * 1);

            _pin.Write(true);
            delayMicroSeconds(_delay * 3);

            _pin.Write(false);
            delayMicroSeconds(_delay * 1);
        }

		// F Sinyali 
        //  _      ___
        // | |___|   |_
        private void sendF()
        {
            _pin.Write(true);
            delayMicroSeconds(_delay * 1);

            _pin.Write(false);
            delayMicroSeconds(_delay * 3);

            _pin.Write(true);
            delayMicroSeconds(_delay * 3);

            _pin.Write(false);
            delayMicroSeconds(_delay * 1);
        }

        // Senkronizasyon Sinyali 
        //  _
        // | |__________
        private void sendSync()
        {
            _pin.Write(true);
            delayMicroSeconds(_delay * 1);

            _pin.Write(false);
            delayMicroSeconds(_delay * 31);
        }

        // Microsaniye seviyesinde bekleme işlemi için kullanılır
        private void delayMicroSeconds(int microSeconds)
        {
            var started = DateTime.Now;

            int ticks = microSeconds * 10;

            var diff = DateTime.Now - started;

            while (diff.Ticks <; ticks)
            {
                diff = DateTime.Now - started;
            }
        }

        // Yayınlanacak kodu oluşturan 1. metot
        private string GetCodeWord(int addressCode, int channelCode, bool status)
        {
            var code = new string[5] { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };

            if (addressCode <; 1 || addressCode >; 4 || channelCode <; 1 || channelCode >; 4)
                return string.Empty;

            var statusCode = status == true ? "FF" : "F0";

            return code[addressCode] + code[channelCode] + "FF" + statusCode + "S";
        }

        // Yayınlanacak kodu oluşturan 2. metot
        private string GetCodeWord2(string group, int channelCode, bool status)
        {
            var code = new string[6] { "FFFFF", "0FFFF", "F0FFF", "FF0FF", "FFF0F", "FFFF0" };

            if (group.Length != 5 || channelCode <; 1 || channelCode >; 5)
            {
                return string.Empty;
            }

            string addressCode = string.Empty;

            for (int i = 0; i <; 5; i++)
            {
                if (group[i] == '0')
                    addressCode += 'F';
                else
                    addressCode += '0';
            }

            var statusCode = status == true ? "FF" : "F0";

            return string.Concat(addressCode, code[channelCode], statusCode, "S");
        }

        #endregion

        #region public

        // Anahtarı aç
        public void SwitchOn(int addressCode, int channelCode)
        {
            var s = GetCodeWord(addressCode, channelCode, true);
            SendTriState(s);
        }

        // Anahtarı aç
        public void SwitchOn(string group, int channel)
        {
            var s = GetCodeWord2(group, channel, true);
            SendTriState(s);
        }

        // Anahtarı kapat
        public void SwitchOff(int addressCode, int channelCode)
        {
            var s = GetCodeWord(addressCode, channelCode, false);
            SendTriState(s);
        }

        // Anahtarı kapat
        public void SwitchOff(string group, int channel)
        {
            var s = GetCodeWord2(group, channel, false);
            SendTriState(s);
        }

        // Oluşturulan yayın kodunu yayınlamaktan sorumlu metot
        public void SendTriState(string codeWord)
        {
            for (int r = 0; r <; _repeat; r++)
            {
                for (int i = 0; i <;= 12; i++)
                {
                    switch (codeWord[i])
                    {
                        case '0':
                            send0();
                            break;
                        case 'F':
                            sendF();
                            break;
                        case '1':
                            send1();
                            break;
                        case 'S':
                            sendSync();
                            break;
                        default:
                            throw new Exception("Invalid code char");
                            break;
                    }
                }
            }
        }      

        #endregion
    }
}

 

Geliştirme kartından bu sınıfı aşağıdaki gibi çağırmamız artık mümkün. Kodlama deli misali lambaları 4. grup 2.anahtarı 2 saniye aralıklarla yakıp söndürür.

 

using System.Threading;

using GHIElectronics.NETMF.FEZ;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using OMR.MF;

namespace tx1
{
    public class Program
    {
        static RCSwitch rf = new RCSwitch((Cpu.Pin)FEZ_Pin.Digital.Di9, 350, 10); // 9. pin, Delay süresi 350ms, 10 kere tekrarlı

        public static void Main()
        {
            while (true)
            {
                Switch(4, 2, true); // 4. Grubun 2. anahtarını aç

                Thread.Sleep(2000); // 2sn bekle

                Switch(4, 2, false); // 4. Grubun 2. anahtarını kapat
                
                Thread.Sleep(2000); // 2 saniye bekle
            }
        }

        static void Switch(int group, int chanel, bool s)
        {
            Debug.Print(s + ": " + group + "-" + chanel); // Çağırılan kodu debug çıktısına yazdır

            if (s) // Aç / Kapat
            {
                rf.SwitchOn(group, chanel); 
            }
            else
            {
                rf.SwitchOff(group, chanel);
            }
            
        }

    }
}

 

Sonuç itibari ile artık yönetebildiğimiz bir uzaktan kumandamız olduğuna göre artık gerisi sizin gönlünüze ve hayal gücünüze kalmış derim. RCSwitch.cs kaynak kodunu http://code.google.com/p/rc-switch/downloads/list adresinden kısa bir süre önce yayınladım. Aynı yerde c++ geliştiricilerinin kullanımına açık olan sınıf da mevcuttur. Faydalı olması dileğiyle, sevgiler...