MSP430 Launchpad – İnternetten Sıcaklık Yayını

Bu uygulamada MSP430’un dahili sıcaklık sensörü ile ölçülen sıcaklığı internet üzerinden yayınlayacağız. Bunun için bir önceki yazımda paylaştığım seri haberleşme kodunda ufak bir değişiklik yaptım. Bilgisayar tarafında ise bir terminal programı değil de, bu proje için C# ile yazdığım bir programı kullanacağız. İnternetten yayın yapmak için de PHP ile hazırlanmış bir sayfa ve gelen sıcaklık verilerini saklamak için MySQL veritabanı kullanacağız. Uygulamanın ev otomasyonu konusunda küçük bir başlangıç olabileceğini düşünüyorum.

Öncelikle kodların daha anlaşılabilir olması için sistemin nasıl işlediğinden bahsedeyim. Bilgisayar uygulamasında “Şimdi ölç” butonuna basıldığında ya da ayarlanan süre aralıklarında bilgisayardan MSP430’a seri port aracılığıyla bir veri (‘1’ karakteri) gönderiliyor. MSP430 veriyi aldığında (verinin ne olduğunun önemi yok) dahili sensörüyle sıcaklığı ölçüp, seri port ile bilgisayara geri gönderiyor. Sıcaklık verisini alan bilgisayar uygulaması, bu veriyi GET yöntemiyle internetteki PHP sayfasına gönderiyor. PHP sayfası, aldığı bu veriyi zaman bilgisiyle birlikte veritabanına kaydediyor ve veritabanına en son kaydedilen bilgiyi gösteriyor.

#include "io430.h"
#include "in430.h"
#include "stdbool.h"

bool rs232Alinacak = 0;      // Veri alınacak mı?
bool rs232Alindi = 0;        // Veri alındı mı?
bool rs232Gonderilecek = 0;  // Veri gönderilecek mi?
int rs232Bit = 0;           // O an kaçıncı bit işlem görüyor?
int rs232Gelen = 0;         // Gelen veri.
int rs232Giden = 0;         // Giden veri.

void rs232Gonder(int);      // Veriyi gönderime hazırlayan fonksiyon.

void main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;

  P1DIR = 0x02;           // P1.1 (TXD) çıkış.
  P1OUT = 0x02;           // P1.1 idle durumda "1" olmalı.
  P1IE = 0x04;            // P1.2 (RXD)'den kesme gelecek.
  P1IES = 0x04;           // Kesme düşen kenarda gelecek. (Start biti)
  TACCR0 = 108;           // 1000000/9600 = 104. Kritik zamanlama olmaması için biraz arttırdım.
  TACCTL0 = CCIE;         // Timer kesmesine izin ver.
  __enable_interrupt();   // Genel kesmelere izin ver.
  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON;  // Vref = 1,5V + SHT = x64
  ADC10CTL1 = INCH_10 + ADC10DIV_3;   // Sıcaklık sensörü + Div = 3

  int sicaklik = 0;
  int birlerBasamagi = 0;
  int onlarBasamagi = 0;

  while(1)                      // Sonsuz döngü içinde,
  {
    if(rs232Alindi)             // Veri alındıysa,
    {
      rs232Alindi = 0;          // Alındı bayrağını temizle.

      ADC10CTL0 |= ENC + ADC10SC;   // ADC dönüşümünü başlat

      sicaklik = ((ADC10MEM - 673) * 423) / 1024;   // ADC'den gelen değere göre sıcaklık hesaplandı.
      onlarBasamagi = sicaklik / 10 + 48;  // Sıcaklık basamaklarına ayrılıyor.
      birlerBasamagi = sicaklik % 10 + 48;

      rs232Gonder(onlarBasamagi);   // Onlar basamağını gönder.
      while(rs232Gonderilecek);     // Onlar basamağı gidene kadar bekle.
      rs232Gonder(birlerBasamagi);  // Birler basamağını gönder.

    }
  }

}

