Hi. Ich versuche schon seit einiger Zeit ein Graph in eine Diagramm auf einem GLCD zu zeichnen. Leider hab ich bis jetzt den richtigen Lösungsweg noch nicht gefunden. Ich möchte den verlauf des Luftdrucks, Temperatur oder Feuchte in einem Diagramm darstellen. Es werden 100 Messwerte in einem Array gespeichert, diesen sollen im Diagramm dargestellt werden. Wenn 100 Messwerte vorliegen soll das älteste gelöscht werden um Platz für das neue zu machen. Das Diagramm soll folgender Maßen aussehen: Der Graph wird von links nach rechts gezeichnet. Sind alle 100 Messwerte gezeichnet, soll sich der Graph in die selbe Richtung weiterrollen. Also links verschwindet ein Pixel, der Graph schiebt sich nach links und rechts wird der neue Wert dargestellt. Dabei soll die Auflösung der Ordinate automatisch ermittelt werden, undzwar so das der größte oder kleinste Wert immer am Rand des Diagramms erscheint. Vielleicht hat einer von euch das schonmal gemacht und kann mit ein Tip geben wie man sowas macht?
>Vielleicht hat einer von euch das schonmal gemacht und kann mit ein Tip >geben wie man sowas macht? Man setzt sich hin, denkt nach und schreibt ein Programm. Honk, honk;) SCNR
Glaub mal nicht das ich das schon gemacht hätte... Diese dummen Sprüche hier immer.... das nervt echt! Ich hab jetzt schon keinen Bock mehr diese Diskusion weiterzuführen! ALSO... sollte irgendjemand von euch auch mal versuchen sowas zu zeichnen und nicht weiterkommen weil das Berechnen des Mittelwertes und das gleichezeite anpassen der Auflösung in Ordinatenrichtung immer eine Grade ergibt... pech gehabt!
Du mußt die Aufgabe einfach aufteilen. 1) Ein Array mit 100 Werten (wir nehmen einfach mal an das alle Werte schon belegt sind) 2) Einen Zeiger auf das älteste Element 3) Eine Funktion welche das älteste Element ersezt und den Zeiger einen weiterschiebt und gleichzeitig das Zeichen zum neuzeichnen Gibt 4) Eine Funktion welche dir das Minimum und das Maximum im Array bestimmt 5) Eine Funktion welche ein Koordinatensystem bei gegeben Min/max zeichnet 6) Eine Funktion welche beginnend beim Wert des Zeigers das Array ausliest, den Wert mit dem aktuellem Skalierungsfaktor multipliziert und ggf rundet und zeichnet. 7) beginne wieder bei 3 Danach kannst du dir eine Funktion schreiben welche diese Punkte noch mit Linien verbindet und fertig ist dein Graph. Wenn du das hast kannst du dir überlegen wie du ggf "noch nicht vorhandene" Werte repräsentierst.
Hallo hier ein kleines Beispiel vielleicht hilft es dir: ist ein code für Auswertung einer Photovoltaikanlage (Atmega16) mit Skala aber die kannst du ja auch weglassen es sind eigentlich nur immer senkrechte linien nebeneinander wo du anstelle des y-wertes deinen gemessenen wert einträgst (mit variable) schaus dir an! kann man auch mit einzelnen punkten machen aber mit linien gefiel es mir besser. --------------------------------------------------------------------- in void dia_data(void) werden die Daten bereitgestellt und gespeichert in array in void dia_anzeige(void) werden sie auf ein KS0108 Grafikdisplay ausgegeben (Breite des Diagramms 120, Höhe 63) ---------------------------------------------------------------------
1 | void dia_data(void) |
2 | {
|
3 | if(diazahler<=119) |
4 | {
|
5 | leidia = leistung/0.25; //Leistung für Diagramm anpassen: 15kw => 60pixel Höhe |
6 | diah[diazahler] = leidia; //wird bis 119 hochgezählt, da 120pixel breite angezeigt werden |
7 | diazahler = diazahler+1; |
8 | }
|
9 | }
|
10 | |
11 | void dia_anzeige(void) |
12 | {
|
13 | xzahler=0; |
14 | data=0; |
15 | |
16 | //-----------------------------------------------------------Skala----------
|
17 | |
18 | ks0108DrawLine(7, 0, 7, 63, BLACK); //senkrecht |
19 | ks0108DrawLine(0, 60, 127, 60, BLACK); //waagrecht |
20 | |
21 | o=15; |
22 | |
23 | for (u=0; u<15; u++) |
24 | {ks0108SetDot(o, 61, BLACK); |
25 | o = o + 8;} |
26 | |
27 | // ks0108SetDot(15, 61, BLACK); //7h
|
28 | // ks0108SetDot(23, 61, BLACK); //8h
|
29 | // ks0108SetDot(31, 61, BLACK); //9h
|
30 | // ks0108SetDot(39, 61, BLACK); //10h
|
31 | // ks0108SetDot(47, 61, BLACK); //11h
|
32 | ks0108DrawLine(55, 61, 55, 62, BLACK); //12h (Mittag) |
33 | // ks0108SetDot(63, 61, BLACK); //13h
|
34 | // ks0108SetDot(71, 61, BLACK); //14h
|
35 | // ks0108SetDot(79, 61, BLACK); //15h
|
36 | // ks0108SetDot(87, 61, BLACK); //16h
|
37 | // ks0108SetDot(95, 61, BLACK); //17h
|
38 | // ks0108SetDot(103, 61, BLACK); //18h
|
39 | // ks0108SetDot(111, 61, BLACK); //19h
|
40 | // ks0108SetDot(119, 61, BLACK); //20h
|
41 | ks0108DrawLine(127, 61, 127, 62, BLACK);//21h (Ende) |
42 | |
43 | o=0; |
44 | for (u=15; u>0; u--) |
45 | {ks0108DrawLine(5, o, 6, o, BLACK); |
46 | o = o + 4;} |
47 | |
48 | // ks0108DrawLine(5, 56, 6, 56, BLACK); //1
|
49 | // ks0108DrawLine(5, 52, 6, 52, BLACK); //2
|
50 | // ks0108DrawLine(5, 48, 6, 48, BLACK); //3
|
51 | // ks0108DrawLine(5, 44, 6, 44, BLACK); //4
|
52 | ks0108DrawLine(3, 40, 6, 40, BLACK); //5 (lang) |
53 | // ks0108DrawLine(5, 36, 6, 36, BLACK); //6
|
54 | // ks0108DrawLine(5, 32, 6, 32, BLACK); //7
|
55 | // ks0108DrawLine(5, 28, 6, 28, BLACK); //8
|
56 | // ks0108DrawLine(5, 24, 6, 24, BLACK); //9
|
57 | ks0108DrawLine(3, 20, 6, 20, BLACK); //10 (lang) |
58 | // ks0108DrawLine(5, 16, 6, 16, BLACK); //11
|
59 | // ks0108DrawLine(5, 12, 6, 12, BLACK); //12
|
60 | // ks0108DrawLine(5, 8, 6, 8, BLACK); //13
|
61 | // ks0108DrawLine(5, 4, 6, 4, BLACK); //14
|
62 | ks0108DrawLine(3, 0, 6, 0, BLACK); //15 (lang) |
63 | |
64 | //------------------------------------------------------------
|
65 | while(xzahler<=119) |
66 | {
|
67 | if(tag==2) |
68 | {ks0108DrawLine(xzahler+8, 60, xzahler+8, 60-diag[data], BLACK);} //gestern senkrechte diagrammlinien |
69 | else {ks0108DrawLine(xzahler+8, 60, xzahler+8, 60-diah[data], BLACK);} //heute senkrechte diagrammlinien |
70 | |
71 | xzahler = xzahler+1; //variable für x-achse wird hochgezählt |
72 | data = data+1; //variable für y-Achse wird hochgezählt |
73 | }
|
74 | }
|
hoffentlich hilft es dir servus martin!!!
Honkmichi schrieb: > Glaub mal nicht das ich das schon gemacht hätte... > > Diese dummen Sprüche hier immer.... das nervt echt! Ich hab jetzt schon > keinen Bock mehr diese Diskusion weiterzuführen! ALSO... sollte > irgendjemand von euch auch mal versuchen sowas zu zeichnen und nicht > weiterkommen weil das Berechnen des Mittelwertes und das gleichezeite > anpassen der Auflösung in Ordinatenrichtung immer eine Grade ergibt... > pech gehabt! Oder man setzt sich mit Papier und Bleistift hin, geht sein Programm durch und findet raus wo man den Denkfehler gemacht hat / den Programmierfehler gemacht hat. Du gibst aber schnell auf :-) Dein Arbeitspferd ist die 'lineare Gleichung' oder 'lineare Transformation' y = k*x + d x und y haben hier nichts mit Pixelkoordinaten zu tun. Die Gleichung beschreibt einfach nur wie ein Ausgangswert x in einen Zielwert y transformiert wird. Bei dir ist der Ausgangswert zb. die Temperatur und der Zielwert ist die Pixelkoordinate in y auf der der Zielwert abgebildet werden soll. Gesucht sind in dieser Gleichung das k und das d, so dass zb ein Messwert von 15 (Grad) auf Pixelkoordinate 25 und ein Messwert von 40 (Grad) auf der Pixelkoordinate 87 abgebildet wird (25 und 87 sind zb die Pixelkoordinaten, so dass dein Diagramm in y-Richtung schön auf den Bildschirm passt) Du hast also 2 bekannte Gleichungen 25 = k*15 + d 87 = k*40 + d 2 Gleichungen in 2 Unbekannten. Na das lässt sich doch lösen! Man erhält k = 2.48 d = -12.2 Probe: Für den Messwert 15: 2.48*15 + (-12.2) = 25 Für den Messwert 40: 2.48*40 + (-12.2) = 87 Stimmt genau. Die Gleichung mit diesen Werten für k und d reproduziert genau das gewünschte Verhalten. Ein Messwert von 28 würde daher auf der Pixelkoordinate 2.48*28 + (-12.2) = 57.24 =~= 57 abgebildet werden. Damit hast du ein Werkzeug um einen Temperaturbereich festzulegen, des weiteren festzulegen, wo diese Temperaturen in Y-Richtung auf deinem GLCD abgebildet werden sollen und wie diese Umrechnung erfolgen soll. Was du brauchst, ist natürlich die Kentniss des minimalen und des maximalen Wertes, denn diese sollen ja so eingepasst werden, dass sich die Kurve am Schirm dazwischen abspielt und diese minimal/maximimalen Werte auf bestimmten Pixel-Koordinaten an der Ordinate abgebildet werden. Du brauchst daher das Minimum und das Maximum (und nicht den Mittelwert). Diese Werte zu bestimmen sollte nun aber wirklich kein großes Problem sein. PS. Man kann dieselbe lineare Transformation auch in der X-Achse des Diagramms machen. Gegeben eine Punktwolke aus irgendwelchen Messwerten. Gesucht: die Koeffizienten k1, k2, d1, d2 - so dass PixelX = k1 * MesswertX + d1 PixelY = k2 * MesswertY + d2 die Punktwolke mit den minimalen Werten MinMesswertX/MinMesswertY und MaxMesswertX/MaxMesswertY auf dem Bildschirm in ein Rechteck MinPixelX/MinPixelY bzw MaxPixelX/MaxPixelY einpasst. Man nennt so etwas in der Graphik eine Window/Viewport Transformation. Das Window sind die Ausgangswerte und das Viewport sind die umgerechneten Werte. Die Window/Viewport Trafo sind die beiden obigen Gleichungen und sie rechnen einen rechteckigen Bereich aus den Ausgangswerten in einen rechteckigen Bereich in den Zielwerten um. Jedes Graphiksystem kann das. Das Arbeitspferd dafür ist aber immer die lineare Gleichung. (Und nicht nur ein Skalierfaktor, wie weiter oben angedeutet) PS: Ich würde dir auch davon abraten, die Minimalen und Maximalen Werte laufend an die Messwerte anzupassen. Der Effekt wird dann nämlich sein, dass deine Kurve auf dem Schirm je nachdem welche Werte neu dazukommen bzw. wegkommen, durch die Gegend driften wird. Und das ist nicht besonders gut, weil der Benutzer dann jedesmal auf die Achsbechriftung sehen muss um zu wissen, ob eine Kurve im oberen Diagrammdrittel nun tatsächlich auf einen hohen Wert hinweist oder ob er einfach nur durch die Anpassung dorthingekommen ist. Leg einfach sinnvolle fixe Grenzen fest und belasse es dabei.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.