Plotting data stream received by a serial port

Nov 1, 2012 at 9:27 PM

Hello,

 

I would like to plot data stream received by a serial port with sampling rate set to 1 Hz. Data stream is generated by a digital temperature sensor TMP102 connected to a microcontroller. The microcontroller sends the temperature values to the PC through serial port. In windows forms there is serial port control which I use to receive the data. All works well, with one exception the plot shows only last value received by the serial port. I am aware that the code I use right now is not optimized to draw a line between received points. I read other similar threads dealing with displaying real time data like:

http://oxyplot.codeplex.com/discussions/398856

http://oxyplot.codeplex.com/discussions/281036

http://oxyplot.codeplex.com/discussions/350457

I also looked at Realtimedemo and Refreshdemo. The answers and code are somehow confusing and complex (I am more involved in hardware than in software).

So my question is: how can I connect data points with a line? I would like to keep the code it as simple as possible.

 

Thanks in advance!

 

The code I use:

 

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Form1.cs" company="OxyPlot">
//   http://oxyplot.codeplex.com, license: Ms-PL
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
 
 
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System;
using System.Windows.Forms;
using OxyPlot;
using System.Globalization;    
 
namespace WindowsFormsDemo
{
    public partial class Form1 : Form
    {
   
        private int i = 0;
       
        public Form1()
        {
            InitializeComponent();
        
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = "COM3";
            serialPort1.BaudRate = 9600;
            serialPort1.DtrEnable = true;
            serialPort1.Open();
            serialPort1.DataReceived += serialPort1_DataReceived;
        }
 
        private void button2_Disconnect_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
            }
        }
 
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string line = serialPort1.ReadLine();
            this.BeginInvoke(new LineReceivedEvent(LineReceived), line);
        }
 
 
        private delegate void LineReceivedEvent(string line);
        private void LineReceived(string line)
        {
            double dTemperature, dTemperatureRound;
 
            try
            {

                dTemperature = double.Parse(line, CultureInfo.InvariantCulture);
                dTemperatureRound = Math.Round(dTemperature, 4);
 
                label1.Text = Convert.ToString(dTemperatureRound);
 
                var pm = new PlotModel("TMP102 digital temperature sensor""Temperature data stream")
                {
                    PlotType = PlotType.Cartesian,
                    Background = OxyColors.White,
                };
 
 
                var linearAxisX = new LinearAxis();
                linearAxisX.Title = "Sample number";
                linearAxisX.Position = AxisPosition.Bottom;
                linearAxisX.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
                linearAxisX.MajorGridlineStyle = LineStyle.Solid;
                linearAxisX.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
                linearAxisX.MinorGridlineStyle = LineStyle.Solid;
                pm.Axes.Add(linearAxisX);
 
                var linearAxisY = new LinearAxis();
                linearAxisY.Title = "Temperature [°C]";
                linearAxisY.Position = AxisPosition.Left;
                linearAxisY.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
                linearAxisY.MajorGridlineStyle = LineStyle.Solid;
                linearAxisY.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
                linearAxisY.MinorGridlineStyle = LineStyle.Solid;
                pm.Axes.Add(linearAxisY);
 
                var lineSeries1 = new LineSeries();
 
                lineSeries1.Color = OxyColor.FromArgb(255, 78, 154, 6);
                lineSeries1.MarkerFill = OxyColor.FromArgb(255, 78, 154, 6);
                lineSeries1.MarkerStroke = OxyColors.ForestGreen;
                lineSeries1.MarkerType = MarkerType.Circle;
                lineSeries1.StrokeThickness = 2;
                lineSeries1.DataFieldX = "Date";
                lineSeries1.DataFieldY = "Value";
 
                lineSeries1.Points.Add(new DataPoint(i, dTemperatureRound));
 
               
                pm.Series.Add(lineSeries1);
 
                plot1.Model = pm;
 
                i++;
            }
 
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
}

 

Coordinator
Nov 1, 2012 at 9:41 PM
Edited Nov 1, 2012 at 9:46 PM

I would suggest to create the PlotModel, axes and LineSeries in your form constructor. Call plot1.InvalidatePlot(true) to refresh. Something like this (not tested):

    public class Form1 : Form
    {
        private readonly LineSeries lineSeries1;

        private int i;

        public Form1()
        {
            InitializeComponent();

            var pm = new PlotModel("TMP102 digital temperature sensor", "Temperature data stream") { PlotType = PlotType.Cartesian, Background = OxyColors.White };

            var linearAxisX = new LinearAxis();
            linearAxisX.Title = "Sample number";
            linearAxisX.Position = AxisPosition.Bottom;
            linearAxisX.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
            linearAxisX.MajorGridlineStyle = LineStyle.Solid;
            linearAxisX.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
            linearAxisX.MinorGridlineStyle = LineStyle.Solid;
            pm.Axes.Add(linearAxisX);

            var linearAxisY = new LinearAxis();
            linearAxisY.Title = "Temperature [°C]";
            linearAxisY.Position = AxisPosition.Left;
            linearAxisY.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
            linearAxisY.MajorGridlineStyle = LineStyle.Solid;
            linearAxisY.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
            linearAxisY.MinorGridlineStyle = LineStyle.Solid;
            pm.Axes.Add(linearAxisY);

            this.lineSeries1 = new LineSeries();
            this.lineSeries1.Color = OxyColor.FromArgb(255, 78, 154, 6);
            this.lineSeries1.MarkerFill = OxyColor.FromArgb(255, 78, 154, 6);
            this.lineSeries1.MarkerStroke = OxyColors.ForestGreen;
            this.lineSeries1.MarkerType = MarkerType.Circle;
            this.lineSeries1.StrokeThickness = 2;
            this.lineSeries1.DataFieldX = "Date";
            this.lineSeries1.DataFieldY = "Value";
            pm.Series.Add(this.lineSeries1);
            plot1.Model = pm;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = "COM3";
            serialPort1.BaudRate = 9600;
            serialPort1.DtrEnable = true;
            serialPort1.Open();
            serialPort1.DataReceived += this.serialPort1_DataReceived;
        }

        private void button2_Disconnect_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string line = serialPort1.ReadLine();
            this.BeginInvoke(new LineReceivedEvent(this.LineReceived), line);
        }

        private void LineReceived(string line)
        {
            double dTemperature, dTemperatureRound;
            try
            {
                dTemperature = double.Parse(line, CultureInfo.InvariantCulture);
                dTemperatureRound = Math.Round(dTemperature, 4);
                label1.Text = Convert.ToString(dTemperatureRound);
                this.lineSeries1.Points.Add(new DataPoint(this.i, dTemperatureRound));
                plot1.InvalidatePlot(true);
                this.i++;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private delegate void LineReceivedEvent(string line);
    }
Nov 1, 2012 at 10:20 PM

Thanks Objo,

it works!