C# Sinus kurve

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    C# Sinus kurve

    Hallo liebe community,

    ich habe mal wieder ein Problem in C#.

    Und zwar soll ich ein Programm entwickeln welches ein Signal Simuliert.
    Das Signal bekomme ich folgt:
    Spoiler anzeigen

    C#-Quellcode

    1. private SignalType signalType = SignalType.Sinus;
    2. public SignalType SignalType
    3. {
    4. get { return signalType; }
    5. set { signalType = value; }
    6. }
    7. private float frequency = 1f;
    8. public float Frequency
    9. {
    10. get { return frequency; }
    11. set { frequency = value; }
    12. }
    13. private float amplitude = 1f;
    14. public float Amplitude
    15. {
    16. get { return amplitude; }
    17. set { amplitude = value; }
    18. }
    19. private float phase = 0f;
    20. public float Phase
    21. {
    22. get { return phase; }
    23. set { phase = value; }
    24. }
    25. private float offset = 0f;
    26. public float Offset
    27. {
    28. get { return offset; }
    29. set { offset = value; }
    30. }
    31. private float invert = 1;
    32. public bool Invert
    33. {
    34. get { return invert == -1; }
    35. set { invert = value ? -1 : 1; }
    36. }
    37. private long startTime = Stopwatch.GetTimestamp();
    38. private long ticksPerSecond = Stopwatch.Frequency;
    39. public float GetValue(float time)
    40. {
    41. float value = 0f;
    42. float t = frequency * time;// + phase;
    43. switch (SignalType)
    44. {
    45. case SignalType.Sinus:
    46. {
    47. //sin( 2 * pi * t )
    48. value = (float)Math.Sin(2f * Math.PI * t);
    49. }
    50. break;
    51. case SignalType.Rechteck:
    52. {
    53. //sign(sin(2*pi*t))
    54. value = Math.Sign(Math.Sin(2f * Math.PI * t));
    55. }
    56. break;
    57. case SignalType.Sägezahn:
    58. {
    59. // 2 * ( t/a - floor( t/a + 1/2 ) )
    60. value = 2f * (t - (float)Math.Floor(t + 0.5f));
    61. }
    62. break;
    63. }
    64. return (invert * amplitude * value + offset);
    65. }
    66. public float GetValue()
    67. {
    68. float time = (float)(Stopwatch.GetTimestamp() - startTime)
    69. / ticksPerSecond;
    70. return GetValue(time);
    71. }
    72. public void Reset()
    73. {
    74. startTime = Stopwatch.GetTimestamp();
    75. }



    Dies so in einem Chart einzufügen ist auch kein Problem und funktioniert einwandfrei:

    C#-Quellcode

    1. private void timer1_Tick(object sender, EventArgs e)
    2. {
    3. chart1.Series[0].Points.AddY(Math.Min(signalGenerator.GetValue(), 100));
    4. }

    Das Intervall beträgt 60ms.

    Wenn ich aber versuche dies in ein Array zu übertragen:

    C#-Quellcode

    1. public double[] GetSignalBlock(int BlockSize)
    2. {
    3. double[] block = new double[BlockSize];
    4. for(int i = 0; i < block.Length; i++)
    5. {
    6. block[i] = Math.Min(gen.GetValue(), 100);
    7. }
    8. return block;
    9. }


    und dieses dann auf das Chart übertragen möchte zeigt er mir zwar etwas an jedoch nicht die gewünschte Sinuskurve:

    C#-Quellcode

    1. double[] data = cd.GetSignalBlock(4096);
    2. chart2.Series[0].Points.Add(data);



    Kann mir jemand weiterhelfen?

    Vielen Dank im Vorraus

    LG Mausekeks :)
    Brain is Loading: 35%

    mausekeks schrieb:

    zeigt er mir zwar etwas an
    Was zeigt er sdenn an?
    Ich nehme mal an, dass Deine zeit-basierte Berechnung der Stützstellen nicht das tut, was Du glaubst, dass sie tut.
    Liste mal die Stützstellen auf und überlege, ob dieses Herangehen sinnvoll ist.
    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!
    Deine Codezeile

    C#-Quellcode

    1. chart2.Series[0].Points.Add(data);
    fügt einem einzigen X-Wert 4096 Y-Werte zu. Gut zu sehen, wenn Du in der Folgezeile einen Haltepunkt setzt und Dir die Chart-Series-Points-Auflistung ansiehst.

    (Aussagekräftig ohne Ende. Da waren die Übersetzungen in VB2010 m.E. deutlich besser. Aber im NSDN sind die genauso. Da kommen wohl keine Übersetzer, sondern nur noch Programme zum Zuge, oder?)
    Im Original zumindest etwas deutlicher:
    "Adds a new DataPoint object to the collection and sets its Y value."
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    mausekeks schrieb:


    Dies so in einem Chart einzufügen ist auch kein Problem und funktioniert einwandfrei:

    C#-Quellcode

    1. private void timer1_Tick(object sender, EventArgs e)
    2. {
    3. chart1.Series[0].Points.AddY(Math.Min(signalGenerator.GetValue(), 100));
    4. }

    Das Intervall beträgt 60ms.


    Insofern ich das Chart-Element und den Code richtig verstehe funktioniert dein Code eher nicht "einwandfrei", sondern weil der Compiler so robust ist. Du übergibst hier nur Y-Werte, keine Punkte (welche ja mindestens aus x und y bestehen). Vermutlich ist der Abstand zwischen zwei Punkten also auch nicht 60ms, sondern einfach Eins (Pixel oder Punkt oder was auch immer, kenne die Einheit hier nicht die automatisch gewählt wird).

    Dazu habe ich noch eine Rückfrage: Warum willst du die Daten überhaupt als Array übergeben?

    Ich persönlich übergebe Daten an das Chart-Element gern als Tabelle, da ich das auch so aus der Datenbank bekomme. Ob dies nun die "beste" Lösung ist weiß ich.
    Hier ein Beispiel wie ich (in vb) Daten an ein Chart-Element übergebe.

    VB.NET-Quellcode

    1. With chart
    2. .Series.Clear()
    3. .DataSource = dt
    4. For col = 1 To dt.Columns.Count - 1
    5. With .Series.Add(dt.Columns(col).ColumnName)
    6. .ChartType = DataVisualization.Charting.SeriesChartType.StepLine
    7. .YValueType = DataVisualization.Charting.ChartValueType.Auto
    8. .YValueMembers = dt.Columns(col).ColumnName
    9. .XValueMember = dt.Columns(0).ColumnName
    10. End With
    11. Next
    12. End With


    ​Bei Tortendiagrammen übergebe ich auch Punkte einzeln über eine Schleife, jedoch folgendermaßen:

    VB.NET-Quellcode

    1. With .Series(0)
    2. For col As Integer = 1 To dt.Columns.Count - 1
    3. .Points.AddXY(dt.Columns(col).ColumnName.ToString, dt.Rows(lstIntervall.SelectedIndex)(col))
    4. Next
    5. End With

    Hi,

    @RodFromGermany

    Ein bild folgt bald
    ausserdem bin ich eine absolute mathe null

    @VaporiZed

    Danke für den Hinweis, stimmt hätte ich selbst sehen können

    @KBT
    Es geht darum das mein Kollege meint ich soll das So machen, da das Signal zu einem späteren Zeitpunkt weiter verarbeitet wird

    "EDIT":
    Mir ist die Idiotie dieser frage bewusst geworden
    =>>Kann es sein das mir die X Punkte komplett fehlen

    Wie berechne ich diese


    LG Mausekeks
    Brain is Loading: 35%

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „mausekeks“ ()

    mausekeks schrieb:


    Wie berechne ich diese
    LG Mausekeks


    Du hast 2 Funktionen namens GetValue. Eine ohne Parameter und eine mit. Du nutzt die Überladung ohne Parameter. Dort wird irgendwie über nen Timer ne Zeit gezogen und an die gleichnamige Funktion mit Parameter übergeben. An der Stelle könntest du dir die wegspeichern. Oder du übergibst selbst Zeitwerte an die Funktion um deine Kurve zu erzeugen.

    Ich persönlich würde vermutlich GetValue ohne Parameter so ändern, dass kein float-Wert sondern ein Point-Wert (mit x und y) zurückgegeben wird. x ist die Zeit des Timers, y ist die Amplitude.

    ​Wenn du dann die Punkte dem Chart-Element übergeben möchtest, übergibst du halt statt mit .AddY beide Parameter mit .AddXY
    Oke danke @KBT,

    hab mein Problem mittlerweile hinbekommen, und mir kurzerhand eine komplett überarbeitete Klasse geschrieben.

    Nun noch eine Frage:
    Wenn ich damit ein Signal erzeuge, wie kann ich auf das erzeugte signal ein Rauschen legen?

    C#-Quellcode

    1. (Amplitude * Math.Sin((2f * Math.PI) * AxisX * Frequency / SampleRate))
    Brain is Loading: 35%
    spontan würde ich sagen nen weiteren Sinus aufs Signal packen mit hoher Frequenz. Oder halt ne Sägezahnfunktion/Rechteckfunktion oder eine Kombination von allem. Das ist dann natürlich nicht zufällig sondern periodisch, selbst wenn du Krumme Frequenzen und auch unterschiedliche für jede dieser Funktionen hernimmst.

    Beispiel: 17f für Frequenz, 29f für Sägezahn, 37f für Rechteck
    ​Alternativ dazu keine Vielfachen von f sondern halt eine ganz andere Frequenz oder gar Frequenzen mit Komma ala 57,3857

    ansonsten: msdn.microsoft.com/de-de/libra…ang=csharp#code-snippet-3
    habe jedoch noch nie mit random gearbeitet und kann da keine Hilfestellung geben
    Nochmal danke an @KBT,

    habe das ganze jetzt per random gelöst:

    C#-Quellcode

    1. for(int i = 0; i < Block.Length; i++)
    2. {
    3. double rauschen = lo + (hi - lo) * rand.Next((int)Amplitude);
    4. Block[i] = (rauschen + GetSinus(i, Amplitude, Frequency, SampleRate));
    5. }
    Brain is Loading: 35%

    mausekeks schrieb:

    habe das ganze jetzt per random gelöst
    Sieh Dir mal die Random.NextDouble()-Methode an: msdn.microsoft.com/de-de/libra…nextdouble(v=vs.110).aspx
    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!