Forum: Mikrocontroller und Digitale Elektronik Was ist schneller: Runden, Addieren und Abschneiden oder Lookup Table


von Sven (Gast)


Lesenswert?

Hi.

Was ist in der Regel schneller, wenn ein 8 Bit Wert auf einen Wert mit 6 
Stufen umgerechnet werden soll.

-Teilen und runden?
-Teilen, Addieren und Abschneiden
-Lookup Table


Der Wert wird irgendwo permanent ausgelesen und liegt als Bytewert vor.
Er soll dann auf 6 einzelne Portpins umgesetzt werden, die wie bei einem 
VU Meter dann den Wert des Eingangssignals anzeigen. (Wert 1 = LED 1 an, 
Wert 2 = LED 1 und 2 an usw)

von Peter II (Gast)


Lesenswert?

kommt auf die Hardware an. Aber Lookup Table wird wohl oft das 
schnellste sein.

von Der Andere (Gast)


Lesenswert?

Einfach die unteren 2 Bits ausblenden.
Erkläre mal wie du einen binären Wert runden willst.

von Michael K. (Gast)


Lesenswert?

Hängt wohl davon ab ob du nur zwei bit nach linkt shiften willst oder 
was da groß berechnet wird.

von Der Andere (Gast)


Lesenswert?

Der Andere schrieb:
> Einfach die unteren 2 Bits ausblenden.

Bzw binäres nach rechts schieben, je nachdem welche portpins benutzt 
werden sollen.
Sind die Pins aus welchem Grund auch immer durcheinander, macht eine 
Tabelle ggf. Sinn.

Peter II schrieb:
> kommt auf die Hardware an. Aber Lookup Table wird wohl oft das
> schnellste sein.
Ist jetzt aber nicht dein Ernst für:

Sven schrieb:
> wenn ein 8 Bit Wert auf einen Wert mit 6
> Stufen umgerechnet werden soll.

von Peter II (Gast)


Lesenswert?

Der Andere schrieb:
> Einfach die unteren 2 Bits ausblenden.

dann hat man 6 bits aber nicht 6 Stufen.

von Jörg (Gast)


Lesenswert?

Wenn ich es richtig verstehe, willst Du 256 Werte auf 7 Werte (alle 
aus.. alle 6 an) falten?

Kommt sehr drauf an, wie linear die Umsetzung das ist Einer LUT ist das 
egal, kostet aber auch viel Platz (256 Byte).

von Sven (Gast)


Lesenswert?

Also wenn ich nur 2 Bits abschneide, habe ich einen 6 Bit Wert.

Ich brauch aber einen Wert der nur von 1-6 geht.

Ist der Zielwert 1= Portpin 1 ein
Ist der Zielwert 2= Portpin 1 und 2 ein
Ist der Zielwert 3= Portpin 1,2,3 ein

usw.

Es soll wie ein VU Meter arbeiten und eine Eingangsspannung als 
Balkenanzeige ausgeben.

Ich könnte dafür einfach rechnen, den Eingangswert durch 42,7 teilen und 
runden oder teilen, 0,5 addieren und Nachkommazahl abschneiden.

Oder ich mach halt einfach eine Lookup Table. Also einfach die oberen 4 
bit nehmen und eine Lookup Table mit 16 Werten und der gewünschen 
Zuordnung im System 1 bis 6.
Es geht zwar nicht ganz auf, aber da kann ich mit der Aufteilung spielen 
und z.B. bis ca 25% nur eine LED anzeigen und im oberen Bereich feiner 
unterteilen.

von Sven (Gast)


Lesenswert?

Jörg schrieb:
> Wenn ich es richtig verstehe, willst Du 256 Werte auf 7 Werte (alle
> aus.. alle 6 an) falten?
>
> Kommt sehr drauf an, wie linear die Umsetzung das ist Einer LUT ist das
> egal, kostet aber auch viel Platz (256 Byte).

genau.
Wobei 0 heißt alle LED aus.
Sobald irgendwas ankommt (Also auch schon bei dem Bytewert 1) soll schon 
eine leuchten damit man sieht, dass die Anlage an ist.

von Thomas E. (picalic)


Lesenswert?

Sven schrieb:
> -Teilen und runden?
> -Teilen, Addieren und Abschneiden

Wenn's auf einem AVR läuft, ist Teilen ganz schlecht, aber 
multiplizieren geht: 8x8 Multiplikation mit einem geeigneten Faktor, 
dann das höherwertige Byte verwenden.

von Michael K. (Gast)


Lesenswert?

Sven schrieb:
> Ich brauch aber einen Wert der nur von 1-6 geht.
Okay, zu flüchtig gelesen.

> Oder ich mach halt einfach eine Lookup Table. Also einfach die oberen 4
> bit nehmen und eine Lookup Table mit 16 Werten und der gewünschen
> Zuordnung im System 1 bis 6.

Warum dann nicht die oberen 3bits ?
5 mal shiften und den Rest per Lookup oder switch case.

von Jörg (Gast)


Lesenswert?

Genau. Dafür sind LUTs ideal. Und wenn Du vom 8-Bit Wert eh' nur die 
oberen 4-Bit brauchst, sind das meist nur zwei Operationen: Nibble 
tauschen und AND mit 0x0F. Dann 16 Byte LUT und gut ist...

von Peter II (Gast)


Lesenswert?

wobei man sich Fragen muss, warum ein paar LEDs so schnell angesteuert 
werden müssen. Jeder weg sollte schnell genug dafür sein.

von Jörg (Gast)


Lesenswert?

Bin mal gespannt, wie lange es dauert nis einer schreibt: Mit 'nem 
LM3914/15 geht das aber auch... ;-)

von Peter D. (peda)


Lesenswert?

Binäre Suche (max 3 Vergleiche).

von Sascha (Gast)


Lesenswert?

Solange du keine Divisionen machst die keine Zweierpotenz als Divisor 
haben ist das alles relativ Wumpe.

LUT ist zügig, bei 6 Stufen kannst du einfach von unten nach oben per 
Schleife durchgehen und für jeden Tabellenwert der kleiner als der 
Eingangswert ist, den LED Portpin auf 1 setzen.
Wenn es noch zügiger sein soll, macht man das gleiche wie bei SAR ADCs, 
man fängt in der Mitte an und halbiert seine Schritte immer weiter. Aber 
die maximale Zeitersparnis ist bei 6 Stufen minimal.

Alternativ kann man da auch die etwas unflexiblere Bitshift/Mathematik 
trickery anwenden:
1
uint8_t input = 127;
2
uint8_t output = 0x00;
3
for (int i = 0; i <=6; i++)
4
{
5
   if(input > (42*i))
6
      {
7
       output |= (1 << i);
8
      }
9
    else {break;}
10
}

von Der Andere (Gast)


Lesenswert?

Peter II schrieb:
> Der Andere schrieb:
>> Einfach die unteren 2 Bits ausblenden.
>
> dann hat man 6 bits aber nicht 6 Stufen.

Uups,
sorry, Asche auf mein Haupt. Ihr habt natürlich recht und ich hab Mist 
interpretiert.

von Sascha (Gast)


Lesenswert?

Der Andere schrieb:
> Peter II schrieb:
>> Der Andere schrieb:
>>> Einfach die unteren 2 Bits ausblenden.
>>
>> dann hat man 6 bits aber nicht 6 Stufen.
>
> Uups,
> sorry, Asche auf mein Haupt. Ihr habt natürlich recht und ich hab Mist
> interpretiert.

Zu deiner Verteidigung: Die Frage ist etwas blöd formuliert, daher war 
ein Bitshift um 5 Bits meine erste Antwort. Dann hab ich den Teil mit 
dem VU Meter nochmal gelesen und den eigentlichen Zweck der Übung 
verstanden.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sven schrieb:
> wenn ein 8 Bit Wert auf einen Wert mit 6 Stufen umgerechnet werden soll.
Mit welcher Skalierung? Linear? Logarithmisch?

