在 VB.NET 上绘制采样图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25994162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 18:15:51  来源:igfitidea点击:

Plotting sampling graph on VB.NET

vb.netgrapharduinosampling

提问by user50949

I am collecting data from an Arduino and transmit on Visual Basic through the serial port. Now I wanted to plot a graph with time vs electrical energy (unit kWh) - time along the x-axis and electrical energy along the y-axis. Usually I am getting data of the current from Arduino.

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

Now I wanted to learn how to start plotting the graph. I need a simple example explaining plotting a graph for sample. I tried some example code. It seems they are not working.

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

How do I plot a graph time vs current read from serial? Once Visual Basic starts running, it should save data w.r.t system time and date.

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

Example available here

此处提供示例

Current code

当前代码

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

回答by γηρ?σκω δ' αε? πολλ? διδασκ?με

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

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

PictureBox1 size = 768, 279
timer interval to 500

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

When you press Button1the graph starts.

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

Calculate width of graph (x axis)

计算图形的宽度(x 轴)

width = PictureBox1.Width - leftPad - rightPad

this widthis equivelant with 24h or 86400sec. So you should set the timer interval to

宽度与 24 小时或 86400 秒相等。所以你应该将定时器间隔设置为

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

There is no need to be that because the tickfunction checks if the new point is the same as the previous. So set timer interval to 1 second.

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