C# arduino bağlantısı - Ekg sensör

Başlatan noob, 21 Aralık 2013, 20:44:14

noob

Merhabalar.
Forumda çok yeniyim. Pic proje geliştirmekte de yeniyim sayılır. Bitirme ödevimi yapmak için sizlerden yardım almak istedim.
Ödevim ekg sensörünü arduino ya bağlayıp arduinoda programlayarak sonuçları c# ta tasarlayacağım arayüzde göstermek. arduino programlama kısmını hallettim sayılır bir kaç eksiği var ama az kaldı fakat c # hakkında çok bir bilgim yok. Tasarlayacağım arayüzde nabzı nasıl göstericem hangi kütüphaneyi kullanmam gerekiyor, form'a hangi göstergeyi koyucam hiç bilmiyorum. İnternette 2 gündür araştırıyorum ama pek bir şey bulamadım. Bu konuda sizlerin yardımınızı bekliyorum.

olemiss

Bu projenin iki alt kısmı bulunuyor: Arduino, ve PC arayüzü.  Ayrıca bu iki alt sistemin kullanacağı ortak protokol.  Siz Arduino ile C# arasındaki bu protokolden hiç söz etmemişsiniz?

"C# arayüzünde ne gösterilecek" sorusunun cevabı belli: Arduino'dan hangi veriler gönderiliyorsa, onlar gösterilecek.  Sizin yerinizde olsam, öncelikle bu verileri basit bir C# console programı ile DOS ekranına yazdırırdım.  Böylece protokol kısmını hallettikten sonra, GUI arayüzün tasarımına geçerdim.



Yazılım Mühendisi, Çevirmen.

noob

#2
Üstad sanırım ben derdimi anlatamadım.

Bahsettiğiniz iki alt programdan arduino kısmı zaten tamam diyorum. c# arayüzünde ne göstericem diye de sormadım ayrıca. Ben bu iki program arasında bağlantıyı nasıl yapıcam? ekg sensöründen gönderilen sinyalleri hangi göstergeyi kullanarak yapıcam bunları sordum. Bununla ilgili örnek varsa çok yardımcı olur.

edit: elde etmem gereken görüntü bu tarz olacak. ECG Machine

atioky_216

O arkadaş ta benim gibi arduino'yu android anlamıştır belki de :) Diyorum hem android hem pc niye..

Yapacağın şu: arduino  kablosunu pc' ye takacaksın muhtemelen COMx adında sanal port olarak görünecek. C# form app başlatacaksın ve oraya portu ekleyip kullanmaya başlayacaksın.

Artık neyi nasıl ekranda göstermek istersin sana kalmış.

NOT: İki program arası bağlantı diye bir şey olmuyor orada... Protokol (farklı cihaz sistem vb. haberleşmesi için ortak dil) ortak olursa mesela seri haberleşme gibi, senin arduino da çalışan C programın PC de çalışan C# ile konuşabiliyor.

Yapacağın C# da seri port kullanımı.

olemiss

#4
Alıntı yapılan: atioky_216 - 22 Aralık 2013, 00:11:24
O arkadaş ta benim gibi arduino'yu android anlamıştır belki de :) Diyorum hem android hem pc niye..
Yok, ben Arduino olarak anlamıştım!  Herhalde şuradaki Arduino shield kullanılmakta: https://www.olimex.com/Products/Duino/Shields/SHIELD-EKG-EMG/

Şu projede açık kaynak C# grafik/şema çizim kütüphanesi ile ilgili bilgi var:

http://www.codeproject.com/Articles/32836/A-simple-C-library-for-graph-plotting

Aşağıdaki gibi bir GUI elde etmek mümkün:



Ayrıca şurada açık kaynak bir C# EKG yazılımı var: http://sourceforge.net/projects/ecgtoolkit-cs/

Belki işe yarayabilir.

Şuradaki stackoverflow sorusu aynı konuda: http://stackoverflow.com/questions/1299816/plot-ecg-in-winforms

Şu kaynak C/C++ ile yazılmış EKG kütüphanesi: http://www.codeproject.com/Articles/4353/ECG-recording-storing-filtering-and-recognition
Yazılım Mühendisi, Çevirmen.

noob

#5
Çok teşekkür ederim arkadaşlar. Çok yardımcı oldunuz. Allah razı olsun. Deneyip tekrar döneceğim inşaallah.

kolay gelsin.

edit: bu arada evet olimex'in ürettiği shield'i kullanmaktayım. bulgaristandan sipariş verdik çok masraf yaptırdı bana. öğrenciyim ben daha :D

noob

Projede baya ilerleme kaydetmiş bulunmaktayım. Yalnız hata alıyorum sizlere danışmak istedim tekrar.

arduino kod
/**********************************************************/
/* Demo program for:                                      */
/*    Board: SHIELD-EKG/EMG + Olimexino328                */
/*  Manufacture: OLIMEX                                   */
/*  COPYRIGHT (C) 2012                                    */
/*  Designed by:  Penko Todorov Bozhkov                   */
/*   Module Name:   Sketch                                */
/*   File   Name:   ShieldEkgEmgDemo.ino                  */
/*   Revision:  Rev.A                                     */
/*    -> Added is suppport for all Arduino boards.        */
/*       This code could be recompiled for all of them!   */
/*   Date: 19.12.2012                                     */
/*   Built with Arduino C/C++ Compiler, version: 1.0.3    */
/**********************************************************/
/**********************************************************
Purpose of this programme is to give you an easy way to 
connect Olimexino328 to ElectricGuru(TM), see:
[url]https://www.olimex.com/Products/EEG/OpenEEG/EEG-SMT/resources/ElecGuru40.zip[/url]
where you'll be able to observe yours own EKG or EMG signal.
It is based on:
***********************************************************
* ModularEEG firmware for one-way transmission, v0.5.4-p2
* Copyright (c) 2002-2003, Joerg Hansmann, Jim Peters, Andreas Robinson
* License: GNU General Public License (GPL) v2
***********************************************************
For proper communication packet format given below have to be supported:
///////////////////////////////////////////////
////////// Packet Format Version 2 ////////////
///////////////////////////////////////////////
// 17-byte packets are transmitted from Olimexino328 at 256Hz,
// using 1 start bit, 8 data bits, 1 stop bit, no parity, 57600 bits per second.

// Minimial transmission speed is 256Hz * sizeof(Olimexino328_packet) * 10 = 43520 bps.

struct Olimexino328_packet
{
  uint8_t	sync0;		// = 0xa5
  uint8_t	sync1;		// = 0x5a
  uint8_t	version;	// = 2 (packet version)
  uint8_t	count;		// packet counter. Increases by 1 each packet.
  uint16_t	data[6];	// 10-bit sample (= 0 - 1023) in big endian (Motorola) format.
  uint8_t	switches;	// State of PD5 to PD2, in bits 3 to 0.
};
*/
/**********************************************************/
#include <compat/deprecated.h>
#include <FlexiTimer2.h>
//http://www.arduino.cc/playground/Main/FlexiTimer2

// All definitions
#define NUMCHANNELS 6
#define HEADERLEN 4
#define PACKETLEN (NUMCHANNELS * 2 + HEADERLEN + 1)
#define SAMPFREQ 256                      // ADC sampling rate 256
#define TIMER2VAL (1024/(SAMPFREQ))       // Set 256Hz sampling frequency                    
#define LED1  13
#define CAL_SIG 9

// Global constants and variables
volatile unsigned char TXBuf[PACKETLEN];  //The transmission packet
volatile unsigned char TXIndex;           //Next byte to write in the transmission packet.
volatile unsigned char CurrentCh;         //Current channel being sampled.
volatile unsigned char counter = 0;	  //Additional divider used to generate CAL_SIG
volatile unsigned int ADC_Value = 0;	  //ADC current value

//~~~~~~~~~~
// Functions
//~~~~~~~~~~

