Was ist schneller: Runden, Addieren und Abschneiden oder Lookup Table

Gast #4512073
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)
Gast #4512086
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.
Gast #4512096
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).
Gast #4512108
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.
Gast #4512115
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.
Gast #4512121
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.
Gast #4512155
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
}
Gast #4512171
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.
#4512198
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
}
#4512209
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
Gast #4512303
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren