aus ansteigenden Werten eine halbe Sinuswelle generieren - Arduino

OP #5495324
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
Gast #5495344
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 ;-)
#5495361
@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.
Gast #5495392
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.
Angehängte Dateien:
Gast #5522911
#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() {
}
Gast #5523521
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
}
Gast #5527227
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...
Gast #5527319
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.
;)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 8 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.