/****************************************************/
/*  Function name: Toggle_LED1                      */
/*  Parameters                                      */
/*    Input   :  No	                            */
/*    Output  :  No                                 */
/*    Action: Switches-over LED1.                   */
/****************************************************/
void Toggle_LED1(void){

 if((digitalRead(LED1))==HIGH){ digitalWrite(LED1,LOW); }
 else{ digitalWrite(LED1,HIGH); }
 
}


/****************************************************/
/*  Function name: toggle_GAL_SIG                   */
/*  Parameters                                      */
/*    Input   :  No	                            */
/*    Output  :  No                                 */
/*    Action: Switches-over GAL_SIG.                */
/****************************************************/
void toggle_GAL_SIG(void){
  
 if(digitalRead(CAL_SIG) == HIGH){ digitalWrite(CAL_SIG, LOW); }
 else{ digitalWrite(CAL_SIG, HIGH); }
 
}


/****************************************************/
/*  Function name: setup                            */
/*  Parameters                                      */
/*    Input   :  No	                            */
/*    Output  :  No                                 */
/*    Action: Initializes all peripherals           */
/****************************************************/
void setup() {

 noInterrupts();  // Disable all interrupts before initialization
 
 // LED1
 pinMode(LED1, OUTPUT);  //Setup LED1 direction
 digitalWrite(LED1,LOW); //Setup LED1 state
 pinMode(CAL_SIG, OUTPUT);
 
 //Write packet header and footer
 TXBuf[0] = 0xa5;    //Sync 0
 TXBuf[1] = 0x5a;    //Sync 1
 TXBuf[2] = 2;       //Protocol version
 TXBuf[3] = 0;       //Packet counter
 TXBuf[4] = 0x02;    //CH1 High Byte
 TXBuf[5] = 0x00;    //CH1 Low Byte
 TXBuf[6] = 0x02;    //CH2 High Byte
 TXBuf[7] = 0x00;    //CH2 Low Byte
 TXBuf[8] = 0x02;    //CH3 High Byte
 TXBuf[9] = 0x00;    //CH3 Low Byte
 TXBuf[10] = 0x02;   //CH4 High Byte
 TXBuf[11] = 0x00;   //CH4 Low Byte
 TXBuf[12] = 0x02;   //CH5 High Byte
 TXBuf[13] = 0x00;   //CH5 Low Byte
 TXBuf[14] = 0x02;   //CH6 High Byte
 TXBuf[15] = 0x00;   //CH6 Low Byte 
 TXBuf[2 * NUMCHANNELS + HEADERLEN] =  0x01;	// Switches state

 // Timer2
 // Timer2 is used to setup the analag channels sampling frequency and packet update.
 // Whenever interrupt occures, the current read packet is sent to the PC
 // In addition the CAL_SIG is generated as well, so Timer1 is not required in this case!
 FlexiTimer2::set(TIMER2VAL, Timer2_Overflow_ISR);
 FlexiTimer2::start();
 
 // Serial Port
 Serial.begin(57600);
 //Set speed to 57600 bps
 
 // MCU sleep mode = idle.
 //outb(MCUCR,(inp(MCUCR) | (1<<SE)) & (~(1<<SM0) | ~(1<<SM1) | ~(1<<SM2)));
 
 interrupts();  // Enable all interrupts after initialization has been completed
}