void rs232Gonder(int rs232GidenFonk)
{
  if(rs232Gonderilecek == 0)      // Eğer o anda veri gönderilmiyorsa,
  {
    rs232Giden = rs232GidenFonk;  // Fonksiyona gönderilen değeri global giden değişkenine al.
    rs232Giden = rs232Giden << 1; // 1 bit sola kaydırarak start biti eklendi.
    rs232Giden += 512;            // En sola stop biti eklendi.
    rs232Gonderilecek = 1;        // Gönderilecek bayrağı set edildi.
    rs232Bit = 0;                 // 0. bitten başlanacak.
    TACTL = TASSEL_2 + ID_0 + MC_1 + TACLR;   // SMCLK + Div = 1 + Up mod + Sıfırla.
  }
}

#pragma vector = PORT1_VECTOR
__interrupt void portKesmesi (void)
{
  if(P1IFG_bit.P1IFG_2)       // Kesme P1.2'den geldiyse,
  {
    if(rs232Alinacak == 0)    // Eğer o anda veri alınmıyorsa,
    {
      rs232Gelen = 256;       // Gelen veriyi 256 yap. Bu şekilde bit bit kaydırırken olası sıkıntı engellenecek.
      rs232Alinacak = 1;      // Alınacak bayrağını 1 yap.
      rs232Bit = 0;           // 0. bitten başlanacak.
      TACTL = TASSEL_2 + ID_0 + MC_1 + TACLR;   // SMCLK + Div = 1 + Up mod + Sıfırla
    }
    P1IFG_bit.P1IFG_2 = 0;    // P1.2 kesme bayrağını temizle.
  }
}

#pragma vector = TIMERA0_VECTOR
__interrupt void timerKesmesi (void)
{
  if(rs232Alinacak == 1)              // Eğer veri alınacaksa,
  {
    if(rs232Bit < 9)                  // Toplam 9 bit alınacak. 8 bit veri + 1 stop biti.
    {       rs232Gelen = rs232Gelen >> 1;   // Zaman geldiğinde gelen veriyi 1 bit sağa kaydır,
      if(P1IN_bit.P1IN_2 == 1)        // Eğer bit "1" ise,
      rs232Gelen += 256;              // Gelen verinin en soldaki bitine 1 yaz. (2^8, 8. bit)
    }
    else                              // 9 bit de alındıysa,
    {
      TACTL = MC_0;                   // Timerı durdur.
      rs232Gelen -= 256;              // Veriden stop bitini ayıkla.
      rs232Alinacak = 0;              // Alınacak bayrağını "0" yap.
      rs232Alindi = 1;                // Alındı bayrağını "1" yap.
    }
  }

  if(rs232Gonderilecek == 1)
  {
    if(rs232Bit < 10)   // Toplam 10 bit gidecek. 8 bit veri + 1 start biti + 1 stop biti.
    {
      P1OUT_bit.P1OUT_1 = rs232Giden & BIT0;  // Giden verinin 0. bitini P1.1'e bas.
      rs232Giden = rs232Giden >> 1;           // Giden veriyi 1 bit sağa kaydır.
    }
    else                      // Eğer 10 bit de gönderilmişse,
    {
      TACTL = MC_0;           // Timerı durdur.
      rs232Gonderilecek = 0;  // Gönderilecek bayrağını sıfırla.
    }
  }
  rs232Bit++;       // Zaman geldikçe kaçıncı bitte olduğumuz artacak.
}

