Plotting data from Arduino

In this video I show you how to continue the previous C# code and create a chart. By using a chart you'll be able to visualize the data that comes from the Arduino. I show you the tricks to process the received data and put them on a chart. I also show a simple example for saving the incoming data into a text file.

In order to fully understand this video, please check the previous two videos:

  1. Two-way serial communication with Arduino

  2. Developing Serial Terminal for Arduino in C#



C# source code

using System;
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;
using System.IO.Ports; //Serial port handling
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
 
namespace Serial_Arduino
{
    public partial class Form1 : Form
    {
        /*
         *  Structure of the input data
         *  col1 \t col2 \t col3 \n
         *  col1 \t col2 \t col3 \n
         *  col1 \t col2 \t col3 \n
         *  .
         *  .
         *  .
         */
 
        private string[] split = new string[3]; //3 -> because of col1,2,3.
        private double _split1, _split2, _split3;
        private double[] Split1, Split2, Split3; //arrays for the split data
        private int counter; //counter
        private string foutput; //file-output
 
 
        private SerialPort SerPort;  //serial port
        private string ReceivedData; //received data from serial port.
       
        public Form1()
        {
            InitializeComponent();
            FetchAvailablePorts(); //at the start we check the list of available COM ports
            InitChart(); //at the start we initialize the chart
           
            //creating the arrays. make sure that you have enough space (number in the [])
            //for dynamic array you might want to use List<>.
            Split1 = new double[1000];
            Split2 = new double[1000];
            Split3 = new double[1000];
        }
 
        void FetchAvailablePorts()
        {
            String[] ports = SerialPort.GetPortNames(); //We get the available COM ports
            AvailablePortsBox.Items.AddRange(ports);
 
        }
 
        private void ConnectToPort_Click(object sender, EventArgs e)
        {
            SerPort = new SerialPort(); //instantiate our serial port SerPort
           
            //hardcoding some parameters, check MSDN for more
            SerPort.BaudRate = 9600;
            SerPort.PortName = AvailablePortsBox.Text;
            SerPort.Parity = Parity.None;
            SerPort.DataBits = 8;
            SerPort.StopBits = StopBits.One;
            SerPort.ReadBufferSize = 200000000;
            SerPort.DataReceived += SerPort_DataReceived;
 
            try
            {
                SerPort.Open();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "Error...!");
            }
 
 
        }
 
        private void SerPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            ReceivedData = SerPort.ReadLine(); //read the line from the serial port
 
            this.Invoke(new Action(ProcessingData)); //at each received line from serial port we "trigger" a new processingdata delegate
        }
 
        private void ProcessingData() //processing received data and plotting it on a chart
        {
 
            try
            {
                ReceivedDataBox.Text += ReceivedData.ToString() + Environment.NewLine; //print the received data into the textbox
 
                //reminder: col1 \t col2 \t col3 \n
 
                split = ReceivedData.Split('\t'); //split the data separated by tabs; split[3] -> split[col1], split[col2], split[col3]; split[i]
               
                //parsing the string to double (we expect numbers from the Arduino)
                Double.TryParse(split[0], out _split1);
                Double.TryParse(split[1], out _split2);
                Double.TryParse(split[2], out _split3);
 
                //the ith element of the Split array will be the recently parsed _split.
                Split1[counter] = _split1;
                Split2[counter] = _split2;
                Split3[counter] = _split3;
 
                //plot
                DataChart.Series["Channel1"].Points.AddXY(Split1[counter], Split2[counter]); //col1 , col2
                DataChart.Series["Channel2"].Points.AddXY(Split1[counter], Split3[counter]); //col1 , col3
                DataChart.ChartAreas[0].RecalculateAxesScale(); //recalculate.rescale
 
                //handle the output
                foutput = _split1.ToString() + "\t" + _split2.ToString() + "\t" + _split3.ToString() + Environment.NewLine;
                //we put together the variables into a string (foutput) again
 
                if (FileSavingCheckBox.Checked == true) //file saving, same folder as executable
                {
                    using (StreamWriter sw = File.AppendText("Outputfile.txt"))//appendtext = the previous file will be continued
                    {
                        sw.Write(foutput); //write the content of foutput into the file
                    }
                }
 
            }
            catch { }
 
            counter++;
            //the value of the counter is increased by one at each loop (at each new data)
            //this makes sure that the next series of data is written in the next line of the arrays
 
 
        }
 
        private void SendSerialButton_Click(object sender, EventArgs e)
        {
            SerPort.WriteLine(SenderTextBox.Text.ToString());
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                SerPort.Close();
            }
            catch { }
        }
 
        private void InitChart() //initializing the chart
        {
            DataChart.ChartAreas[0].AxisX.IsStartedFromZero = false; //in case we get negative number
            DataChart.ChartAreas[0].AxisX.MajorGrid.LineWidth = 0; //no grids
            DataChart.ChartAreas[0].AxisY.MajorGrid.LineWidth = 0;
            DataChart.ChartAreas[0].AxisX.Title = "X-axis ()"; //name of the x-y axis
            DataChart.ChartAreas[0].AxisY.Title = "Y-axis ()";
            DataChart.ChartAreas[0].AxisX.Enabled = AxisEnabled.True;
            DataChart.ChartAreas[0].AxisY.Enabled = AxisEnabled.True;
            DataChart.ChartAreas[0].CursorX.AutoScroll = true;
 
            //Check the MSDN documentation!
 
            //series for the channel1
            Series series = new Series()
            {
                Name = "Channel1",
                Color = System.Drawing.Color.Black,
                ChartType = SeriesChartType.FastLine,
                IsXValueIndexed = true
            };
 
            DataChart.Series.Add(series);
 
            //series for the channel2
            Series series2 = new Series()
            {
                Name = "Channel2",
                Color = System.Drawing.Color.Red,
                ChartType = SeriesChartType.FastLine,
                IsXValueIndexed = true
            };
 
            DataChart.Series.Add(series2);
 
        }
       
    }
}

Previous
Previous

DIY Miniature Tensile Testing Machine

Next
Next

Developing Serial Terminal for Arduino in C#