Lookup-Tabelle für Anfänger

Gast #2607159
Lesenswert?

Hi Leute,

ich bin ein ziemlich unerfahrener Mikrocontroller-Programmierer und mein 
C-Programm soll ungefär folgendes machen:

- Der ADC liest eine Spannung ein
- Je nach ADC-Wertebereich sollen beliebige Ausgänge geschaltet werden

Es gibt insgesamt 2 verschiedene Tabellen mit je 30 Intervallen (z.B 
if(200<ADC<225) {schalte port bla bla})


Das Ganze habe ich jetzt erstmal mit 60 if-else Verzweigungen 
programmiert, was mir allerdings ziemlich primitiv erscheint, da im 
schlimmsten Fall 29 Abfragen umsonst durchlaufen werden müssen. Wie 
liese sich sowas denn eleganter lösen? (ich habe was von Lookup Tabelle 
gelesen?)


Gibt es ausserdem eine Möglichkeit im Compiler (AVR Studio 4.19) noch 
einen "Korrekturfaktor" auf meine Schaltschwellen (oder auf den 
ADC-Wert) draufzurechnen ohne, dass am Ende eine eklige Kommazahl 
herauskommt?


Besten Dank!

Gruß,
Philipp
Gast #2607166
Lesenswert?

Philipp schrieb:
> Wie liese sich sowas denn eleganter lösen?

Das kommt drauf an, wie deine Schaltschwellen liegen.

Philipp schrieb:
> Gibt es ausserdem eine Möglichkeit im Compiler (AVR Studio 4.19) noch
> einen "Korrekturfaktor" auf meine Schaltschwellen (oder auf den
> ADC-Wert) draufzurechnen ohne, dass am Ende eine eklige Kommazahl
> herauskommt?

Rechne mit Ganzzahl, dann kann das nicht passieren.
Gast #2607170
Lesenswert?

Wie groß ist der Wertebereich Deiner Messung? Und sind das nur integer?

Wenn Du z.B. einen Wertebereich von 0-255 hast könntest Du ein Array 
anlegen in der für jeden Wert drinsteht was auf den Port ausgegeben 
werden soll...


Also z.B.:

0-9 => Port Pin 1 aktiv
10-19 => Port Pin 2 aktiv
20-255 => Port Pin 3 aktiv


Dann belegst Du Dein Array so vor:
1
 
2
uint8_t schaltzustand[255] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0-9 */
3
                               2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  /* 10-19 */
4
                               4, 4, 4, 4, 4, ..... bis zum Ende }; /*20-255 */

Auswerten tust Du dann mit

in uint8_t adc_value steht Dein auswerteergebniss:
1
  PORT<blafasel> = schaltzustand[adc_value];
Gast #2607177
Lesenswert?

Mal unterstellt deine Schaltschwellen sind linear aufsteigend dann 
dividiere deinen ADC Wert durch 10 und du erhältst 102 Schaltpunkte.

Beispiel Pseudocode
1
const u8 PortCombination [8] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
2

3
Port = PortCombination [(getAdcValue () / 128];

Ergibt 8 verschiedene Zustände in Abhängigkeit deines AD Wertes.
Gast #2607197
Lesenswert?

Wolfgang schrieb:
> Das kommt drauf an, wie deine Schaltschwellen liegen.
Uli schrieb:
> Wie groß ist der Wertebereich Deiner Messung? Und sind das nur integer?
Bernd N. schrieb:
> Mal unterstellt deine Schaltschwellen sind linear aufsteigend...

Die Tabelle fängt bei etwa ADC=200 an und geht bis etwa ADC=800. Das 
sind direkt die integer Werte die aus dem ADC kommen. Die 
Schaltschwellen sind aber NICHT linear aufsteigend sondern müssen 
beliebig festgelegt werden können.

Am schönsten wäre es natürlich, wenn man die Schaltschwellen direkt als 
Zahl eingeben könnte.


Wolfgang schrieb:
> Rechne mit Ganzzahl, dann kann das nicht passieren.

Wie genau funktioniert das denn?
Gast #2607214
Lesenswert?

Ist nur schnell hingeschmiert. Wenn die Tabelle länger ist kann man sie 
in den Flash verbannen.
1
typedef struct
2
{
3
  uint16_t max;
4
  uint8_t pin;
5
} schwelle_t;
6

7
#define NB_SCHWELLEN 5
8

9
...
10

11
schwelle_t schwellen[NB_SCHWELLEN]= { { 100, 1},
12
                                      { 250, 4},
13
                                      { 500, 5},
14
                                      { 500, 2},
15
                                      {1023, 6} };
16

17
uint8_t i=0;
18
for(i=0;i<NB_SCHWELLEN && !(schwellen[i].max>=ADC);i++);
19
if(schwellen[i].max>=ADC)
20
  PORTB|=(1<<schwellen[i].pin);
Gast #2607242
Lesenswert?

abc123 schrieb:
> Ist nur schnell hingeschmiert. Wenn die Tabelle länger ist kann man sie
> in den Flash verbannen.

Vielen Dank! Das gefällt mir jetzt schon recht gut. Da wär ich nie drauf 
gekommen.

abc123 schrieb:
> Wenn der letzte Eintrag im Array 1023 = "uint10_max" enthält kann man
> sich die if-Abfrage sparen.

Wegen der Abbruchbedingung der for-Schleife oder?

Wolfgang schrieb:
> Das kommt drauf an, was du genau vor hast.

Wenn ich jetzt z.B. die uint16_t max Werte in dem Array aus dem Beispiel 
von "abc123" alle mit einem Korrekturfaktor multiplizieren möchte. Aber 
ohne, dass der Compiler mir dann Kommawerte daraus macht und in den 
Atmega programmiert. Quasi so als würde ich die Werte alle manuell mit 
dem Korrekturfaktor multiplizieren und dann den gerundeten Wert in das 
Array reinschreiben.


Gruß,
Philipp

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