JesterBaze
JesterBaze

Reputation: 130

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. I'm receiving serial data to my PC that looks like this:

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.

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). 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()?

TLDR: I want continuously updated (realtime?), properly formatted serial data, that I can separate in to two variables (sonarDist, and sonarDeg).

Do your worst, I'm honestly completely lost. Any advice is welcome.

Upvotes: 0

Views: 11743

Answers (1)

zmo
zmo

Reputation: 24812

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. But I've googled the syntaxes and API references for objects and it looks fine.

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().

Upvotes: 1

Related Questions