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
voiddia_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
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.