Hallo Profis.
Ich habe erstmal folgende Frage an Euch.
Ich möchte an meinem 128x64 glcd eine Sinus-Kurve darstellen.
Bis jetzt habe ich eine Funktion mit der ich nur einen Punkt darstellen
kann.
set_pixel(x,y); //schreibt einen Pixel auf dem LCD
Hat jemand vielleicht eine Funktion/Lib mit der ich eine gesamte Sinus
Kurve
darstellen kann ???
Wäre es möglich meine set_pixel Funktion in die Sinus Funktion zu
implementieren?
Für Antworten sowie Anregungen bin ich sehr Dankbar.
Liebe Grüße
Adam
Hi,
ich denke die einfachste Möglichkeit wäre, eine Tabelle anzulegen, in
der die Sinuswerte für 90° eingetragen sind. Durch Spiegelung etc.
erreichst du dann die anderen Werte. Die Anzahl der Einträge bestimmt
die Genauigkeit, also z.B. 0.5°- oder 1°-Schritte. Über die Gradangabe
ermittelst du den Sinuswert.
Ralf
Danke Ralf.
Hast Du vielleicht ein Link bzw ein Beispiel dafür ?
Wie Du merkst ist das Darstellen von Kurven nicht meine Stärke.
Vieln Dank nochmal für die Antwort.
Liebe grüße
> Ich möchte an meinem 128x64 glcd eine Sinus-Kurve darstellen.
Soso, mit welchem Prozessor denn? Mit welcher Sprache denn?
Es gibt in allen handelsüblichen Programmiersprachen eine Funktion zur
Berechnung eines Sinus-Wertes ( sowas wie sin() ). Die liefert dann
einen Wert zwischen -1 und +1 zurück, den mußt du nur noch entsprechend
skalieren und einen Offset dazuaddieren. Und dann dein set_pixel()
aufrufen.
Hallo Lothar.
Danke erstmal für die rasche Antwort.
Controller : Atmega32
Sprache : C
GLCD : 128x64
ich kann also einen Punkt am glcd "zeichnen". Soweit bin ich :o)
In wieweit kann ich denn math.h miteinbeziehen ???
Habe außerdem noch folgendes gefunden :
for(fx=0;fx<=129;fx=fx+1)
{
fy=((sin(fx/10)*20)+ 64);
LCD_pixel_write8((int8)(fx), (int8)(fy),BLACK);
fy=((sin(fx/10+128)*20)+ 64);
LCD_pixel_write8((int8)(fx), (int8)(fy),BLACK);
}
Dies gibt mir jedoch nur "Quatsch" aus...
Ich komme da einfach nicht weiter
Liebe Grüße
Adam wrote:
> Danke Ralf.>> Hast Du vielleicht ein Link bzw ein Beispiel dafür ?>> Wie Du merkst ist das Darstellen von Kurven nicht meine Stärke.
Du musst dir eine Funktion ausdenken, die deine Kurve realisiert, indem
du ein x vorgibst.
Dann lässt du das x in einer for-Schleife von 0 bis 127 laufen, rufst
deine Funktion dafür auf (und erhältst so den y-Wert) und rufst deine
set_pixel mit den so bekannten Werten auf.
Deine Funktion muss jetzt nur noch dafür sorgen, dass die errechneten
y-Werte in einem sinnvollen Bereich (bei dir 0 bis 63) liegen. Das
kannst du aber durch Mutliplikationen bzw. Addition von Werten leicht
erreichen.
zb. liefert ein Sinus ja Werte zwischen -1 und +1
Damit die in den Bereich 0 bis 63 zu liegen kommen, kannst du zb. mit 31
multiplizieren (dadurch wird der Wertebereich zu -31 bis +31) und dann
noch 32 addieren (was den Wertebereich auf 0 bis 63 verschiebt)
y = sin( x ) * 31 + 32;
indem du das Argument for x noch mit einem Faktor multiplizierst oder
dividierst, kannst du jetzt den Sinus in die Länge ziehen
1
#include<math.h>
2
3
....
4
5
6
voidplot_sinus()
7
{
8
intx;
9
inty;
10
11
for(x=0;x<128;++x){
12
y=sin(x/0.5)*31+32;
13
14
set_pixel(x,y);
15
}
16
}
Du wirst wahrscheinlich auch schnell sehen, wo die Grenzen dieses
einfachen Verfahrens liegen: WEnn sich deine Kurve nur schnell genug
zwischen 2 benachbarten X-Werten verändert, entsteht eine Lücke, weil ja
die zugehörigen Y-Werte mehr als 1 Pixel auseinander liegen. In dem Fall
müsste mann dann einfach Linien zwischen jeweils 2 benachbarten (x,y)
Wertepaaren zeichnen.
> y = sin( x ) * 31 + 32;
wobei anzumerken ist, das sin() einen Wert zwischen 0 und 2*PI für einen
vollständigen Umlauf erwartet.
Also wäre für
> x in einer for-Schleife von 0 bis 127...
die Funktion besser mit einen skalierten Wert aufzurufen:
y = sin( x*2*PI/128 ) * 31 + 32;
EDIT:
> y = sin( x / 0.5 ) * 31 + 32;
Liege ich so falsch? :-/
Vielen Dank Euch Beiden !
@Karl heinz Buchegger
@Lothar Miller
Beide Beiträge waren sehr hilfreich und haben zum Ergebnis geführt..
Lösung :
void plot_sinus()
{
int x;
int y;
for( x = 0; x < 128; ++x ) {
y = sin( x*2*3.14/128 ) * 31 + 32;
set_pixel( x, y );
}
}
Anstatt PI musste ich jedoch mit 3.14 angeben. (PI wird nicht akzeptiert
)
Nun habe ich eine Sinuskurve :o)
Vielen Dank für die Hilfe
Liebe Grüße
Lothar Miller wrote:
>> EDIT:>> y = sin( x / 0.5 ) * 31 + 32;> Liege ich so falsch? :-/
Nein, überhaupt nicht. Hängt davon ab, wieviele Sinus-Schwingungen er
sehen will. Und ein bischen was zum Nachdenken soll für den TO ja
schliesslich auch noch bleiben.
Der Hinweis mit dem Winkelargument in Radianten war schon wichtig.
Hallo nochmal!
Die Sinuskurve wird von der Mitte des LCD´s gezeichnet sprich in der
rechten Hälfte des LCD´s bis zum rechten Rand.
Dann wird sie weiter in der linken Hälfte der LCD´s bis zu Mitte
gzeichnet.
Warum (wahrscheinlich gibt es dafür eine einfache Erklärung )????
Am Chipselect liegt es 100%-ig nicht. Das kann ich außschliessen.
Liebe Grüße
Adam
Ein paar Experimente und daraus folgende Schlussfolgerungen solltest du
schon selbst machen.
Zb. Welcher Punkt wird bei setpixel( 0, 0 ) eingeschaltet?
Hallo Karl heinz.
Bitte überbewerte meine AVR-kenntnisse nicht. Bin ein blutiger
Anfänger :o) sorry
laut :
for( x = 0; x < 128; ++x ) {
y = sin( x*2*3.14/128 ) * 31 + 32;
set_pixel( x, y );
wird der erste Punkt bei x=0 und y=32 gesetzt.
Das wäre die absolute linke Hälfte des LCD´s nicht die Mitte.
irgendwie tappe ich noch im Dunkeln.
Gruß
Adam wrote:
> Hallo Karl heinz.> Bitte überbewerte meine AVR-kenntnisse nicht. Bin ein blutiger> Anfänger :o) sorry
Das hat nichts mit AVR zu tun.
> laut :>> for( x = 0; x < 128; ++x ) {> y = sin( x*2*3.14/128 ) * 31 + 32;>> set_pixel( x, y );>> wird der erste Punkt bei x=0 und y=32 gesetzt.> Das wäre die absolute linke Hälfte des LCD´s nicht die Mitte.
Sagt wer?
Was macht denn die set_pixel Funktion?
Die kann ihren 0-Punkt überall haben, wo sie will.
Links/oben
Links/unten
Mitte/Mitte
Mitte/oben
Mitte/unten
....
und ja nachdem, wo die set_pixel ihren 0-Punkt hat, verschieben sich
dann natürlich alle andern Funktionen, die auf set_pixel aufbauen.
Also gilt es erst mal rauszufinden, welches Pixel von set_pixel
eingeschaltet wird, wenn set_pixel(0,0) aufgerufen wird.
Und genau das meine ich mit: Die siehst einen seltsamen Effekt,
überlegst dir was es sein könnte, klärst ihn ab und hast etwas ganz auf
eigene Fasut gelernt. Ganz zu schweigen vom Erkentnissgewinn, dass
höhere Funktionen (wie das Zeichnen einer Kurve) genau dann von den
genauen Eigenschaften einer niedrigern Funktion (wie set_pixel) abhängen
und man daher oft auch deren Details kennen sollte.
Vielleicht ist aber auch einfach nur dein GLCD verdreht und das was du
als X-Achse ansiehst, ist in Wirklichkeit die Y-Achse.
Oder ...
Olaf wrote:
>> Mitte/Mitte>> Hat sowas schonmal irgendwo einer gesehen?
Macht man sogar relativ oft, dass bei einer Window/Viewport
Transformation das default Window [-1..+1, -1..+1] lautet, der 0-Punkt
also in der Mitte liegt.
> Und werden dann Pixel> ueber Radius und Gon adressiert? :-D
LOL
Wenns dir Spass macht kannst du das auch so kriegen.
Hallo.
@Karl heinz Buchegger
Also. Ich habe den "Fehler" gefunden.
Es hatte doch (peinlich) was mit den Display-Controllern zu tun.
Die CS1 und CS2 Anschlüsse waren zwar korrekt verdrahtet aber
in der set_pixel Funktion habe ich einen Dreher gehabt und habe
nun CS1 und CS2 vertauscht.
<i>Am Chipselect liegt es 100%-ig nicht. Das kann ich außschliessen.</i>
Die Aussage bezog sich nur auf die Verdrahtung und nicht auf die
softwaremäßige Auswahl der Chipselect.
Aus Fehlern lernt man.
Jetzt versuche ich mal eine Variablenabhängige Sinus Funktion
darzustellen.
Ich komme wieder :o)
Danke mal wieder für die Hilfe.
Grüße
Hi,
habe folgendes Problem mit der hier diskutierten Routine. Compiler ist
AVR Studio 4.16 und Chip ein ATmega644 mit 16MHz. Display ist ein
320x240 Grafik-LCD mit SSD2119 LCD-Controller.
1
voidplot_sinus(void)
2
{
3
intx;
4
inty;
5
6
for(x=0;x<128;++x)
7
{
8
y=sin(x*2*3.14/128)*31+32;
9
LCDD_DrawPixel(hor_left_aligned,x,y,WHITE);
10
}
11
}
Diese Funktion generiert im Bereich von x=14 bis x=48 fehlerhafte Werte.
y nimmt in diesem Bereich nur Werte von 2, 32 oder 36 an. Außerhalb des
Bereichs stimmen die Werte von y. Setze ich jetzt z.B. x=19 ohne
for-Schleife, dann passt das Ergebnis mit y=56. In der for-Schleife ist
aber bei x=19 das Ergebnis für y=2 ?!?
Kann mir da jemand weiterhelfen?
Gruß
Richard
Paul W. schrieb:
> Ohne Gewähr, liegt das vielleicht an Rundungsfehlern, hervorgerufen> durch die ints?
Nicht in der Größenordnung.
Irgendetwas läuft da mächtig schief, aber ich kann nicht sagen was.
Der Codeausschnitt ist auf jeden Fall in Ordnung.
Adam schrieb:
>> Anstatt PI musste ich jedoch mit 3.14 angeben. (PI wird nicht akzeptiert)>
In der math.h gibt es einen Define M_PI geben, der Pi auf einige
Dezimalstellen genau angibt: