Recieve and send data from arduino to c# and vice versa

Hi everyone,
i started using c# a day ago so i appologize for potential numb questions.

So far i wrote the following code. I'm able to send data from c# to arduino which seems to be working fine. Now i would like to ontinuously receive and display data regardless of me sending data to the arduino and display it in a box (RichBox?). How could i add this to the code?

I would be thankfull for any input, tips and ideas.

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

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        
        public Form1()
        {
            InitializeComponent();
            stop.Enabled = false;
            left.Enabled = false;
            right.Enabled = false;
            up.Enabled = false;
            down.Enabled = false;
            string[] ports = SerialPort.GetPortNames();
            comboBox1.Items.AddRange(ports);
            
        }
        private void Form1_Load(object sender, EventArgs e)
        {
              
            
        }
        private void start_Click(object sender, EventArgs e)
        {

            
            if (comboBox1.SelectedIndex > -1)
            {
                string port = (string)comboBox1.SelectedItem;
                serialPort2.PortName = port; // "port";
                serialPort2.BaudRate = 9600;
                serialPort2.Open();
                if (serialPort2.IsOpen)
                {
                    start.Enabled = false;
                    stop.Enabled = true;
                    left.Enabled = true;
                    right.Enabled = true;
                    up.Enabled = true;
                    down.Enabled = true;
                }
            }
                else
                {
                    MessageBox.Show("Please connect the Arduino and select a Port");
                }
            
        }
        private void stop_Click(object sender, EventArgs e)
        {
            if (serialPort2.IsOpen)
            {
                serialPort2.Close();
                start.Enabled = true;
                stop.Enabled = false;
                left.Enabled = false;
                right.Enabled = false;
                up.Enabled = false;
                down.Enabled = false;
            }
        }
        private void up_Click(object sender, EventArgs e)
        {
            
            if (serialPort2.IsOpen)
            {
                serialPort2.WriteLine("1");
            }
            
        }

        private void left_Click(object sender, EventArgs e)
        {
           
            if (serialPort2.IsOpen)
            {
                serialPort2.WriteLine("4");
            }
            
        }

        private void right_Click(object sender, EventArgs e)
        {
            if (serialPort2.IsOpen)
            {
                serialPort2.WriteLine("2");
            }
        }

        private void down_Click(object sender, EventArgs e)
        {
            if (serialPort2.IsOpen)
            {
                serialPort2.WriteLine("3");
            }
        }      
    }
}

All in all i'm trying to control the position of a solar tracker via 4 buttons in c# (up, down, left, right) and to recieve the current angle of both axes from arduino and display these in c#

You could use a timer.
Like:

        private void timer1_Tick(object sender, EventArgs e)
        {
            if ((SerialPort1.IsOpen == true) && (SerialPort1.BytesToRead > 0))
            {
//Rest of code here
}
}

For the visualization of data i use a Textbox.
With appendText you can display data to it.

You could use a timer.

No!

The arrival of serial data triggers an event. Create a delegate to handle that event.

One issue you will have is that serial data is handled in one thread, and the user interface is handled in another thread. The serial thread can not directly write to the user interface elements owned by the user interface thread.

Attached is a C# application that uses a worker thread for dealing with the serial data and the Invoke process for getting serial data to the user interface thread.

CommunicateWithArduino.zip (54 KB)

Hi PaulS, i have been playing around with the code you attached. Everything works great except that i have a disconnect button which crashes the program since when i close the port the while loop is still runing. I have been looking into cancellation Token but cant figure it out. How could i solve this?

except that i have a disconnect button which crashes the program since when i close the port the while loop is still runing.

Crashes which program? The C# application?

What while loop?

Sorry, yes , the c# application. Would you mind having a look? Here is the code :

It crashes in public void Read() due to string message = serialPort2.ReadLine(); it says "Serial port closed" when it crashes guessing since the loop is interrupted. Just not sure how i could solve this

namespace WindowsFormsApplication1{
    public partial class Form1 : Form{
        public static System.IO.Ports.SerialPort port;
        delegate void SetTextCallback(string text);
        private BackgroundWorker hardWorker;
        private Thread readThread = null;
        public Form1() {
            InitializeComponent();
            hardWorker = new BackgroundWorker();
            stop.Enabled = false;
            left.Enabled = false;
            right.Enabled = false;
            up.Enabled = false;
            down.Enabled = false;
            button4.Enabled = false;
            button3.Enabled = false;
            string[] ports = SerialPort.GetPortNames();
            comboBox1.Items.AddRange(ports);
        }
        private void Form1_Load(object sender, EventArgs e){
        }
        private void SetText(string text){
            if (this.receiveText.InvokeRequired){
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else{
                this.receiveText.Text += "";
                this.receiveText.Text += text;
                this.receiveText.Text += Environment.NewLine;
            }
        }
        private void stop_Click(object sender, EventArgs e){
            if (serialPort2.IsOpen){
                serialPort2.Close();
                start.Enabled = true;
                stop.Enabled = false;
                left.Enabled = false;
                right.Enabled = false;
                up.Enabled = false;
                down.Enabled = false;
                button4.Enabled = false;
                button3.Enabled = false;
            }
        }
        public void Read(){
            while (serialPort2.IsOpen){
                try{
                    if (serialPort2.BytesToRead > 0){
                        Thread.Sleep(1000);
                        string message = serialPort2.ReadLine();
                        this.SetText(message);
                    }
                }
                catch (TimeoutException) { }
            }
        }
        private void start_Click(object sender, EventArgs e){
            System.ComponentModel.IContainer components = new System.ComponentModel.Container();   
            if (comboBox1.SelectedIndex > -1){
                string port = (string)comboBox1.SelectedItem;
                serialPort2.PortName = port;
                serialPort2.BaudRate = 9600;
                serialPort2.DtrEnable = true;
                serialPort2.ReadTimeout = 1000;
                serialPort2.WriteTimeout = 500;
                serialPort2.Open();
                readThread = new Thread(new ThreadStart(this.Read));
                readThread.Start();
                this.hardWorker.RunWorkerAsync();
                if (serialPort2.IsOpen){
                    start.Enabled = false;
                    stop.Enabled = true;
                    left.Enabled = true;
                    right.Enabled = true;
                    up.Enabled = true;
                    down.Enabled = true;
                    button4.Enabled = true;
                    button3.Enabled = true;
                }
            }
                else{
                    MessageBox.Show("Please connect the Arduino and select a Port");
                }
        }
        private void up_Click(object sender, EventArgs e){
           if (serialPort2.IsOpen){
                serialPort2.WriteLine("1");
           } 
        }
        private void left_Click(object sender, EventArgs e){
           if (serialPort2.IsOpen){
                serialPort2.WriteLine("4");
           } 
        }
        private void right_Click(object sender, EventArgs e){
           if (serialPort2.IsOpen){
                serialPort2.WriteLine("3");
           }
        }
        private void down_Click(object sender, EventArgs e){
           if (serialPort2.IsOpen){
                serialPort2.WriteLine("3");
           }
        }
        private void button2_Click(object sender, EventArgs e){
           string[] ports = SerialPort.GetPortNames();
           comboBox1.Items.Clear();
           comboBox1.Items.AddRange(ports);
        }
        private void receiveText_TextChanged(object sender, EventArgs e){
            receiveText.SelectionStart = receiveText.Text.Length;
            receiveText.ScrollToCaret();
            receiveText.Refresh();
        }
        private void button3_Click(object sender, EventArgs e){  //auto
            if (serialPort2.IsOpen){
                serialPort2.WriteLine("5");
                button3.Enabled = false;
                button4.Enabled = true;
            }
        }
        private void button4_Click(object sender, EventArgs e){  //manual
            if (serialPort2.IsOpen){
                serialPort2.WriteLine("6");
                button4.Enabled = false;
                button3.Enabled = true;
            }
        }
    }
}

Just not sure how i could solve this

Why are you sleeping in the Read() function? There is data to read. Read it. Don't take a nap, and expect the port still to be open when you wake up.