Oszilloskop - dynamische Darstellung beliebiger Kurven

    • VB.NET
    • .NET (FX) 1.0–2.0

    Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von egon.

      Oszilloskop - dynamische Darstellung beliebiger Kurven

      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 List(Of PointF)
      Interessant ist der Teil der Darstellung.
      Hier wird durch Verwendung 2er GraphicsPaths 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.
      Oszilloskop

      VB.NET-Quellcode

      1. Imports System.Drawing.Drawing2D
      2. Public Class Form1
      3. ' Lists für 2 Datenreihen
      4. Private points1 As List(Of PointF)
      5. Private points2 As List(Of PointF)
      6. ' Rechen-Koordinate
      7. Private coord As Integer = 0
      8. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      9. Me.Timer1.Interval = 20 ' schnell genug
      10. End Sub
      11. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
      12. Me.points1 = New List(Of PointF)
      13. Me.points2 = New List(Of PointF)
      14. Me.coord = 0
      15. ' zuerst Check, dann Timer, weil CheckBox1_CheckedChanged() aufgerufen wird
      16. Me.CheckBox1.Checked = False
      17. Me.Timer1.Enabled = True
      18. End Sub
      19. Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
      20. ' Timer togglen
      21. Me.Timer1.Enabled = Not Me.Timer1.Enabled
      22. End Sub
      23. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
      24. ' die Zeit-Koordinate
      25. Dim t = Me.coord / 10
      26. ' - y wegen technischen Koordinaten, die y-Achse zeigt nach oben
      27. ' feste Kurve
      28. Dim y1 = -100 * Math.Sin(t)
      29. ' variable Kurve: Amplitude und Frequenz
      30. Dim y2 = -10 * Me.NumericUpDown1.Value * Math.Sin(t * Me.NumericUpDown2.Value)
      31. ' Daten für die horizontale Darstellung bereitstellen
      32. Me.points1.Add(New PointF(Convert.ToSingle(t), Convert.ToSingle(y1)))
      33. Me.points2.Add(New PointF(Convert.ToSingle(t), Convert.ToSingle(y2)))
      34. ' Bildbreite festlegen
      35. If Me.points1.Count > 500 Then
      36. Me.points1.RemoveAt(0)
      37. Me.points2.RemoveAt(0)
      38. End If
      39. ' nächste Koordinate
      40. Me.coord += 1
      41. Me.PictureBox1.Invalidate()
      42. End Sub
      43. Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
      44. ' Darstellungsbedingungen abtesten
      45. If Me.points1 Is Nothing OrElse Me.points1.Count < 10 Then
      46. Return
      47. End If
      48. ' Instanzen bereitstellen
      49. Dim g1 As GraphicsPath = New GraphicsPath
      50. Dim g2 As GraphicsPath = New GraphicsPath
      51. ' befüllen
      52. g1.AddLines(Me.points1.ToArray)
      53. g2.AddLines(Me.points2.ToArray)
      54. ' das Um-Rechteck bestimmen
      55. Dim rc1 = g1.GetBounds()
      56. Dim rc2 = g2.GetBounds()
      57. ' das größere von beiden
      58. Dim rc = RectangleF.Union(rc1, rc2)
      59. ' Kurven auf Darstellungsbereich skalieren
      60. g1.Warp(Me.GetPointsFromRect(), rc)
      61. g2.Warp(Me.GetPointsFromRect(), rc)
      62. ' darstellen
      63. e.Graphics.DrawPath(Pens.Red, g1)
      64. e.Graphics.DrawPath(Pens.Blue, g2)
      65. End Sub
      66. Private Function GetPointsFromRect() As PointF()
      67. Dim sz = Me.PictureBox1.Size
      68. ' 3 Rechteck-Punkte in ein Point-Array konvertieren
      69. ' (- 1): Rectangle-Effekt berücksichtigen
      70. Return New PointF() {New PointF(0, 0), New PointF(sz.Width - 1, 0), New PointF(0, sz.Height - 1)}
      71. End Function
      72. Private Sub PictureBox1_Resize(sender As Object, e As EventArgs) Handles PictureBox1.Resize
      73. ' falls der Timer gerade aus ist
      74. Me.PictureBox1.Invalidate()
      75. End Sub
      76. End Class
      Dateien
      • Oszilloskop.zip

        (16,82 kB, 386 mal heruntergeladen, zuletzt: )
      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!

      nafets schrieb:

      keine Queue
      Ich sehe bei einer Queue(Of T) keinen Gewinn gegenüber einer List(Of T), sondern einen praktisch identischen Aufwand. In diesem Fall verspricht die List(Of T) eine höhere Performance.
      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!

      egon schrieb:

      Fehlermeldung
      Laden und laufen lassen sollte eigentlich gehen.
      Das Projekt steht auf Framework 2.0 und AnyCPU. Kann sein, dass Du bei W8 und VS2013 da keinen 2.0-er Support hast.
      Was hast Du für einen Rechner / Sudio?
      Ändere das Framework.
      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!