【问题标题】:Plotting sampling graph on VB.NET在 VB.NET 上绘制采样图
【发布时间】:2014-09-23 11:39:42
【问题描述】:

我正在从 Arduino 收集数据并通过串行端口在 Visual Basic 上传输。现在我想绘制一个时间与电能的关系图(单位kWh) - 沿 x 轴的时间和沿 y 轴的电能。通常我从 Arduino 获取电流数据。

现在我想学习如何开始绘制图表。我需要一个简单的例子来解释为样本绘制图表。我尝试了一些示例代码。看来他们没有工作。

如何绘制图表时间与从串行读取的电流?一旦 Visual Basic 开始运行,它应该保存数据 w.r.t 系统时间和日期。

Example available here

当前代码

Imports System
Imports System.IO.Ports
Imports System.ComponentModel
Imports System.Threading

Imports System.Drawing

Public Class Form1
    Dim myPort As Array
    Dim Distance As Integer


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        myPort = IO.Ports.SerialPort.GetPortNames()
        PortComboBox.Items.AddRange(myPort)
        BaudComboBox.Items.Add(9600)
        BaudComboBox.Items.Add(19200)
        BaudComboBox.Items.Add(38400)
        BaudComboBox.Items.Add(57600)
        BaudComboBox.Items.Add(115200)
        ConnectButton.Enabled = True
        DisconnectButton.Enabled = False
    End Sub

    Private Sub ConnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectButton.Click
        SerialPort1.PortName = PortComboBox.Text
        SerialPort1.BaudRate = BaudComboBox.Text
        SerialPort1.Open()
        Timer1.Start()

        'lblMessage.Text = PortComboBox.Text & " Connected."
        ConnectButton.Enabled = False
        DisconnectButton.Enabled = True
    End Sub

    Private Sub DisconnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DisconnectButton.Click
        SerialPort1.Close()

        DisconnectButton.Enabled = False
        ConnectButton.Enabled = True
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Try
            SerialPort1.Write("c")
            System.Threading.Thread.Sleep(250)
            Dim k As Double
            Dim distance As String = SerialPort1.ReadLine()
            k = CDbl(distance)
            ListBoxSensor.Text = k
        Catch ex As Exception

        End Try
    End Sub

    Private Sub Relay_ON_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Relay_ON.Click
        SerialPort1.Write("1")
    End Sub

    Private Sub Relay_Off_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Relay_Off.Click
        SerialPort1.Write("0")
    End Sub

End Class

【问题讨论】:

  • 你是什么意思...一旦vb开始运行它应该保存数据w.r.t系统时间和日期
  • 我想绘制图形时间与串行数据的关系。当我说加载图表或显示图表时,它需要系统时间和串行监视器中的数据并绘制它。
  • 我的问题是如何绘制折线图??
  • 当您向某人讲话时,请使用他/她的 @username 来通知您。我给你举个简单的例子。

标签: vb.net graph arduino sampling


【解决方案1】:

Add a picturebox, a timer a button and a textbox:

PictureBox1 size = 768, 279
定时器间隔为 500

Private img As Bitmap
Private imgClone As Bitmap
Private widthInterval As Integer
'the distance from the left side of picturebox where x axis starts
Private leftPad As Integer = 50
'the distance from the down side of picturebox where x axis is
Private downPad As Integer = 30
'the distance from the up side of picturebox where y axis ends
Private upPad As Integer = 50
'the distance from the right side of picturebox where x axis ends
Private rightPad As Integer = 80
Private rn As New Random

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    drawBack()

    Timer1.Enabled = True
End Sub

Private Sub drawBack()
    Static count As Boolean = False
    Dim g As Graphics
    'number of values in x axis e.g 1, 2, 3, ... representing time
    Dim numX As Integer = 23
    'number of values in y axis representing KW/h
    Dim numY As Integer = 5
    Dim stringFormat As New StringFormat()
    'arreys to hold the text for both axies
    Dim arrayTextX(numX), arrayTextY(numY - 1) As String
    Dim i As Integer
    'the distance from the right side of picturebox where x axis stops
    Dim rightPad As Integer = 80
    Dim brush As Brush = New SolidBrush(Color.FromArgb(245, 255, 255))
    Dim pen As Pen = New Pen(Color.FromArgb(212, 212, 212), 1)
    Dim height, x, y As Integer

    'Run once
    If count = True Then
        Return
    End If

    count = True

    stringFormat.Alignment = StringAlignment.Center

    img = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    imgClone = New Bitmap(PictureBox1.Width, PictureBox1.Height)

    g = Graphics.FromImage(img)
    g.SmoothingMode = SmoothingMode.AntiAlias
    g.Clear(Color.White)

    'the distance in x axis between each value
    widthInterval = CInt((PictureBox1.Width - leftPad - rightPad) / (numX + 1))
    'the distance in y axis between each value
    height = CInt((PictureBox1.Height - upPad - downPad) / (numY + 1))

    'fill arrays with text
    For i = 0 To numX - 1
        arrayTextX(i) = (i + 1).ToString
    Next

    For i = 0 To numY - 1
        arrayTextY(i) = ((i + 1) * height).ToString
    Next

    'fill background of graph with color
    g.FillRectangle(brush, New Rectangle(leftPad, upPad, PictureBox1.Width - leftPad - rightPad + 1, _
                                         PictureBox1.Height - downPad - upPad))
    'vertical lines
    x = leftPad
    For i = 0 To numX - 1
        x += widthInterval 
        g.DrawLine(pen, x, PictureBox1.Height - downPad, x, upPad)
        g.DrawString(arrayTextX(i), New Font("Arial", 8), Brushes.Black, _
                     New Rectangle(x - 10, PictureBox1.Height - downPad + 3, 20, 20), stringFormat)
    Next

    'horizontal lines
    stringFormat.Alignment = StringAlignment.Far
    y = PictureBox1.Height - downPad
    For i = 0 To numY - 1
        y -= height
        g.DrawLine(pen, leftPad, y, PictureBox1.Width - rightPad, y)
        g.DrawString(arrayTextY(i), New Font("Arial", 8), Brushes.Black, _
                     New Rectangle(0, y - 6, leftPad - 5, 20), stringFormat)
    Next

    g.DrawString("KW/Hour", New Font("Arial", 8, FontStyle.Bold), Brushes.Black, _
                     New PointF(5, 5))
    g.DrawString("Time", New Font("Arial", 8, FontStyle.Bold), Brushes.Black, _
                     New PointF(PictureBox1.Width - 50, PictureBox1.Height - 20))

    'draws x axis
    g.DrawLine(Pens.Black, New Point(leftPad, PictureBox1.Height - downPad), _
               New Point(PictureBox1.Width - rightPad, PictureBox1.Height - downPad))
    'draws y axis
    g.DrawLine(Pens.Black, New Point(leftPad, PictureBox1.Height - downPad), _
               New Point(leftPad, upPad))

    g.Dispose()

    PictureBox1.Image = img
    imgClone = CType(img.Clone, Bitmap)
End Sub

Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
    Dim value, x As Integer
    Dim g As Graphics
    Dim pntEnd As Point
    Static pnt As Point = New Point(-1, -1)
    Static staticX As Integer = -1

    Dim hour As Integer = DateTime.Now.Hour
    Dim minute As Integer = DateTime.Now.Minute
    Dim second As Integer = DateTime.Now.Second

    second = minute * 60 + second

    x = leftPad + hour * widthInterval + CInt(CDbl(widthInterval - 1) * CDbl(second) / 3600.0R)

    If pnt.X >= 0 Then
        'checks if the new points x coordinate is the same as the previous and returns
        If x <= staticX Then
            Return
        End If
    End If

    GetValue(value)

    pntEnd = New Point(x, PictureBox1.Height - value - downPad)

    g = Graphics.FromImage(img)
    g.SmoothingMode = SmoothingMode.AntiAlias

    If pnt.X < 0 Then
        g.DrawLine(Pens.Red, pntEnd, pntEnd)
    Else
        g.DrawLine(Pens.Red, pnt, pntEnd)
    End If

    g.Dispose()

    pnt = pntEnd
    staticX = x

    PictureBox1.Invalidate()
End Sub

Private Sub GetValue(ByRef value As Integer)
    'here you can take the value from arduino.
    value = rn.Next(0, PictureBox1.Height - downPad - upPad) 'random value
End Sub

当您按下 Button1 时,图表开始。

计算图形的宽度(x 轴)

width = PictureBox1.Width - leftPad - rightPad

这个 width 相当于 24 小时或 86400 秒。所以你应该将定时器间隔设置为

Timer1.Interval = CInt((86400 / width ) * 1000) 'in milliseconds

没有必要这样做,因为 tick 函数会检查是否 新点与前点相同。所以将定时器间隔设置为 1 秒。

【讨论】:

  • 感谢您的代码。我收到错误 ListControls.Add(New Point(0, 0)) g = Graphics.FromImage(img) g.SmoothingMode = SmoothingMode.AntiAlias 用于平滑模式和列表控件的声明错误
  • GetValue(value) 函数如何为您的代码加载值
  • @user50949 天哪。你说的对!我在那里忘记了它,因为我正在尝试一种不同的方法。删除了这一行。谢谢
  • @user50949 答案有两部分(在我编辑之前),它引起了混乱。第一个具有固定绘图的 tick 功能,第二个 tick 是最终解决方案。你没有检查第一部分
猜你喜欢
  • 1970-01-01
  • 2012-04-12
  • 2019-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多