Netduino ve WPF İle Direnç Ölçme

Volkan AKTAŞElektronik, Micro Framework, Netduino, WPF1 Yorum21 Şubat 2014

ftdi_kabloNetduino üzerinde bulunan analog pinlerden yararlanarak direnç ölçümü yapabiliriz. Örneğimizde 1K-100 K arası direnç ölçümü yapmaktayız.  Bunun için netduino ile ölçülen direnç değerini FTDI kablosunu kullanarak seri porttan bilgisayara göndereceğiz. FTDI kablosu USB’den seriye dönüşüm sağlamaktadır.  Bu kabloyu kullanarak usb port üzerinden bilgisayarda yaptığınız masaüstü uygulamalar ile netduinonun haberleşmesini sağlayabilirsiniz.

 

 

ftdi_pinoutKablonun bir yüzünde A tipi USB konnektör diğer yüzünde ise standart pinlere uyumlu 6 pinli konnektör bulunmaktadır.Örnek uygulamamızda UART protokolünü kullanarak iletişim kuracağız. Bunun için turuncu renkli kablo (TX), netduino’nun D0 nolu pinine (RX), sarı renkli kablo (RX) ise, netduino’nun D1 nolu pinine (TX) bağlanır. Siyah renkli kabloyu da (GND),  netduino üzerindeki GND pinine bağlıyoruz.

direnc_olcmeUygulamamızda WPF uygulaması üzerinden netduino’nun analog pinlerinden birine bağlı direnç değerini ölçeceğimiz için A0 pinine ölçeceğimiz direnci bağlıyoruz (Vout).  Direnç ölçümünü yaparken diğer bir referans direnci kullanarak direnç değerini ölçebilmekteyiz. Örnek uygulamamızda 1-100K aralığında direnç değerlerini ölçeceğimiz için 10K değerinde bir referans direnç değeri kullandık. Referans direncin bir ucu şaseye bağlanırken diğer ucu ölçeceğimiz dirence bağlanmaktadır. Ölçeceğimiz direncin ise bir ucu referans dirence bağlanırken diğer ucu +5V’a bağlanmaktadır. Referans direnç ile ölçeceğimiz direncin birleşim noktasını ise netduino üzerindeki A0 pinine götürmekteyiz.

 

 

 

 

 

Netduino içerisine aşağıdaki kod satırlarını yazıyoruz:

 

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using System.IO.Ports;
namespace DirencOlcme_NP2
{
    public class Program
    {
        static SerialPort port;
        public static void Main()
        {
            AnalogInput A0 = new AnalogInput(Cpu.AnalogChannel.ANALOG_0);
            port = new SerialPort("COM1", 9600, Parity.None, 
8, StopBits.One);
            port.Open();
            AnalogInput direnc = new 
AnalogInput(AnalogChannels.ANALOG_PIN_A0);
            double raw = 0;         
            double Vin = 5;         
            double Vout = 0;        
            double R2 = 10;         
            double R1 = 0;          
            double buffer = 0;      
            byte[] bytes = new byte[1];
            while (true)
            {
                raw = direnc.ReadRaw();    
                Vout = (5.0 / 1023.0) * raw;    
                buffer = (Vin / Vout) - 1;
                R1 = R2 / buffer;

                Debug.Print("Direnç değeri = " + (R1).ToString());     
                bytes = Encoding.UTF8.GetBytes(R1.ToString("f1"));
                port.Write(bytes, 0, bytes.Length);
                Thread.Sleep(1000);
            }        }  
    }
}

Kodumuzda

port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);

satırında port ismi ile tanımlamış olduğumuz seri port nesnesinin parametrelerini belirliyoruz.

Seri Port nesnesi

SerialPort(Port İsmi, Baud Rate, Parity Biti, Data Biti, Stop Biti)

Şeklinde kullanılır.

Baud Rate: Veri iletişim hızını belirtir. Hız değerleri saniyedeki bit sayısını ifade eder. Varsayılan değer 9600’dür.

Parity (Eşlik) Biti:  Gönderilen verinin hatalı olup olmadığını kontrol etmek amacıyla kullanılır. Alabileceği değerler şunlardır:

Data Biti: Veri uzunluğunu belirlemek için kullanılır. 5 ile 8 arasında bir değer alabilir. 8 değeri bir byte’ın uzunluğuna denk gelip hemen her türlü veri için kullanılabilmektedir.

Stop (Durma) Biti: Yeni bir veri gönderilmeden önce stop bitinin gönderilmesi gerekmektedir. Genellikle tek bitlik durma biti kullanılmaktadır.

