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
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.
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]; |
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.
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?
Ergänzung: Alle Schaltschwellen die ich eingegeben habe sollen vom Compiler schon bevor das Programm erstellt wird z.B. mit 1,04 multipliziert und dann auf ganze Zahlen gerundet werden.
Philipp schrieb: > 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. sind dann alle werte durch 4 Teilbar? wenn ja dann passt es schon mal gute in ein byte rein. Das spart dann platz im speicher.
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); |
Wenn der letzte Eintrag im Array 1023 = "uint10_max" enthält kann man sich die if-Abfrage sparen.
Philipp schrieb: > Wie genau funktioniert das denn? Das kommt drauf an, was du genau vor hast. z.B. a = (b * c - d) * 2^-d Wobei 2^-d eine Shift-Operation um d Stellen ist.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.