简体   繁体   中英

Writing and reading serial data from C# to Arduino

I have a .net app in Visual Studio that communicates with an Arduino Uno. The Uno is connected to a pressure sensor. I want to send a message from my .net app to the Arduino via serial, asking for pressure data. Then I want the Arduino to respond with the latest data point, and send it via serial back to my .net app which then plots it and stores the data.

I can send a stream of data continously from my Uno and the app registers the entire stream. But this creates significant lag. I have also tried to use a timer to send the message to my Uno, but this only works if I use a threadsleep of at least 2500ms, which is way too much for my purpose.

My problem is that I can not find a way to continuously send requests from the .net app. I can, for example, add a button that sends the command to the Arduino and I get the correct respons. But I want to do this at a high frequency in a continuous manner.

Here are the relevant parts of my code:

public void Read() //Reads sensor values from Uno
{
    while (port.IsOpen)
    {
        try
        {
            if (port.BytesToRead > 0)
            {
                string message = port.ReadLine();
                this.SetText(message);
            }
        }
        catch (TimeoutException) { }
    }
}

    private void SetText(string text)
    {
        if (this.labelPressure.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] {text});
        }
        else
        {
            this.labelPressure.Text = text;

            chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Enabled = false;
            chart1.Invoke((MethodInvoker)(() => chart1.Series["Pressure"].Points.AddXY(DateTime.Now.ToLongTimeString(), text)));

            if (chart1.Series[0].Points.Count > 20)
            {
                chart1.Series[0].Points.RemoveAt(0);
                chart1.ChartAreas[0].AxisX.Maximum = 0;
                chart1.ChartAreas[0].AxisX.Maximum = 20;
                chart1.ChartAreas[0].AxisY.Maximum = 10;
                chart1.ChartAreas[0].AxisY.Minimum = -90;
                chart1.ChartAreas[0].AxisY.Interval = 10;
            }
        }

    }

This part of the code works for reading the entire data stream. The message I would like to send to the Uno is

           string d2 = "M";
           port.Write(d2);

But I have no idead how to continously and with high frequency send this message to my Uno and then recieve the answer. Does anyone have a solution?

The best algorithm would be that, you open the connection, send the measuring request and wait for the answer and start from the beginning.

There is a DataReceived event, you can use that instead of continuously polling the data in a while loop.

using System;
using System.IO.Ports;

class PortDataReceived
{
    public static void Main()
    {
        SerialPort mySerialPort = new SerialPort("COM1");

        mySerialPort.BaudRate = 9600;
        mySerialPort.Parity = Parity.None;
        mySerialPort.StopBits = StopBits.One;
        mySerialPort.DataBits = 8;
        mySerialPort.Handshake = Handshake.None;
        mySerialPort.RtsEnable = true;

        mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        mySerialPort.Open();
        mySerialPort.Write("M"); // initiate the query
        
        Console.ReadKey();
        mySerialPort.Close();
    }

    private static void DataReceivedHandler(
                        object sender,
                        SerialDataReceivedEventArgs e)
    {
        var sp = (SerialPort)sender;
        var indata = sp.ReadLine();
        //process your message (here you refresh your controls in GUI app )
        /* process data on the GUI thread
        Application.Current.Dispatcher.Invoke(new Action(() => {
            this.labelPressure.Text = indata;
        }));
        */
        Console.WriteLine(indata);
        mySerialPort.Write("M"); // send message request again (it is a bit recursive solution, but maybe this is enough for your use case)
    }
}

Try this first in a command line solution, and if you are satisfied with the data frequency, you implement it in your solution (Delete the Console.* lines, uncomment the commented code and everything should work).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM