Forum: Mikrocontroller und Digitale Elektronik Parabel mit UC ATtiny2313 berechnen


von H. G. (ledi)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte wie in der Grafik beschrieben eine rote LED in Form einer 
Parabel zu einer weißen LED dazu mischen.

Zuerst wollte ich das über eine Wertetabelle machen, aber bei einem 
Array mit 256 int. Werten ist mein Datenspeicher um das 4-fache 
überschritten!

Hat jemand einen Vorschlag (ohne den UC zu tauschen) was ich hier machen 
kann?

von avr (Gast)


Lesenswert?

H. G. schrieb:
> Array mit 256 int. Werten ist mein Datenspeicher um das 4-fache
> überschritten!

Kann ich mir nicht vorstellen. Das wären ja 8KB. 256 int-Werte brauchen 
512 Byte.

> Hat jemand einen Vorschlag (ohne den UC zu tauschen) was ich hier machen
> kann?

Die Parabel zur Laufzeit mit Festkommaarithmetik berechnen.

von c-hater (Gast)


Lesenswert?

H. G. schrieb:

> ich möchte wie in der Grafik beschrieben eine rote LED in Form einer
> Parabel zu einer weißen LED dazu mischen.

Naja, unter einer Parabel verstehe ich was anderes. Das in der Grafik 
sieht eher wie Kreissegmente aus.

Aber egal, sie zeigen trotz der eigenwilligen Form eine wichtige Sache: 
Symmetrie. D.h.: den beklagten Speicheplatzbedarf kann man schonmal 
Vierteln, selbst wenn man das Konzept der der Lookup-Tabelle beibehält.

Ansonsten halt berechnen. Google-Futter: "Newton-Iteration". Is' noch 
nicht so teuer bei 16-Bit. Wenn man sich noch ein schönes Verfahren zur 
Gewinung eines guten Startwerts ausdenkt, sollte man mit deutlich unter 
100 Takten pro Funktionsaufruf auskommen können, würde ich mal ganz grob 
abschätzen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

H. G. schrieb:
> ich möchte wie in der Grafik beschrieben eine rote LED in Form einer
> Parabel zu einer weißen LED dazu mischen.

Parabel? Das ist eher ne Zykloide oder Ellipsenbögen.

von Floh (Gast)


Lesenswert?

H. G. schrieb:
> Array mit 256 int. Werten

1. Werte als Tabelle in den Flash legen -> "progmem"

2. Ein Viertelbogen reicht aus, der Rest ist nur Wiederholung 
rückwärtsund dann nochmal von vorn.

3. Gibt es auch Möglichkeiten, die Parabel (solls jetzt eine sein?) 
auszurechenen. Ein tiny braucht für ne SW-Multiplikation ca 20 Takte, 
die Formel einer Parabel mit y=a*x*x + b*x + c ist jetzt nicht so 
wahnsinnig komplex zu rechnen.

4. Kann man sie notfalls annähern -> Newton oder ähnliche

von Norbert (Gast)


Lesenswert?

Look-Up Tabelle mit ca. 10 - 16 Stützpunkten und die Zwischenwerte 
interpolieren. Sollte fürs Auge mehr als ausreichend sein!

von H. G. (ledi)


Lesenswert?

Norbert schrieb:
> Look-Up Tabelle mit ca. 10 - 16 Stützpunkten und die Zwischenwerte
> interpolieren. Sollte fürs Auge mehr als ausreichend sein!

Das kling interessant!
Hast du hier etwas mehr info? Wie geht interpolieren? Beispiel?

von H. G. (ledi)


Lesenswert?

avr schrieb:
> H. G. schrieb:
>> Array mit 256 int. Werten ist mein Datenspeicher um das 4-fache
>> überschritten!
>
> Kann ich mir nicht vorstellen. Das wären ja 8KB. 256 int-Werte brauchen
> 512 Byte.

Der ATtiny2313 hat nur 128 Bytes an SRAM!
Was du hier meinst ist der Programmspeicher!

von Malte S. (maltest)


Lesenswert?

H. G. schrieb:
> Der ATtiny2313 hat nur 128 Bytes an SRAM!
> Was du hier meinst ist der Programmspeicher!

Und genau da sollst du deine - vorberechnete und eincompilierte - 
Tabelle ablegen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wenn es wirklich eine Parabel werden soll — wozu braucht man da eine 
Tabelle?

von H. G. (ledi)


Lesenswert?

Johann L. schrieb:
> Wenn es wirklich eine Parabel werden soll — wozu braucht man da eine
> Tabelle?

Nun zugegeben, es war schlecht formuliert.
Es ist keine Parabel sondern eher ein Kreisbogen!

von Malte S. (maltest)


Lesenswert?

Braucht man nicht, aber falls er das wie im Eingangspost geschrieben 
so machen will, dann im PROGMEM.

von Karl H. (kbuchegg)


Lesenswert?

H. G. schrieb:
> Norbert schrieb:
>> Look-Up Tabelle mit ca. 10 - 16 Stützpunkten und die Zwischenwerte
>> interpolieren. Sollte fürs Auge mehr als ausreichend sein!
>
> Das kling interessant!
> Hast du hier etwas mehr info? Wie geht interpolieren? Beispiel?


Im einfachsten Fall: linear interpolieren

5 Äpfel kosten 3 Euro, 12 Äpfel kosten 6 Euro (in der Menge wirds 
billiger).
Wieviel kosten 7 Äpfel?
1
   y = f(x) = k*x + d

Aufgabe: bestimme ein k und ein d, so dass die Beziehungen
1
      x =  5     ->  y = f(5) = 3
2
und   x = 12     ->  y = f(12) = 6
gelten.
Na, wenn das eine lineare Interpolation ist, mit der allgemeinen 
Gleichung
1
    y = k * x + d
und ich 2 Wertpaare x und y kenne, dann kann ich das ja mal einsetzen
1
    3 = k * 5 + d
2
    6 = k * 12 + d
macht 2 Gleichungen in 2 Unbekannten und das kann man lösen. Mit den 
dann bekannten Werten für k und d kann ich dann diese lineare 
Interpolation auf jeden beliebigen Wert für x anwenden und kriege den 
Wert für y.


Jetzt hast du allerdings keine Gerade. D.h. eine lineare Interpolation 
wird dir da keine besonders guten Werte liefern.
Das kann man aber umgehen. Schaut man nicht so genau hin, dann kann man 
deinen Kreisbogen sich auch aus zb 5 Geradenstücken zusammengesetzt 
vorstellen. Und für jedes Geradenstück kann man eine eigene lineare 
Interpolation ansetzen. Man muss halt vorher für einen bestimmten Wert 
von x feststellen, welche Gerade überhaupt zuständig ist. Aber das 
sollte ja kein Problem sein. Der Rest ist jetzt nur noch Organisation 
dieser Geraenabschnitte bzw. was damit gleichwertig ist, der 
'Stützstellen', ein bischen raussuchen, zwischen welchen Stützstellen 
der x Wert liegt, für den gerechnet werden soll und ein wenig rechnen 
auf Grundschulniveau. Nichts was einen Tiny umhaut.

Oder aber: Das was man mit einer Geraden kann, kann man natürlich auch 
mit einem Polynom höherer Ordnung machen. Zb. mit einem Polynom 2. 
Grades (eine Gerade wäre ein Polynom 1. Grades), mit der allgemeinen 
Gleichung
1
    y = f(x) = j*x^2 + k*x + d
dann braucht man eben 3 Wertpaare um die Parameter j, k und d zu 
bestimmen. Aber im Endeffekt hat man dann eine Parabel durch diese 3 
Wertpaare gelegt und interpoliert dann eben über diese Parabel. Auch 
hier wieder: hat meine seine Vorarbeiten auf dem Papier erledigt, dann 
bleibt da für den Tiny nicht mehr viel übrig. Durch das Quadrat muss man 
ein wenig vorsichtig sein, dass man keine Overflows in den Berechnungen 
hat, aber das muss man generell sowieso immer im Hinterkopf behalten.

