简体   繁体   English

如何在C#中不断从Arduino中读取串行数据,同时循环刷新serial.readExisting()数据

[英]How to continuously read serial data from Arduino in C#, while looping to refresh the serial.readExisting() data

I'm using my Arduino UNO board to read and plot points on a radar display. 我正在使用Arduino UNO开发板在雷达显示器上读取和绘制点。 I'm receiving serial data to my PC that looks like this: 我正在向PC接收串行数据,如下所示:

44.16 ; 48
44.47 ; 49
44.57 ; 50
44.88 ; 51
158.01 ; 52
44.88 ; 53

The first number is the distance, the second number is the degree marker that the servo is rotated to. 第一个数字是距离,第二个数字是伺服器旋转到的角度标记。

I want to take this data and create an array that will plot and refresh the measurement of every degree as the servo sweeps from 1-180 degrees and back from 180 degrees to 1 degree. 我想获取这些数据并创建一个数组,该数组将在伺服器从1-180度扫过然后从180度变回1度时绘制并刷新每个度的测量值。

Here is my code: 这是我的代码:

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

    namespace SonarRadarProject
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                var comPorts = new string[10]; //You really shouldn't have many more than 10 ports open at a time.... Right?
                comPorts = SerialPort.GetPortNames();
                foreach (var comPort in comPorts)
                    listBoxComPorts.Items.Add(comPort);
                listBoxBaudRate.Items.Add(9600);
            }

            private void buttonConnect_Click(object sender, EventArgs e)
            {
                #region User Interface

                /*-------------------------------------------------------*
                 * --------------USER INTERFACE SECTION------------------*
                 *-------------------------------------------------------*/

                var userPortChoice = listBoxComPorts.SelectedItem;
                var userBaudChoice = listBoxBaudRate.SelectedItem;
                if ((userBaudChoice == null) || (userPortChoice == null))
                {
                    MessageBox.Show("Please select both a PORT and a BAUD rate.", "Error");
                    return;
                }
                SerialPort arduinoPort = new SerialPort()
                                             {
                                                 PortName = userPortChoice.ToString(),
                                                 BaudRate = Convert.ToInt16(userBaudChoice)
                                             };
                arduinoPort.Open();
                arduinoPort.NewLine = "\r\n";

                #endregion

                #region Real Code
                    /*-------------------------------------------------------*
                     * --------------THE REAL CODE SECTION-------------------*
                     *-------------------------------------------------------*/
                while (arduinoPort.IsOpen)
                {
                    //
                    //BEGIN making a string array based on serial data sent via USB from the Arduino UNO
                    //
                }
                #endregion
            }
        }
    }

I can make the array, and separate the Degrees from the Distance measurement (using string.split and string.remove). 我可以制作数组,并将“度”与“距离”测量分开(使用string.split和string.remove)。 I have no idea to keep this information continuously flowing in from the serial port (with the lines of output being separated, and properly formatted) and updating my variables for this data. 我不知道要让这些信息连续不断地从串行端口流入(输出的行分开并正确格式化),并为该数据更新我的变量。

Do I need to introduce a handshake? 我需要握手吗? Perhaps read this data bit by bit and compile it? 也许一点一点地读取此数据并进行编译? Read the inBuffer, instead of arduinoPort.readLine()? 读取inBuffer而不是arduinoPort.readLine()吗?

TLDR: I want continuously updated (realtime?), properly formatted serial data, that I can separate in to two variables (sonarDist, and sonarDeg). TLDR:我想不断更新(实时?),正确格式化的串行数据,以便将其分为两个变量(sonarDist和sonarDeg)。

Do your worst, I'm honestly completely lost. 尽你所能,老实说我完全迷失了。 Any advice is welcome. 欢迎任何建议。

About your question: 关于您的问题:

If I were you I'd create a pair-like class that will help you encapsulate both distance/angle to define a location. 如果您是我,我将创建一个类似配对的类,该类将帮助您封装距离/角度以定义位置。 Then you can add some methods to do some calculations if needed etc.. 然后,您可以根据需要添加一些方法进行一些计算等。

class Location {
    public Location(float distance, float angle) {
    Distance = distance;
        Angle = angle;
    }
    public Location(String distance, String angle) {
        Distance = Convert.ToSingle(values[0]);
        Angle = Convert.ToSingle(values[1]);
    }
    public float Angle { get; private set; }
    public float Distance { get; private set; }
}

Then for your main loop, I'm assuming you want a fixed width array, so you can do a 'circular' iteration over it, meaning that the index after the maximum is the first index. 然后对于您的主循环,我假设您需要一个固定宽度的数组,因此您可以对其进行“循环”迭代,这意味着最大值之后的索引是第一个索引。 As you're designing a radar, you will want to replace old values with new values on each iteration round. 在设计雷达时,您需要在每个迭代回合中用新值替换旧值。

int MAX_LOCATIONS = 360; // let's assume there's 1 value per degree

Location[] radarmap = new Location(MAX_LOCATIONS);
int radar_idx = 0;

while (arduinoPort.IsOpen) {
    //BEGIN making a string array based on serial data sent via USB from the Arduino UNO
    String[] values = ArduinoPort.ReadLine().Split(' ; ');
    radarmap[radar_idx] = Location(values[0], values[1]);
    // as you're working on a radar, I assume you need to overwrite values once you've made 360 degrees
    if (++radar_idx == MAX_LOCATIONS)
        radar_idx = 0;
}

But instead of using an array, as you've asked, I think it'd be even better to use a hashmap, given your angles stay constant: 但是,考虑到您的角度保持不变,我认为与其使用数组,不如使用哈希表更好。

while (arduinoPort.IsOpen) {
    Hashtable locations = new Hashtable();
    String[] values = ArduinoPort.ReadLine().Split(' ; ');
    locations[values[0]] = values[1]; // key is the angle, value is the distance
}

It makes the code way simpler, but it all depends on your constraints, so the choice is up to you. 它使代码方式更简单,但是这完全取决于您的约束,因此选择取决于您。

Disclaimer: I'm not a C# programmer (that's the second time I'm writing C# in my whole life), so by no means this example is complete or even compilable. 免责声明:我不是C#程序员(这是我一生中第二次编写C#),因此,该示例绝不是完整的甚至是可编译的。 But I've googled the syntaxes and API references for objects and it looks fine. 但是我已经搜索了对象的语法和API参考,看起来还不错。

about your comment: 关于您的评论:

  • You should set the newline setting to \\n (unix end-of-line) instead of \\r\\n (windows end-of-line), as it is the default with arduino's Serial.println() . 您应该将换行设置为\\n (unix行尾),而不是\\r\\n (windows行尾),因为这是arduino的Serial.println()的默认设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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