/****************************************************/
/*  Function name: Timer2_Overflow_ISR              */
/*  Parameters                                      */
/*    Input   :  No	                            */
/*    Output  :  No                                 */
/*    Action: Determines ADC sampling frequency.    */
/****************************************************/
void Timer2_Overflow_ISR()
{
  // Toggle LED1 with ADC sampling frequency /2
  Toggle_LED1();
  
  //Read the 6 ADC inputs and store current values in Packet
  for(CurrentCh=0;CurrentCh<6;CurrentCh++){
    ADC_Value = analogRead(CurrentCh);
    TXBuf[((2*CurrentCh) + HEADERLEN)] = ((unsigned char)((ADC_Value & 0xFF00) >> 8));	// Write High Byte
    TXBuf[((2*CurrentCh) + HEADERLEN + 1)] = ((unsigned char)(ADC_Value & 0x00FF));	// Write Low Byte
  }
	 
  // Send Packet
  for(TXIndex=0;TXIndex<17;TXIndex++){
    Serial.write(TXBuf[TXIndex]);
  }
  
  // Increment the packet counter
  TXBuf[3]++;			
  
  // Generate the CAL_SIGnal
  counter++;		// increment the devider counter
  if(counter == 12){	// 250/12/2 = 10.4Hz ->Toggle frequency
    counter = 0;
    toggle_GAL_SIG();	// Generate CAL signal with frequ ~10Hz
  }
}


/****************************************************/
/*  Function name: loop                             */
/*  Parameters                                      */
/*    Input   :  No	                            */
/*    Output  :  No                                 */
/*    Action: Puts MCU into sleep mode.             */
/****************************************************/
void loop() {
  
 __asm__ __volatile__ ("sleep");
 
}


C # GUI

using System.Windows.Forms;
using System.IO.Ports;
using ZedGraph;

namespace WindowsFormsApplication3
{

    public partial class Form1 : Form
    {
        private SerialPort port;
        private static int tickStart = 0;  //timer
        private double counter = 0;
        private int addindex = 0;
        private double[] datasend = new double[10000];
        private static ArrayList portdata;
        private Thread newthread;
        private Thread beepthread;
        private Thread OLthread;
        private Thread qrsthread;
        private Thread threshdecrement;
        private Boolean beeper = false;
        private double qrsaverage = 0;
        private double finitedif = 0;
        private double thresh = 10;
        private double[] qrs = new double[10];          //qrs detection array
        private double[] recentd = new double[150];     //overload detection array
        private double[] lowarray = new double[150];
        private double[] higharray = new double[150];
        private Boolean gainselect = false;
        private double heartbeat = 0;
        private DateTime oldbeep = DateTime.Now;
        private DateTime newbeep = DateTime.Now;

        public Form1()
        {
            InitializeComponent();

            for (int i = 0; i < 150; i++)           //overload checker
            {
                lowarray[i] = 0;
            }

            for (int j = 0; j < 150; j++)
            {
                higharray[j] = 1000;
            }

            // This is to remove all plots
            zedGraphControl1.GraphPane.CurveList.Clear();

            // GraphPane object holds one or more Curve objects (or plots)
            GraphPane pane = zedGraphControl1.GraphPane;
           

            //Set up Graph Pane
            pane.Fill.Color = System.Drawing.Color.RoyalBlue;
            pane.Title.Text = "ECG Machine";
            pane.XAxis.Title.Text = "Time (Seconds)";
            pane.YAxis.Title.Text = "Voltage (mV)";
            pane.Legend.IsVisible = false;
            pane.XAxis.Scale.MajorUnit = DateUnit.Millisecond;
            pane.XAxis.Scale.MinorUnit = DateUnit.Millisecond;

            
            zedGraphControl1.GraphPane.XAxis.Scale.Max = 30;
          //  zedGraphControl1.GraphPane.XAxis.Scale.Min = 0;
            zedGraphControl1.GraphPane.YAxis.Scale.Max = 1024;
            zedGraphControl1.GraphPane.YAxis.Scale.Min = 0;
            

            zedGraphControl1.IsShowHScrollBar = true;
            zedGraphControl1.IsAutoScrollRange = true;

            zedGraphControl1.AxisChange();

            // PointPairList holds the data for plotting, X and Y arrays 
            PointPairList points = new PointPairList();

            // Add cruves to myPane object
            LineItem myCurve = pane.AddCurve("Heart Rate", points, Color.Red, SymbolType.None);
            
            tickStart = Environment.TickCount;
            portdata = new ArrayList();
            
            
        }

        private void EstablishConnection()
        {
            port = new SerialPort("COM3", 57600, Parity.None, 8, StopBits.One);
            port.Handshake = Handshake.None;
            port.ReadTimeout = 500;
            port.WriteTimeout = 500;
            if (!(port.IsOpen == true)) port.Open();
            port.Write("B");
            port.Write("D");
            port.Write("E");
        }


        /* This begins data reading from serial Port */
        private void button1_Click(object sender, EventArgs e)
        {
            EstablishConnection();
            button1.Enabled = false;
            pointHP.Select();
            newthread = new Thread(new ThreadStart(this.reader));
            newthread.IsBackground = true;
            newthread.Start();

            beepthread = new Thread(new ThreadStart(this.beepcontrol));
            beepthread.IsBackground = true;
            beepthread.Start();

            OLthread = new Thread(new ThreadStart(this.OLdetection));
            OLthread.IsBackground = true;
            OLthread.Start();

            qrsthread = new Thread(new ThreadStart(this.qrsdetection));
            qrsthread.IsBackground = true;
            qrsthread.Start();

            threshdecrement = new Thread(new ThreadStart(this.threshdec));
            threshdecrement.IsBackground = true;
            threshdecrement.Start();

            timer1.Interval = 1;
            timer1.Enabled = true;
            timer1.Start();     //start timer to add points to chart
            
        }

        private void threshdec()
        {
            while (port.IsOpen)
            {
                if (thresh > 0)
                {
                    if (!gainselect)
                    {
                        thresh = thresh - 1;
                        Thread.Sleep(80);
                    }
                    else
                    {
                        thresh = thresh - 2;
                        Thread.Sleep(20);
                    }
                }
            }
        }

        private void qrsdetection()
        {

            while (port.IsOpen)
            {
                if (addindex > 10)
                {
                    int sum = 0;
                    int C = portdata.Count - 1;
                    for (int i = 0; i < 10; i++)
                    {
                        qrs[i] = (double)portdata[C - (9 - i)];
                    }
                    foreach (int num in qrs)
                    {
                        sum += num;
                    }
                    qrsaverage = sum / 10;          //smooth out signal
                    finitedif = qrs[9] - qrsaverage;
                    if (finitedif > thresh)
                    {
                        thresh = finitedif;
                        if (thresh > 8)
                        {
                            beeper = true;
                        }
                   }
                }

            }
        }

        private void OLdetection()
        {

            while (port.IsOpen)
            {
                if (addindex > 150) {
                int C = portdata.Count - 1;
                

                for (int i = 0; i < recentd.Length; i++)
                {
                    recentd[i] = (double)portdata[C - (149 - i)];
                }

                if (lowcheck(recentd) || highcheck(recentd))
                {
                    setOL("Overload");
                    //set to 5 hp filter
                    Thread.Sleep(150);
                    selectfilter();

                }
                else
                {
                    setOL("");
                }
                
            }
                }
        }

        private void selectfilter()
        {
            if (this.InvokeRequired)
            {
                BeginInvoke(new MethodInvoker(delegate() { selectfilter(); }));
            }
            else
            {
                pointHP.Select();
                pointHP.Enabled = false;
                port.Write("D");
                thresh = 0;
            }
        }

        private void setOL(string text)
        {
            if (this.OverLoad.InvokeRequired)
            {
                try
                {
                    this.Invoke(new Action<string>(setOL), new object[] { text });
                    return;
                }
                catch (ObjectDisposedException) { }
            }
            try
            {
                OverLoad.Text = text;
            }
            catch (Win32Exception) { }
        }

        private void setHeartRate(double bpm)
        {
            if (this.HeartRate.InvokeRequired)
            {
                try
                {
                    this.Invoke(new Action<double>(setHeartRate), new object[] { bpm });
                    return;
                }
                catch (ObjectDisposedException) { }
            }
            try
            {
                HeartRate.Text = String.Format("{0:0.0}", bpm);
                   
            }
            catch (Win32Exception) { }
        }

        private void beepcontrol()
        {
            while (port.IsOpen)
            {
                if (beeper)
                {
                    Thread.Sleep(80);   //makes sure it doesnt beep twice within 1/120 sec
                    Console.Beep();
                    //get BPM
                    oldbeep = newbeep;
                    newbeep = DateTime.Now;
                    double span = (newbeep-oldbeep).Milliseconds;
                    heartbeat = 60000 / span;
                    setHeartRate(heartbeat);
                    beeper = false;
                    
                    
                }
            }
        }


        public void reader()
        {
            while (port.IsOpen)
            {

                    double pt;
                    string dat = port.ReadLine();

                    if (Double.TryParse(dat, out pt))           //if data read is a double value
                    {
                        portdata.Add(pt);
                    }

            }
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            //make sure curvelist isnt empty
            if (zedGraphControl1.GraphPane.CurveList.Count <= 0)
                return;

            //get first curve in graph
            LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem;
            if (curve == null)
                return;

            IPointListEdit list = curve.Points as IPointListEdit;
 
                if (addindex < portdata.Count)
                {
                    list.Add(counter, (double)portdata[addindex]);

                    addindex = addindex + 20;
                    counter = counter + .02;

                }


            zedGraphControl1.GraphPane.XAxis.Scale.Max = counter + 5;
            zedGraphControl1.GraphPane.XAxis.Scale.Min = zedGraphControl1.GraphPane.XAxis.Scale.Max - 10;
            zedGraphControl1.AxisChange();
            zedGraphControl1.Invalidate();
            zedGraphControl1.Refresh();
        }


        private void NotchBox_CheckedChanged(object sender, EventArgs e)
        {
            if (NotchBox.Checked)
            {
                port.Write("F");
            }
            else
            {
                port.Write("E");
                thresh = 0;
            }
        }

        private void GainBox_CheckedChanged(object sender, EventArgs e)
        {
            thresh = 0;

            if (GainBox.Checked)
            {
                port.Write("A");
                gainselect = true;
            }
            else
            {
                port.Write("B");
                gainselect = false;
            }
        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            pointHP.Enabled = false;
            fiveHP.Enabled = true;
            port.Write("D");
        }

        private void fiveHP_CheckedChanged(object sender, EventArgs e)
        {
            fiveHP.Enabled = false;
            pointHP.Enabled = true;
            port.Write("C");
        }

        private void Snapshot_Click(object sender, EventArgs e)
        {
            this.Hide();
            int currentday,currentmonth,currentyear,currenthour,currentminute,currentsecond;
            double currentheartrate;
            string currenttime, currentdate;
            currentday = DateTime.Today.Day;
            currentmonth = DateTime.Today.Month;
            currentyear = DateTime.Today.Year;
            currenttime = DateTime.Now.ToString("hh:mm:ss tt", System.Globalization.DateTimeFormatInfo.InvariantInfo);
            currentdate = DateTime.Now.ToString();
            currenthour = DateTime.Now.Hour;
            currentminute = DateTime.Now.Minute;
            currentsecond = DateTime.Now.Second;
            currentheartrate = heartbeat;

            if (addindex > 9999)
            {
                for (int i = 0; i < 10000; i++)
                {
                    datasend[i] = (double)portdata[portdata.Count - (10000 - i)];
                }

                Database d = new Database(currentheartrate,currentday, currentmonth, currentyear, currenthour, currentminute, currentsecond, currentdate, currenttime, datasend,this);
                //timer1.Stop();
                d.Show();
            }
            else
            {
                MessageBox.Show("Not Enough Data Collected");
                this.Show();
            }
        }

        private Boolean lowcheck(double[] a)
        {
   
                for (int i = 0; i < a.Length; i++)
                {
                    if (a[i] != lowarray[i])
                        return false;
                }
                return true;

        }

        private Boolean highcheck(double[] a)
        {
                for (int i = 0; i < a.Length; i++)
                {
                    if (a[i] < higharray[i])
                        return false;
                }
                return true;
        }



        /* Unused methods */
        private void chart1_Click(object sender, EventArgs e) { }
        private void Form1_Load(object sender, EventArgs e) { }
        private void zedGraphControl1_Load(object sender, EventArgs e){ }
        private void textBox1_TextChanged(object sender, EventArgs e) { }
        private void Overload_TextChanged(object sender, EventArgs e) { }
 



            

    }

}


aldığım hata ise  string dat = port.ReadLine(); kod satırı zaman aşımına uğradı diyor. anladığım kadarıyla devreden bilgileri ya çok geç okuyor ya da hiç okumuyor.

ZZombie

Şu kod satrıındaki tüm tanımlar doğru mu?

port = new SerialPort("COM3", 57600, Parity.None, 8, StopBits.One);

Baund değerini değiştirip denemeler yapın bir de.
Hız farkı olabilir Arduino çıkışı ile PC girişi arasında
Ki 57600 baund oldukça yüksek bir hız.

olemiss

Yazılım Mühendisi, Çevirmen.

noob

baud hızıyla alakalı olduğunu sanmıyorum. establishconnection'ın altındaki point.write("B") nin ve diğerlerinin içini değiştirmem gerekiyor bence. ama ne yazacağımı bilemedim.

picusta

C# ile Arduino kodlarinin arasinda baglanti yok.

C# programi degerleri tek tek bekliyor, text olarak yazilmis ve CR ile biten. ornegin  "14.45\r". O yüzden readLine timeout veriyor.

Olimex'teki abiler ise header + binary olarak 6 kanal ADC (16 bit üzerinden) girisilerini gönderiyor.

atioky'nin ön tespiti dogru imis :
Alıntı YapNOT: İki program arası bağlantı diye bir şey olmuyor orada... Protokol (farklı cihaz sistem vb. haberleşmesi için ortak dil) ortak olursa mesela seri haberleşme gibi, senin arduino da çalışan C programın PC de çalışan C# ile konuşabiliyor.

noob

#11
Alıntı yapılan: picusta - 25 Aralık 2013, 20:30:10
C# ile Arduino kodlarinin arasinda baglanti yok.

C# programi degerleri tek tek bekliyor, text olarak yazilmis ve CR ile biten. ornegin  "14.45\r". O yüzden readLine timeout veriyor.

Olimex'teki abiler ise header + binary olarak 6 kanal ADC (16 bit üzerinden) girisilerini gönderiyor.

atioky'nin ön tespiti dogru imis :

arduinodaki gönderilen  kodları  stringe çevirip sonuna \r eklersem sorun çözülür mü yani? biraz daha açar mısınız?

ya da c# taki beklenen verileri sayısala mı çevirmeliyim? öyleyse nereleri değiştirmem gerekir?

seri porttan hiç anlamıyorum daha bu ilk projem affınıza sığınıyorum.

noob


picusta

Arduino da degerini println fonksyonu çagirirsan olur.
Sonuna otomatik olarak Carriage Return (CR , veya 13 degerindeki byte (\r ) örnek :
Serial.println("14.56");

Koddaki timer2 overflow interuptta degistirmen gereken :

//Read the 1 ADC inputs and store current values in Packet
ADC_Value = analogRead(CurrentCh);
//send packet
Serial.println(ADC_Value );

CurrentCh degiskeninde ise hangi ADC girisi ile ilgileniyorsan o olacak.


C#  :

C# ta  port.ReadLine();  fonksyonu CR alana kadar bekler.

"portdata" listesi sonsuza kadar gidebilir, arada bir bosaltmak gerekir.

olemiss

Ek bir not:

Serial.Println() fonksiyonu satır sonuna iki karakter ekler: ASCII 13, '\r' (satırbaşı - carriage return - karakteri) ve ASCII 10, '\n' (yeni satır - newline - karakteri). 

Windows satır sonunu bu iki karakterle gösterir. 

Linux (Unix) sistemleri ise satır sonu için sadace newline karakteri kullanır.
Yazılım Mühendisi, Çevirmen.