Bilgisayar uygulamasının kaynak kodları :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace rs232_2
{

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            timer1.Stop();
            şimdiÖlçToolStripMenuItem.Enabled = false;

            try
            {
                StreamReader dosya;
                dosya = File.OpenText("ayarlar.txt");

                site.Text = dosya.ReadLine();
                port.Text = dosya.ReadLine();
                baudrate.Text = dosya.ReadLine();
                dakika.Text = dosya.ReadLine();
                dosya.Close();

                webBrowser1.Navigate(site.Text);
            }
            catch
            {
                MessageBox.Show("Ayar dosyası yok, ya da dosya okunamadı. Lütfen gelecek pencerede ayarlarınızı girdikten sonra \"Ayarları Kaydet\" butonuna basınız.");
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            string sicaklik, randStr;
            int rnd;
            Random randnum = new Random();

            if (serialPort1.IsOpen)
            {
                serialPort1.Write("1");
                sicaklik = Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));
                sicaklik += Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));

                rnd = randnum.Next(100000, 999999);

                randStr = rnd.ToString();

                webBrowser1.Navigate("http://" + site.Text + "?sicaklik=" + sicaklik + "&rand=" + randStr);

                }
            else {
                MessageBox.Show("Bağlantı hatası!");
            }

        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            string sicaklik, randStr;
            int rnd;
            Random randnum = new Random();

            if (serialPort1.IsOpen)
            {
                serialPort1.Write("1");
                sicaklik = Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));
                sicaklik += Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));

                rnd = randnum.Next(100000, 999999);

                randStr = rnd.ToString();

                webBrowser1.Navigate("http://" + site.Text + "?sicaklik=" + sicaklik + "&rand=" + randStr);

                }
            else
            {
                MessageBox.Show("Bağlantı hatası!");
            }

        }

        private void baglan_Click(object sender, EventArgs e)
        {
            string sicaklik, randStr;
            int rnd;
            Random randnum = new Random();

            serialPort1.BaudRate = Convert.ToInt32(baudrate.Text);
            serialPort1.PortName = "COM" + port.Text;
            try
            {
                serialPort1.Open();
                button1.Enabled = true;
                kes.Enabled = true;
                baglan.Enabled = false;
                port.Enabled = false;
                baudrate.Enabled = false;
                guncelle.Enabled = true;
                kaydet.Enabled = false;
                site.Enabled = false;
                şimdiÖlçToolStripMenuItem.Enabled = true;
                timer1.Interval = Convert.ToInt32(dakika.Text) * 1000 * 60;

                serialPort1.Write("1");
                sicaklik = Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));
                sicaklik += Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));

                rnd = randnum.Next(100000, 999999);

                randStr = rnd.ToString();

                webBrowser1.Navigate("http://" + site.Text + "?sicaklik=" + sicaklik + "&rand=" + randStr);
                timer1.Start();
            }

            catch
            {
                MessageBox.Show("Bağlantı kurulamadı. Lütfen ayarlarınızı denetleyin.");
            }

        }

        private void kes_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            serialPort1.Close();
            button1.Enabled = false;
            kes.Enabled = false;
            baglan.Enabled = true;
            baudrate.Enabled = true;
            port.Enabled = true;
            guncelle.Enabled = false;
            kaydet.Enabled = true;
            site.Enabled = true;
            şimdiÖlçToolStripMenuItem.Enabled = false;
        }

        private void guncelle_Click(object sender, EventArgs e)
        {
            timer1.Interval = Convert.ToInt32(dakika.Text) * 1000 * 60;
        }

        private void kaydet_Click(object sender, EventArgs e)
        {
            try
            {
                StreamWriter dosya = new StreamWriter("ayarlar.txt");
                dosya.WriteLine(site.Text);
                dosya.WriteLine(port.Text);
                dosya.WriteLine(baudrate.Text);
                dosya.WriteLine(dakika.Text);
                dosya.Close();
                MessageBox.Show("Ayarlarınız başarıyla kaydedildi.");
            }
            catch
            {
                MessageBox.Show("Ayar dosyasına yazılamadı.");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Hide();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Show();
        }

        private void gösterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Show();
        }

        private void çıkışToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Close();
        }

        private void şimdiÖlçToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string sicaklik, randStr;
            int rnd;
            Random randnum = new Random();

            if (serialPort1.IsOpen)
            {
                serialPort1.Write("1");
                sicaklik = Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));
                sicaklik += Convert.ToString(Convert.ToChar(serialPort1.ReadChar()));

                rnd = randnum.Next(100000, 999999);

                randStr = rnd.ToString();

                webBrowser1.Navigate("http://" + site.Text + "?sicaklik=" + sicaklik + "&rand=" + randStr);

            }
            else
            {
                MessageBox.Show("Bağlantı hatası!");
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.berkbaykal.com/blog");
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.mcu-turkey.com");
        }

    }
}
Uygulamanın ekran görüntüsü