von Peter D. (peda)


Lesenswert?

Im einfachsten Fall nimmt man switch mit Bereichen (der AVR-GCC kann 
das), dann macht der Compiler die binäre Suche für Dich.
Z.B. für logarithmische Bereiche:
1
ausgabe( uint8_t val ){
2
{
3
  switch( val ){
4
    case 128 ... 255: display6(); break;
5
    case 64 ... 127:  display5(); break;
6
    case 32 ... 63:   display4(); break;
7
    case 16 ... 31:   display3(); break;
8
    case 8 ... 15:    display2(); break;
9
    case 4 ... 7:     display1(); break;
10
    default:          display0(); break;
11
  }
12
}

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ich würde den 8-Bit-Wert einfach mit 6 multiplizieren und vom Ergebnis
die obersten 8 Bit nehmen. In C:
1
  y = 6*x >> 8; // y in [0..5]

von Stefan K. (stefan64)


Lesenswert?

Peter II schrieb:
> wobei man sich Fragen muss, warum ein paar LEDs so schnell angesteuert
> werden müssen. Jeder weg sollte schnell genug dafür sein.

Das sehe ich auch so. LUT ist der schnellste Weg, aber wozu den Aufwand, 
wenn die Funktion alle x ms einmal aufgerufen wird?

Ich bin ja normalerweise kein Freund von langen if..else Ketten, aber in 
diesem Fall bist Du so am flexibelsten, weil Du die Schwellwerte direkt 
einstellen kannst.
1
#define SCHWELLWERT_LED6 180
2
#define SCHWELLWERT_LED5 96
3
#define SCHWELLWERT_LED4 44
4
#define SCHWELLWERT_LED3 23
5
#define SCHWELLWERT_LED2 10
6
#define SCHWELLWERT_LED1 2
7
8
// todo: define Portbits LED1 .. LED6
9
10
uint8_t ledMask;
11
12
...
13
14
ledMask = 0;
15
16
if (input > SCHWELLWERT_LED6)
17
{
18
  ledMask = LED1 | LED2 | LED3 | LED4 | LED5 | LED6;
19
}
20
else
21
if (input > SCHWELLWERT_LED5)
22
{
23
  ledMask = LED1 | LED2 | LED3 | LED4 | LED5;
24
}
25
else
26
if (input > SCHWELLWERT_LED4)
27
{
28
  ledMask = LED1 | LED2 | LED3 | LED4;
29
}
30
else
31
if (input > SCHWELLWERT_LED3)
32
{
33
  ledMask = LED1 | LED2 | LED3;
34
}
35
else
36
if (input > SCHWELLWERT_LED2)
37
{
38
  ledMask = LED1 | LED2;
39
}
40
else
41
if (input > SCHWELLWERT_LED1)
42
{
43
  ledMask = LED1;
44
}
45
// todo: gib ledMask auf Port aus

Gruß, Stefan

von Stefan K. (stefan64)


Lesenswert?

Peter D. schrieb:
> case 128 ... 255: display6(); break;

Interessant, dass das geht. Peters Code sieht hübscher aus. Ist aber 
(noch) kein Standard, oder?

Gruß, Stefan

von Yalu X. (yalu) (Moderator)


Lesenswert?

Stefan K. schrieb:
> Peter D. schrieb:
>> case 128 ... 255: display6(); break;
>
> Interessant, dass das geht. Peters Code sieht hübscher aus. Ist aber
> (noch) kein Standard, oder?

Nein, das ist eine C-Erweiterung in GCC.

von radiostar (Gast)


Lesenswert?

Stefan K. schrieb:
> Interessant, dass das geht. Peters Code sieht hübscher aus.

Das wird auch mit if/else hübsch.
1
ausgabe( uint8_t val ){
2
{
3
  if (val > 128) display6();
4
  else if (val > 64) display5();
5
  else if (val > 32) display4();
6
  else if (val > 16) display3();
7
  else if (val > 8) display2();
8
  else if (val > 4) display1();
9
  else display0();
10
}

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.