von Thomas K. (rlyeh_drifter) Benutzerseite


Lesenswert?

Das Handrechnen lässt sich mit (Libre-)Office durch LINEST umgehen ;-)
Dort bietet sich auch an gleich die Funktion mit der Näherung zu 
vergleichen

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

H. G. schrieb:
> Es ist keine Parabel sondern eher ein Kreisbogen!

Was heißt "eher"? Hast du die Kurve irgendwie berechnet, oder ist sie 
aus dem Gefühl heraus entstanden?

Wenn letzteres der Fall ist, sind die Genauigkeitsanforderungen 
wahrscheinlich nicht allzu hoch. Du könntest die Kurve in deinem Bild 
dann bspw. durch die Funktion

approximieren. Diese erfordert (nach etwas Umformen) 3 Multiplikationen 
und 3 Additionen, ist also relativ leicht zu berechnen. Der dabei 
entstehende Fehler in der LED-Helligkeit dürfte mit dem Auge kaum 
wahrnehmbar sein. Im Anhang siehst du das Ergebnis für a=-9.84e-6, 
b=-3.70e-2 und c=154.

Das Ganze wird auf dem ATtiny2313 natürlich nicht mit Floating-Point-, 
sondern mit Integer-Arithmetik berechnet. Dazu müssen die Parameter in 
Abhängigkeit des gewünschten Wertebereichs angepasst und die 
Zwischenergebnisse ggf. mit Shift-Operationen skaliert werden.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Yalu X. schrieb:

> Du könntest die Kurve in deinem Bild dann bspw. durch die Funktion
>
> approximieren. Diese erfordert (nach etwas Umformen) 3 Multiplikationen
> und 3 Additionen, ...


...und zudem, daß kein Zwischenergebnis aus dem Wertebereich 
herausfällt, was bei einer Funktion 4. Grades rasch der Fall ist.

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

Johann L. schrieb:
> ...und zudem, daß kein Zwischenergebnis aus dem Wertebereich
> herausfällt, was bei einer Funktion 4. Grades rasch der Fall ist.

Ja klar, siehe hier:

Yalu X. schrieb:
> Das Ganze wird auf dem ATtiny2313 natürlich nicht mit Floating-Point-,
> sondern mit Integer-Arithmetik berechnet. Dazu müssen die Parameter in
> Abhängigkeit des gewünschten Wertebereichs angepasst und die
> Zwischenergebnisse ggf. mit Shift-Operationen skaliert werden.

Das Ganze könnte dann etwa so aussehen:
1
uint8_t dim2pwm(uint8_t x) {
2
  int8_t x1 = x - 128;
3
  uint16_t x2 = x1 * x1;
4
5
  return (uint8_t)(112 - ((3 * x2 + 0x10000) * x2 >> 24));
6
}

x ist der Dim-Wert (0..255, 256 entspricht 100%), das Ergebnis ist der 
PWM-Wert für eine 8-Bit-PWM (0..255, 256 entspricht 100%). Es werden 
zwei 16-Bit- und eine 32-Bit-Multiplikation benötigt. Das Ergebnis ist 
im Anhang zu sehen.

Evtl. kann man hier
1
(3 * x2 + 0x10000)

noch etwas handoptimieren, indem man die Multiplikation mit 3 durch 
Shift und Addition ersetzt (der GCC tut das nicht von selber).

Die Paramater a, b und c der Funktion sind übrigens so gewählt, dass die 
Funktionswerte an den Stellen 0% (x=0), 25% (x=64), 50% (x=128) und 
damit aus Symmetriegründen auch an 75% (x=192) und 100% (x=256) mit dem 
Bild im Eingangsbeitrag übereinstimmt. Zufälligerweise ergibt das sehr 
rechnerfreundliche Parameter (a=-3·2¯²⁴ und b=-2¯⁸).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Spricht eigentlich etwas gegen die Verwendung von Fixed-Point Typen 
(fract, accum, ...), die der aktuelle avr-gcc ja von Hause aus 
unterstützt?

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.