Uygulamanın ekran görüntüsü

Aşağıdaki linkte C# proje dosyasını bulacaksınız. Projeyi Visual Studio 2010 ile açarak istediğiniz değişiklikleri yapabilirsiniz. Ya da direkt olarak bin klasöründeki Debug veya Release klasörleri içindeki rs232-2.exe dosyasını açarak uygulamayı başlatabilirsiniz. Programın kullanımı oldukça basit. Ayarlarınızı girip Bağlan butonuna bastığınızda, bir sorun yoksa RS232 bağlantısı kuruluyor. Daha sonra ayarladığınız süre aralıklarında ya da Şimdi Ölç butonuna bastığınızda sıcaklık ölçülerek internette yayınlanmakta. Süreyi uygulama çalışırken değiştirmek isterseniz yeni süreyi girip Süre Güncelle butonuna basmanız yeterli. Programı sistem tepsisine küçültmek için ise Gizle butonunu kullanabilirsiniz.

PHP kodu :

ini_set("display_errors", "Off");

$db_host = "localhost";
$db_username = "root";
$db_password = "";
$db_name = "sicaklik";

$db_baglan = mysql_connect("$db_host", "$db_username", "$db_password") or die('Veritabanı bağlantısı kurulamadı. Hata : '.mysql_error());
mysql_select_db("$db_name", $db_baglan) or die('Veritabanı seçerken hata oluştu. Hata : '.mysql_error());
mysql_query("SET NAMES 'utf8'");

if($_GET['sicaklik'])
{
 $sicaklik = $_GET["sicaklik"];
 mysql_query("insert into sicaklik(sicaklik, zaman) values('$sicaklik', NOW())");
 header("Refresh: 0 url = sicaklik.php");
}

$sql = mysql_query("select * from sicaklik order by zaman desc limit 0, 1");

print "Son ölçülen sıcaklık : ".mysql_result($sql, 0, "sicaklik")." derece.<br>Ölçüm zamanı : ".date("d.m.Y H:i:s", strtotime(mysql_result($sql, 0, "zaman")));

PHP ile çalışabilmek için PHP destekli bir sunucu kullanmalısınız. Ya da kendi bilgisayarınıza bir PHP sunucusu kurabilirsiniz. Ben kendi bilgisayarımda “XAMPP Server” kullanıyorum. MySQL bağlantısı için de db_host, db_username, db_password, db_name değişkenlerini kendi ayarlarınıza göre düzenlemelisiniz. XAMPP Server kullanacaksanız bu ayarlar muhtemelen sizde de aynı olacaktır. Ancak dışarıdaki bir sunucu üzerinde çalışıyorsanız bu ayarlar farklılık gösterebilir.

Sıcaklık bilgilerini takip etmek için http://localhost/sicaklik.php şeklinde sayfaya erişebilirsiniz. Ayrıca sıcaklık bilgileri veritabanında tutulduğu için, istenirse ileride incelenebilir veya çeşitli amaçlarla kullanılabilir.

MSP430 ve C# proje dosyalarını, PHP dosyasını ve veritabanını oluşturmak için SQL dosyasını buradan indirebilirsiniz.

Kolay gelsin…

Share
  1. Satir 41 deki hesaplamalar neye gore nasil yapiliyor acaba? 673, 423 ve 1024 degerleri nedir?

    sicaklik = ((ADC10MEM – 673) * 423) / 1024;   // ADC’den gelen değere göre sıcaklık hesaplandı

    Tesekkurler

    • O hesaplar denetleyicinin datasheetinde yer alan sıcaklık sensörü ile ilgili parametreler dikkate alınarak yapıldı. 1024, ADC 10 bitlik olduğu için kullanıldı, diğerleri yine bu sensörün özellikleri ile ilgili çıkarılan değerler.

Yorum Yap


Not - Bunları KullanabilirsinizHTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>