Forum: Mikrocontroller und Digitale Elektronik aus ansteigenden Werten eine halbe Sinuswelle generieren - Arduino


von Kolja L. (kolja82)


Lesenswert?

Hallo

Warum kann ich, oder die ArduinoIDE, keine Welle machen ;-)
j läuft von 0-33 immer wieder hoch und ich hätte gerne halbe (positive) 
Sinuswellen über die Schleife:

Die map() Funktion kann wohl nur mit ganzen Zahlen rechnen,
aber ich kann es auch nicht nachträglich erzwingen:

    float tick = sin(map(j, 0, 33, 0, 3141)/1000);

gibt nur das aus:

0 0.00
...
10 0.00
11 0.84
...
21 0.84
22 0.91
...
31 0.91
32 0.14
33 0.14

von foobar (Gast)


Lesenswert?

Dein "map(...)/1000" ergibt nur ints. Mach mal nen "map(...)/1000.0" 
raus, dann macht er ne float-Division.

von Wolfgang (Gast)


Lesenswert?

Kolja L. schrieb:
> Die map() Funktion kann wohl nur mit ganzen Zahlen rechnen,
> aber ich kann es auch nicht nachträglich erzwingen:
>
>     float tick = sin(map(j, 0, 33, 0, 3141)/1000);
>
> gibt nur das aus:
>
> 0 0.00
> ...
> 10 0.00

Und was gefällt dir daran nicht?
Was erwartest du?

map() ist in Arduino als long deklariert, d.h. liefert nur ganze Zahlen.
https://www.arduino.cc/reference/en/language/functions/math/map/

Durch 1000 dividiert bekommst du also auch ganze Zahlen, d.h. es können 
die Werte 0,1,2 oder 3 auftreten. Für die sin()-Berechnung werden die 
automatisch in float gekastet und die Funktion liefert dir genau die 
Werte 0.84, 0.91, 0.14 oder 0.00
Der Rechner macht genau das, was du ihm gesagt hast ;-)

von Falk B. (falk)


Lesenswert?

@Kolja L. (kolja82)

>Warum kann ich, oder die ArduinoIDE, keine Welle machen ;-)

Du kannst es nicht.

>j läuft von 0-33 immer wieder hoch und ich hätte gerne halbe (positive)
>Sinuswellen über die Schleife:

Und warum nimmst du dafür nicht wie jeder einfac die Sinusfunktion mit 
passender Skalierung?

>Die map() Funktion kann wohl nur mit ganzen Zahlen rechnen,

Die ist was für Knalltüten, die nicht mal 7. Klassemathematik 
beherrschen.

float tick = sin(3.1415/33*j);

Der Parameter von Sinus ist ein Winkel im Bogenmaß, 0-2Pi. Du willst nur 
bis Pi rechnen (halber Sinus), also muss man bei j=33 auf Pi kommen.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

An dieser Stelle würde allerdings nicht die Rechenintensive Sinus 
Funktion benutzen, sondern eine Übersetzungstabelle, die ich vorher mit 
einer Tabellenkalkulation erstellt habe.
1
float sinus_tabelle[]={0.098, 0.195, ... };
2
float sinus=sinus_tabelle[j];

Um RAM zu sparen, könnte man diese Tabelle im Flash Speicher halten (mit 
PROGMEM).

Auch würde ich vermeiden, das Ergebnis als Fließkommazahl weiter zu 
verarbeiten. Am Ende wirst du sehr wahrscheinlich etwas digitales 
steuern, was Boolean oder Integer benötigt.

Ein PWM Ausgang braucht zum Beispiel 8bit Werte zwischen 0 und 255, 
nicht Float zwischen 0 und 1. Das kannst du bereits in der 
Übersetzungstabelle berücksichtigen.

von max123 (Gast)


Lesenswert?

#include <math.h>
unsigned char fe[32];
int i;

void setup() {
  Serial.begin(9600);
  // Tabelle aufstellen
  for (i = 0; i < 32; i++)
    fe[i] = 127 + 127 * sin( i / 32.0 * 3.1415 );


  // Tabelle ausgeben
  for (i = 0; i < 32; i++ )
    Serial.println((int)fe[i]);
}

void loop() {
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Stefanus F. schrieb:
> sondern eine Übersetzungstabelle, die ich vorher mit
> einer Tabellenkalkulation erstellt habe.

Oder einfach online:
http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml

Macht dir ne Copy&Paste Tabelle, die direkt in C passt.

von Tim (Gast)


Lesenswert?

Oder on-the-fly ausrechnen:
1
uint8_t sine_wave[ 256]; 
2
3
void calculate_sine( void)
4
{
5
    int16_t x = 0;
6
    int16_t y = 8180;
7
    for( int i = 0; i < 256; i++)
8
    {
9
        x = x + ( y * 4) / 163;
10
        y = y - ( x * 4) / 163;
11
        sine_wave[i] = 128 + ( x >> 6);
12
    }
13
}

von max123 (Gast)


Lesenswert?

Hallo Tim,
danke für das Programm und um eine Programmerklärung.

von max123 (Gast)


Lesenswert?

Hallo Tim,
danke für das Programm und bitte um eine Programmerklärung.

von Tim (Gast)


Lesenswert?

max123 schrieb:
> danke für das Programm und bitte um eine Programmerklärung.
Ich habe die Funktion ursprünglich hier gefunden:
http://www.technoblogy.com/show?22HF

Dort wird sie als "Minsky circle algorithm" beschrieben.

Für mich sieht es nach einem "Equi-amplitude staggered update 
oscillator" aus.
Ein bischen Theorie dazu ist u.a. hier zu finden:
http://www.usbsoundcard.com/images/pdfs/digital_resonators.pdf

Immerhin mit dem Verweis, das das grundlegende Verfahren schon 1572 von 
François Viète beschrieben und genutzt wurde...

von Plaste & Elaste (Gast)


Lesenswert?

Tim schrieb:

> Immerhin mit dem Verweis, das das grundlegende Verfahren schon 1572 von
> François Viète beschrieben und genutzt wurde...

Das muß aber dann auf einem Rechner noch vor dem Robotron R300 gewesen 
sein.
;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.