0

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.

dsolimano
  • 8,870
  • 3
  • 48
  • 63
JesterBaze
  • 130
  • 2
  • 2
  • 11
  • PS -It's not that I didn't have anything in my "Real Code" section, I just got mad after I kept getting debug "index out of range" exceptions and random garbage outputs such as "908123090;00000\r\n09812039890000\r\n". I highlighted everything, deleted it, and closed VS2012. Probably not my best decision. Posting here was an afterthought =( – JesterBaze Jun 20 '13 at 17:12
  • 1
    Have you read this sample http://code.msdn.microsoft.com/windowsdesktop/SerialPort-brief-Example-ac0d5004 – John b Jun 20 '13 at 17:12
  • No I haven't! Thank you. How would I get my Arduino to send a stop bit however, or is it sent automatically? I just assumed the arduinoPort.NewLine = "\r\n" would determine the end of one serial line, and the next arduinoPort.ReadLine() would kick out the next line, thereby acting as a 'stop bit'. I'm just a programming hobbyist, sorry if this is a dumb question. – JesterBaze Jun 20 '13 at 17:29
  • 1
    @JesterBaze - Look at my code in http://stackoverflow.com/questions/16335690/serial-port-reading-threads-or-something-better/16345503#16345503, It describes how to add the received data from the arduino into a threadsafe queue. The datareceived handler continuously add the received characters to the queue, and then you take the characters "out" (dequeue) in your code at your leisure, and assign the characters to variables. – user2019047 Jun 20 '13 at 18:05
  • 1
    There are no start or stop bits sent automatically from the Arduino board. It sends what you tell it to send, so when you send data it is good to mark this data somehow. Think protocols. A protocol defines how data is formatted before transmission. For the Arduino the user defines the protocol. For this particular question the data could be sent in a structured way, say [d:a] where d is distance and a is angle and the brackets [] are start and end of the information sent (a packet of data). On the receiving end it will be easy to disassemble the packet as it is sent in a structured manner. – user2019047 Jun 21 '13 at 00:32
  • Awesome, I will try this as soon as I have the chance. Thank you, I think this _should_ work =) – JesterBaze Jun 21 '13 at 04:21

1 Answers1

1

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().
zmo
  • 24,463
  • 4
  • 54
  • 90