Moin Leute,
ich hatte das Problem, permanent gerechnete Werte oszilloskop-artig darzustellen. Dabei ist es unerheblich, woher die Daten kommen, über Serial, aus einer Datei oder halt gerechnet.
Diesen Teil habe ich ersetzt durch zwei in einer Timer-Tick-Prozedur berechnete Sinus-Kurven, von denen eine durch die Parameter Amplitude und Frequenz beeinflusst werden kann.
Wie bei einem richtigen Oszilloskop wird die Vergangenheit vergessen, das passiert dadurch, dass bei einer Punkteanzahl größer als hier 500 Punkte am Anfang gelöscht werden, dazu nutze ich eine
Interessant ist der Teil der Darstellung.
Hier wird durch Verwendung 2er
So kommt es auch, dass in der Einlaufphase nur der obere Teil der Kurve dargestellt wird, so lange keine negativen Werte vorliegen. Dies kann allerdings bei der Bestimmung des Um-Rechtecks der Datenkurven einfach angepasst werden, ist aber m.E. nicht erforderlich.
Mit dem Button wird die Darstellung neu gestartet, die CheckBox erlaubt, die Darstellung zu pausieren. Die beiden NumericUpDowns verändern Amplitude und Frequenz der einen Kurve.
Oszilloskop
ich hatte das Problem, permanent gerechnete Werte oszilloskop-artig darzustellen. Dabei ist es unerheblich, woher die Daten kommen, über Serial, aus einer Datei oder halt gerechnet.
Diesen Teil habe ich ersetzt durch zwei in einer Timer-Tick-Prozedur berechnete Sinus-Kurven, von denen eine durch die Parameter Amplitude und Frequenz beeinflusst werden kann.
Wie bei einem richtigen Oszilloskop wird die Vergangenheit vergessen, das passiert dadurch, dass bei einer Punkteanzahl größer als hier 500 Punkte am Anfang gelöscht werden, dazu nutze ich eine
List(Of PointF)
Interessant ist der Teil der Darstellung.
Hier wird durch Verwendung 2er
GraphicsPath
s eine permanente Skalierung der Kurven auf den Darstellungsbereich realisiert, so dass beim Vergrößern / Verkleinern der Form die Darstellung augenblicklich angepasst wird.So kommt es auch, dass in der Einlaufphase nur der obere Teil der Kurve dargestellt wird, so lange keine negativen Werte vorliegen. Dies kann allerdings bei der Bestimmung des Um-Rechtecks der Datenkurven einfach angepasst werden, ist aber m.E. nicht erforderlich.
Mit dem Button wird die Darstellung neu gestartet, die CheckBox erlaubt, die Darstellung zu pausieren. Die beiden NumericUpDowns verändern Amplitude und Frequenz der einen Kurve.
VB.NET-Quellcode
- Imports System.Drawing.Drawing2D
- Public Class Form1
- ' Lists für 2 Datenreihen
- Private points1 As List(Of PointF)
- Private points2 As List(Of PointF)
- ' Rechen-Koordinate
- Private coord As Integer = 0
- Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- Me.Timer1.Interval = 20 ' schnell genug
- End Sub
- Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
- Me.points1 = New List(Of PointF)
- Me.points2 = New List(Of PointF)
- Me.coord = 0
- ' zuerst Check, dann Timer, weil CheckBox1_CheckedChanged() aufgerufen wird
- Me.CheckBox1.Checked = False
- Me.Timer1.Enabled = True
- End Sub
- Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
- ' Timer togglen
- Me.Timer1.Enabled = Not Me.Timer1.Enabled
- End Sub
- Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
- ' die Zeit-Koordinate
- Dim t = Me.coord / 10
- ' - y wegen technischen Koordinaten, die y-Achse zeigt nach oben
- ' feste Kurve
- Dim y1 = -100 * Math.Sin(t)
- ' variable Kurve: Amplitude und Frequenz
- Dim y2 = -10 * Me.NumericUpDown1.Value * Math.Sin(t * Me.NumericUpDown2.Value)
- ' Daten für die horizontale Darstellung bereitstellen
- Me.points1.Add(New PointF(Convert.ToSingle(t), Convert.ToSingle(y1)))
- Me.points2.Add(New PointF(Convert.ToSingle(t), Convert.ToSingle(y2)))
- ' Bildbreite festlegen
- If Me.points1.Count > 500 Then
- Me.points1.RemoveAt(0)
- Me.points2.RemoveAt(0)
- End If
- ' nächste Koordinate
- Me.coord += 1
- Me.PictureBox1.Invalidate()
- End Sub
- Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
- ' Darstellungsbedingungen abtesten
- If Me.points1 Is Nothing OrElse Me.points1.Count < 10 Then
- Return
- End If
- ' Instanzen bereitstellen
- Dim g1 As GraphicsPath = New GraphicsPath
- Dim g2 As GraphicsPath = New GraphicsPath
- ' befüllen
- g1.AddLines(Me.points1.ToArray)
- g2.AddLines(Me.points2.ToArray)
- ' das Um-Rechteck bestimmen
- Dim rc1 = g1.GetBounds()
- Dim rc2 = g2.GetBounds()
- ' das größere von beiden
- Dim rc = RectangleF.Union(rc1, rc2)
- ' Kurven auf Darstellungsbereich skalieren
- g1.Warp(Me.GetPointsFromRect(), rc)
- g2.Warp(Me.GetPointsFromRect(), rc)
- ' darstellen
- e.Graphics.DrawPath(Pens.Red, g1)
- e.Graphics.DrawPath(Pens.Blue, g2)
- End Sub
- Private Function GetPointsFromRect() As PointF()
- Dim sz = Me.PictureBox1.Size
- ' 3 Rechteck-Punkte in ein Point-Array konvertieren
- ' (- 1): Rectangle-Effekt berücksichtigen
- Return New PointF() {New PointF(0, 0), New PointF(sz.Width - 1, 0), New PointF(0, sz.Height - 1)}
- End Function
- Private Sub PictureBox1_Resize(sender As Object, e As EventArgs) Handles PictureBox1.Resize
- ' falls der Timer gerade aus ist
- Me.PictureBox1.Invalidate()
- End Sub
- End Class
Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert!
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert!