Forum: Mikrocontroller und Digitale Elektronik Graph in Diagramm zeichnen GLCD


von Honkmichi (Gast)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>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

von Honkmichi (Gast)


Lesenswert?

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!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von Martink11 M. (Firma: google) (martink11) Flattr this


Lesenswert?

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!!!

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.