none
Reading data from serial port and plotting graph RRS feed

  • Question

  • Hi all,

    I am developing a program to read bytes from a serial port and plot a graph using this data.

    I am using a serial port control and read data using ReadByte method in the data_received event of serial port and store  the data in to a buffer( byte array). Data from this buffer is used to plot a graph(MS Chart control). I have implemented some logic to workout this, but what happens is that the app hangs when working.

    What I need is that I want two threads to be written, one to read data from serial port and store the data to a buffer. Another thread to plot graph using this buffer. Please share some code to start two threads which works independent without causing any hanging of app.

    Thanks in advance

    Sunday, September 2, 2018 8:00 PM

All replies

  • I would suspect that there is more going on than just needing a separate thread. If you are using the example from your previous question that runs on a timer then you should be able to collect your data in the time between the timer ticks.

    If you show your code to collect the serial data there might be some improvements. However the forum members that really know the serial port part have not been around lately, maybe on vacation. There are lots of examples on the forum if you search.

    Anyhow, here is an example I adapted from the chart samples here:

    https://code.msdn.microsoft.com/Samples-Environments-for-b01e9c61

    The samples are a visual studio project you run in visual studio. Very easy. Look under Working with data - Real time data - thread safe for this example.

    Perhaps you can use this example? Instead of the random points you put in your serial data. This example is set on 1 second intervals you may need to change that?

    It is the similar to the previous example from your other question but this one has a separate thread to collect the data and then a delegate to keep from cross threading problems. I dont really know for sure.

    Hopefully some of the members that know this better will be around soon.

    How fast does your data come in and how many points per second and exactly what is it a thermometer or an ekg or what?

    Get the samples project running and look it over and then let us know more about your data. Hopefully some of the other members will be back from vacation soon?

    Imports System.Windows.Forms.DataVisualization.Charting
    Imports System.Threading
    
    Public Class StreamChart
        Private addDataRunner As Thread
        Private rand As New Random()
        Public Delegate Sub AddDataDelegate()
        Public addDataDel As AddDataDelegate
        Private LastTime As Double
    
        Private Sub Form3_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
            Dim addDataThreadStart As New ThreadStart(AddressOf AddDataThreadLoop)
            addDataRunner = New Thread(addDataThreadStart)
            addDataDel = New AddDataDelegate(AddressOf AddData)
    
            ChartSetup()
    
        End Sub
    
        Private Sub startTrending_Click(sender As Object, e As System.EventArgs) Handles startTrending.Click
            startTrending.Enabled = False
            stopTrending.Enabled = True
    
            ' start worker threads.
            If addDataRunner.IsAlive = True Then
                addDataRunner.Resume()
            Else
                addDataRunner.Start()
            End If
    
        End Sub 'startTrending_Click 
    
        Private Sub stopTrending_Click(sender As Object, e As System.EventArgs) Handles stopTrending.Click
            If addDataRunner.IsAlive = True Then
                addDataRunner.Suspend()
            End If
    
            startTrending.Enabled = True
            stopTrending.Enabled = False
    
        End Sub
    
        '/ Main loop for the thread that adds data to the chart.
        '/ The main purpose of this function is to Invoke AddData
        '/ function every 1000ms (1 second).
    
        Private Sub AddDataThreadLoop()
            While True
                chart1.Invoke(addDataDel)
    
                Thread.Sleep(120)
            End While
        End Sub
    
        Public Sub AddData()
            Dim timeStamp As DateTime = DateTime.Now
    
            Dim ptSeries As Series
            For Each ptSeries In Chart1.Series
                AddNewPoint(timeStamp, ptSeries)
            Next ptSeries
        End Sub
    
        '/ The AddNewPoint function is called for each series in the chart when
        '/ new points need to be added.  The new point will be placed at specified
        '/ X axis (Date/Time) position with a Y value in a range +/- 1 from the previous
        '/ data point's Y value, and not smaller than zero.    
        Public Sub AddNewPoint(timeStamp As DateTime, ptSeries As System.Windows.Forms.DataVisualization.Charting.Series)
            Dim newVal As Double = 0
    
            If ptSeries.Points.Count > 0 Then
                newVal = ptSeries.Points((ptSeries.Points.Count - 1)).YValues(0) + (rand.NextDouble() * 2 - 1)
            End If
    
            If newVal < 0 Then newVal = 0
    
            ' Add new data point to its series.
            ptSeries.Points.AddXY(timeStamp.ToOADate(), rand.Next(20, 80))
    
            ' remove all points from the source series older than 1.5 minutes.
            Dim removeBefore As Double = timeStamp.AddSeconds((CDbl(10) * -1)).ToOADate()
            'remove oldest values to maintain a constant number of data points
            While ptSeries.Points(0).XValue < removeBefore
                ptSeries.Points.RemoveAt(0)
            End While
    
            Chart1.ChartAreas(0).AxisX.Minimum = ptSeries.Points(0).XValue
            Chart1.ChartAreas(0).AxisX.Maximum = DateTime.FromOADate(ptSeries.Points(0).XValue).AddMinutes(0.3).ToOADate()
    
            Chart1.Invalidate()
        End Sub
    
        Private Sub ChartSetup()
            Chart1.BackColor = Color.FromArgb(211, 223, 240)
            Chart1.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom
            Chart1.BackSecondaryColor = System.Drawing.Color.White
            Chart1.BorderlineColor = Color.FromArgb(26, 59, 105)
            Chart1.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid
            Chart1.BorderlineWidth = 2
            Chart1.BorderSkin.SkinStyle = System.Windows.Forms.DataVisualization.Charting.BorderSkinStyle.Emboss
    
            With Chart1.ChartAreas(0)
                .AxisX.LabelStyle.Font = New System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold)
                .AxisX.LabelStyle.Format = "hh:mm:ss"
                .AxisX.LabelStyle.Interval = 10
                .AxisX.LabelStyle.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds
                .AxisX.LineColor = Color.LightGray
                .AxisX.Title = "Time"
                .AxisX.MajorGrid.LineColor = Color.LightBlue
                .AxisX.MajorGrid.Interval = 10
                .AxisX.MajorGrid.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds
                .AxisX.MajorTickMark.Interval = 10
                .AxisX.MajorTickMark.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds
    
                .AxisY.Title = "Time Interval (ms)"
                .AxisY.IsLabelAutoFit = False
                .AxisY.IsStartedFromZero = False
                .AxisY.LabelStyle.Font = New System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold)
                .AxisY.LineColor = Color.LightGray
                .AxisY.MajorGrid.LineColor = Color.LightGray
                .AxisY.Maximum = 100
                .AxisY.Minimum = 0
    
                .BackColor = Color.FromArgb(64, 165, 191, 228)
                .BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom
                .BackSecondaryColor = System.Drawing.Color.White
                .BorderColor = Color.FromArgb(64, 165, 191, 228)
                .BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid
    
                .InnerPlotPosition.Auto = False
                .InnerPlotPosition.Height = 80
                .InnerPlotPosition.Width = 90
                .InnerPlotPosition.X = 9
                .InnerPlotPosition.Y = 4
    
                .Position.Auto = False
                .Position.Height = 86
                .Position.Width = 88
                .Position.X = 6
                .Position.Y = 6
    
            End With
    
            Chart1.Legends(0).BackColor = System.Drawing.Color.Transparent
            'Chart1.Legends(0).Alignment = System.Drawing.StringAlignment.Far
    
            Dim minValue = New Date(100)
            minValue = DateTime.Now
            Dim maxValue As New Date(100)
            maxValue = minValue.AddSeconds(100)
    
            Chart1.ChartAreas(0).AxisX.Minimum = minValue.ToOADate()
            Chart1.ChartAreas(0).AxisX.Maximum = maxValue.ToOADate()
            Chart1.Series.Clear()
            Chart1.Series.Add("Time Interval")
            With Chart1.Series(0)
                Chart1.Series(0).IsVisibleInLegend = False
                .ChartType = SeriesChartType.Line
                .BorderWidth = 2
                .Color = Color.OrangeRed
                .BorderColor = Color.FromArgb(224, 64, 10)
                .ShadowOffset = 1
            End With
        End Sub
    End Class

    Monday, September 3, 2018 11:18 AM