byte[] bytes = new byte[1];

satırında seri porttan okuyacağımız verileri saklayacağımız byte dizisini tanımlıyoruz. Tek bir byte okuyarak üzerinde işlem gerçekleştireceğimiz için byte dizisini bir elemanlı olarak tanımlıyoruz.

Daha sonra while(true) şeklinde sürekli bir döngü kurarak

raw = direnc.ReadRaw();    
Vout = (5.0 / 1023.0) * raw;    
buffer = (Vin / Vout) - 1;
R1 = R2 / buffer;

Satırlarında okunan direnç değerini hesaplıyoruz.
raw değişkeni analog porttan okunan değeri, Vin + giriş voltajı değerini (+5V için 5 değeri), Vout çıkış voltajı değerini, R2 referans direnç değerini(10 K R2 referans direnç değeri için 10 değeri), R1 ölçülecek direnç değerini, buffer ise hesaplama işleminde kullanılacak geçici değeri ifade etmektedir.

bytes = Encoding.UTF8.GetBytes(R1.ToString("f1"));
port.Write(bytes, 0, bytes.Length);

R1 değişkeni içerisinde saklanan verileri Encoding.UTF8.GetBytes metodu ile byte türüne dönüştürerek bytes isimli byte dizisi içerisinde saklıyor ve daha sonra Write metodu ile seri porta yazıyoruz. Write metodunun kullanımı aşağıdaki gibidir:
Write(buffer , offset, sayı)
Buffer: Seri porta yazılacak değerlerin saklandığı dizi değişkenini belirtir.
Offset: Verilerin dizinin hangi elemanından itibaren ekleneceğini belirtir. 0 değeri dizinin ilk elemanından itibaren ekleme yapılacağını belirtir.
Sayı: Kaç byte’lık veri yazılacağını belirtir.

Thread.Sleep(1000);

Satırı ile okuma işleminin 1000 ms (1 saniye) aralıklarla gerçekleştirilmesini sağlıyoruz.

netduino_direnc_okuma_wpf_tasarım_izahlıMasaüstü uygulamamız için yeni bir C# WPF uygulaması açıyoruz. Form tasarımı yandaki gibi olacak:
1) cmbCOMPort
2) btnPortAc
3) btnPortKapat
4) btnOku
5) Commdata
6) DirencRes
7) b1
8) b2
9) b3

Kodumuz ise aşağıdaki gibi olacak:

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace DirencOlcme
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();              
    }
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {            
      DirencRes.Source = new BitmapImage(new 
Uri(AppDomain.CurrentDomain.BaseDirectory + "\\resbody.png"));            
      foreach (string portname in SerialPort.GetPortNames())
          cmbCOMPort.Items.Add(portname);
    }

    SerialPort serialPort1 = new SerialPort();
    string recieved_data;
    FlowDocument mcFlowDoc = new FlowDocument();
    Paragraph para = new Paragraph();
    private void btnPortAc_Click(object sender, RoutedEventArgs e)
    {
      serialPort1.PortName = cmbCOMPort.Text;
      serialPort1.NewLine = "\r\n";
      if (!serialPort1.IsOpen)
          serialPort1.Open();
    }
    private void btnPortKapat_Click(object sender, RoutedEventArgs e)
    {
      if (serialPort1.IsOpen)
      {
        serialPort1.DataReceived -= new 
System.IO.Ports.SerialDataReceivedEventHandler(Recieve);
        serialPort1.Close();
      }
    }
    private void btnOku_Click(object sender, RoutedEventArgs e)
    {
      serialPort1.DataReceived += new 
System.IO.Ports.SerialDataReceivedEventHandler(Recieve);
    }
    private delegate void UpdateUiTextDelegate(string text);
    private void Recieve(object sender, 
System.IO.Ports.SerialDataReceivedEventArgs e)
    {       
      recieved_data = serialPort1.ReadExisting().Trim();          
      if ((Regex.Matches(recieved_data, "-").Count == 1) & 
(recieved_data.Length>1))
      {              
        Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(WriteData), recieved_data);
      }          
    }
    private void WriteData(string text)
    {
      Commdata.SelectAll();
      Commdata.Selection.Text = "";
      if (text.Contains("."))
      {
        int nokta = text.IndexOf(".");
        para.Inlines.Add(text.Substring(1, text.Length - 3));
      }
      else
        para.Inlines.Add(text);

      mcFlowDoc.Blocks.Add(para);            
      Commdata.Document = mcFlowDoc;           
    }
    private void Commdata_TextChanged(object sender, TextChangedEventArgs 
e)
    {            
      TextRange rangeData = new TextRange(Commdata.Document.ContentStart, 
Commdata.Document.ContentEnd);
      if(!rangeData.IsEmpty)
      {
        if (rangeData.Text.Trim().Length == 1)
        {
          switch (rangeData.Text.Substring(1, 1))
          {
            case "0":
              b1.Background = new SolidColorBrush(Colors.Black);
              break;
            case "1":
              b1.Background = new SolidColorBrush(Colors.Brown);
              break;
            case "2":
              b1.Background = new SolidColorBrush(Colors.Red);
              break;
            case "3":
              b1.Background = new SolidColorBrush(Colors.Orange);
              break;
            case "4":
              b1.Background = new SolidColorBrush(Colors.Yellow);
              break;
            case "5":
              b1.Background = new SolidColorBrush(Colors.Green);
              break;
            case "6":
              b1.Background = new SolidColorBrush(Colors.Blue);
              break;
            case "7":
              b1.Background = new SolidColorBrush(Colors.Purple);
              break;
          }
          b2.Background = new SolidColorBrush(Colors.Black);
          b3.Background = new SolidColorBrush(Colors.Red);
        }
        if ((rangeData.Text.Trim().Length == 2) | 
(rangeData.Text.Trim().Length == 3))
        {
          switch (rangeData.Text.Substring(0, 1))
          {
            case "0":
              b1.Background = new SolidColorBrush(Colors.Black);
              break;
            case "1":
              b1.Background = new SolidColorBrush(Colors.Brown);
              break;
            case "2":
              b1.Background = new SolidColorBrush(Colors.Red);
              break;
            case "3":
              b1.Background = new SolidColorBrush(Colors.Orange);
              break;
            case "4":
              b1.Background = new SolidColorBrush(Colors.Yellow);
              break;
            case "5":
              b1.Background = new SolidColorBrush(Colors.Green);
              break;
            case "6":
              b1.Background = new SolidColorBrush(Colors.Blue);
              break;
            case "7":
              b1.Background = new SolidColorBrush(Colors.Purple);
              break;
            }
            if (rangeData.Text.Trim().Length == 2)
            {
              switch (rangeData.Text.Substring(1, 1))
              {
                case "0":
                  b2.Background = new SolidColorBrush(Colors.Black);
                  break;
                case "1":
                  b2.Background = new SolidColorBrush(Colors.Brown);
                  break;
                case "2":
                  b2.Background = new SolidColorBrush(Colors.Red);
                  break;
                case "3":
                  b2.Background = new SolidColorBrush(Colors.Orange);
                  break;
                case "4":
                  b2.Background = new SolidColorBrush(Colors.Yellow);
                  break;
                case "5":
                  b2.Background = new SolidColorBrush(Colors.Green);
                  break;
                case "6":
                  b2.Background = new SolidColorBrush(Colors.Blue);
                  break;
                case "7":
                  b2.Background = new SolidColorBrush(Colors.Purple);
                  break;
               }
               b3.Background = new SolidColorBrush(Colors.DarkOrange);
             }                    
            }
        }
    }      

  }
}

Kodumuzda formun Load olayı içerisinde

foreach (string portname in SerialPort.GetPortNames())
            cmbCOMPort.Items.Add(portname);

satırları ile foreach döngüsü içerisinde GetPortNames metodu ile bilgisayarda yüklü olan seri port isimlerini elde ederek comboBox içerisine ekliyoruz.

serialPort1.PortName = cmbCOMPort.Text;
if (!serialPort1.IsOpen)
    serialPort1.Open();

Satırlarında comboBox içerisinde seçili olan port ismini PortName özelliğine aktarıyoruz. IsOpen özelliği portun açık olup olmadığını belirtir. Eğer açıksa geriye true değeri, açık değilse false değeri dönmektedir. Kodumuzda (!) operatörü ile bu işlemin tersini alarak, port açık değilse Open metodu ile portun açılmasını sağlıyoruz. Aynı işlemi portu kapatmak için de uygulayarak pert açıksa Close metodu ile portun kapatılmasını sağlıyoruz.

if (serialPort1.IsOpen)
{
  serialPort1.DataReceived -= new 
System.IO.Ports.SerialDataReceivedEventHandler(Recieve);
  serialPort1.Close();
}

satırlarında ise eventhandler ile daha önce eklenen Receive metodunu çıkartarak, eğer seri port açıksa seri portun kapatılmasını sağlıyoruz.
Seri porttan değer okuma işlemini Receive metodu içerisinde yazıyoruz. Receive metodunu çağırmak için gerekli delegate’i ise

private delegate void UpdateUiTextDelegate(string text);

satırında tanımlıyoruz.

recieved_data = serialPort1.ReadExisting().Trim();

satırında ReadExisting metodu ile seri porttan veri okuyoruz.

if ((Regex.Matches(recieved_data, "-").Count == 1) 
	& (recieved_data.Length>1))

Satırında Regular Expressions (Düzenli ifadeler) yapısı içerisindeki Matches metodunu kullanarak içerik kontrolü yapıyoruz ve porttan gelen içeriğin bizim için gerekli değere sahip olmadığını kontrol ediyoruz.

Dispatcher.Invoke(DispatcherPriority.Send, new 
	UpdateUiTextDelegate(WriteData), recieved_data);

Satırında WriteData isimli metodun tetiklenmesini sağlıyoruz. Böylece porta her veri geldiğinde WriteData isimli metod tetiklenerek çalıştırılacaktır.
Seri porttan okunan değerleri uygulamamızda RichTextBox kontrolü içerisine ekleyeceğiz. RichTextBox kontrolü içerisine değer eklemek için

FlowDocument mcFlowDoc = new FlowDocument();
Paragraph para = new Paragraph();
para.Inlines.Add(text);            
mcFlowDoc.Blocks.Add(para);            
Commdata.Document = mcFlowDoc;

Satırlarını kullanıyoruz. para değişkeni CommData isimli RichTextBox içerisine eklenecek paragrafı temsil etmektedir. Bu paragraf nesnesi içerisine seri porttan okunan değeri text değişkeni ile ekliyoruz. Daha sonra mcFlowDoc isimli bir FlowDocument nesnesi kullanarak paragraf nesnesini FlowDocument içerisine Block.Add metodu ile ekliyoruz. Son olarak RichTexBox’ın Document özelliğine mcFlowDoc isimli FlowDocument nesnesini aktararak RichTextBox içerisine seri porttan okunan değeri eklemiş oluyoruz.
RichTextBox’ın TextChanged olayını kullanarak içerisindeki direnç değerine göre b1,b2,b2 isimli label nesnelerinin zemin renklerini değiştireceğiz.
RichTextBox içerisine eklenmiş olan değeri seçmek için

TextRange rangeData = new 
  TextRange(Commdata.Document.ContentStart, Commdata.Document.ContentEnd);

Kod satırını kullanıyoruz.
Eğer direnç değerimiz 1-10 K arası bir değer olacaksa

if (rangeData.Text.Trim().Length == 1)
{
         switch (rangeData.Text.Substring(1, 1))

Satırları çalışacaktır. Bu değerlere sahip dirençlerde son 2 bant rengi kırmızı ve siyah olacağı için switch bloğuna

b2.Background = new SolidColorBrush(Colors.Black);
b3.Background = new SolidColorBrush(Colors.Red);

Eğer 10K’dan büyük bir direnç değeri varsa

if ((rangeData.Text.Trim().Length == 2) | 
	(rangeData.Text.Trim().Length == 3))

kod satırları çalıştırılacaktır. Eğer 2 band rengine sahip bir direnç ise

switch (rangeData.Text.Substring(0, 1))

satırı
3 band değerine sahip bir dirençse

switch (rangeData.Text.Substring(1, 1))

satırı çalıştırılacaktır.
3 band rengine sahip dirençte 3. bant direnç değerinin sonuna eklenecek 0 sayısını belirteceği için switch bloğuna

b3.Background = new SolidColorBrush(Colors.DarkOrange);

satırını ekliyoruz.

Dispatcher.Invoke(DispatcherPriority.Send, new 
	UpdateUiTextDelegate(WriteData), recieved_data);

Satırında
Uygulamamızı çalıştırdığımızda okunan direnç değeri renkleriyle beraber uygulamamız içerisinde görüntülenecektir.
netduino_direnc_okuma

Uygulama dosyasının linki

Etiketler: , , ,

Netduino ve WPF İle Direnç Ölçme Hakkında Yapılan Yorumlar

  1. Cenkay diyor ki:

    Hocam emeğinize sağlık. WPF ile yapılabilinen bu kadar gelişmiş uygulamalar görünce sadece c# bilsek her işimize yeter diyoruz 😉

Netduino ve WPF İle Direnç Ölçme Hakkında Yorum Yaz

Sponsor Reklam Sponsor Reklam Sponsor Reklam Sponsor Reklam

Son Yorumlar

En çok Tıklananlar

Site İstatistikleri

Yandex.Metrica