在VB.NET上绘制采样图

时间:2014-09-23 11:39:42

标签: vb.net graph arduino sampling

我从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

1 个答案:

答案 0 :(得分:0)

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

宽度与24h或86400sec等效。所以你应该把定时器间隔设置为

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

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