Forum: Mikrocontroller und Digitale Elektronik c code vereinfachen


von sepp (Gast)


Lesenswert?

Hallo,

Ich versuch grad einen feuchtigkeitssensor zu programmieren der eine 
impedanz hat. Ich hab grad eine anweisung geschrieben aber die ist 
leider zu groß, also code size limit überschritten.

Weis jemand wie man das vereinfachen kann:???

    if (erg_luft <= 0x84)             //     80   6,85k
    {     h=80;
    }
    else if (erg_luft <= 0x106)     // 77,5
    {     h=77.5;
    }
    else if (erg_luft <= 0x128)     // 75  10,5k
    {     h=75;
    }
    else if (erg_luft <= 0x168)     // 72,5
    {     h=72.5;
    }
    else if (erg_luft <= 0x207)     // 70  17k
    {      h=70;
    }
    else if (erg_luft <= 0x256)     // 67,5
    {      h=67.5;
    }
    else if (erg_luft <= 0x305)    // 65    25k
    {     h=65;
    }


Vielen Dank

mfg

Sepp

von Eddy C. (chrisi)


Lesenswert?

Also eine Tabelle abklappern wird sich nicht rentieren.

Du könntest statt floats uint8_t zuweisen, die den doppelten Wert 
aufweisen: Offensichtlich ist die Genauigkeit, die h aufweist, nicht
größer wie 0.5%. Somit weist Du erst mal einem uint8_t den Wert 135 
(=67.5*2) zu. Hinterher kommt die Hälfte in den float.

Und das evtl. mit ner Tabelle kombinieren.

von R. F. (rfr)


Lesenswert?

Was heisst" code size limit überschritten."  genau?

Würde eine case-Anweisung helfen?

Gruss

Robert

von Eddy C. (chrisi)


Lesenswert?

Im Prinzip so:

inline float Doit(uint16_t erg_luft)
{
    const uint16_t Tab[] = { 0x84,0x106,0x128,0x168,0x207,0 };
    uint8_t Result = 160;
    uint16_t *p;
    for (p=Tab; *p; p++,Result -= 5)
        if (erg_luft <= *p)
            return ((float)Result)*0.5;
    return 0.0;
}

von sepp (Gast)


Lesenswert?

mit case hab ichs schon versucht das funtk aber nur mit constanten 
faktoren im case und das bringt mir nichts

@eddy

also die tabelle sieht sehr intressant aus, da ich aber c nicht so 
vertieft gelernt hab hört sich da ein wenig kompliziert an?

was macht der befehl uint8_t Result = 160; ?
wieso gibts uint16_t und uint8:t?

vielen dank

mfg

von sepp (Gast)


Lesenswert?

if (erg_luft <= 0x84)             //     80   6,85k
    {     h=80;
    }

durch den bereich bekomm ich im h die prozent der luftfeuchtigkeit
also h=80, das kann ich dan ausgeben

aber in der tabelle wo würd das dann stehen?
also jetzt ist wenns kleiner <=84h ist, dann steht im h=80;

mfg

von Lehrmann M. (ubimbo)


Lesenswert?

nur so eine Frage: worauf programmierst du, dass du derart wenig 
Speicher hast ... oder überschreitet das Gesamtprojekt den vorhanden 
Speicher ...

von Oliver (Gast)


Lesenswert?

>h=77.5;

Die paar if's sind bestimmt nicht das Problem, die brauchen doch nur ein 
paar Byte Programmspeicher. Aber wenn du im weiteren mit den float-Werte 
rechnest, kommen da ganz schnell ein paar kB für die floating point libs 
hinzu.

Lass die floats ganz weg, und nimm dafür geeignet skalierte Integer. 
Oder FixPoint-Arithemtik. Dann klappt es auch auf einem Tiny.

Oliver

von Eddy C. (chrisi)


Lesenswert?

Aaaalso:

Die Anweisung

uint8_t Result = 160;

setzt ein einzelnes Byte auf den Wert 160, welcher später als 80.0 
zurück gegeben wird. Mit jedem Schleifendurchlauf wird der Wert um 5 
reduziert, was 2.5% Luftfeuchtigkeit entspricht. Somit braucht man die 
Werte für die Luftfeuchtigkeit gar nicht erst mit in die Tabelle packen. 
Ist es richtig, dass die Tabelle eigentlich noch viel länger ist? Dann 
rentiert sich der Aufwand umso eher.

von Falk B. (falk)


Lesenswert?


von Eddy C. (chrisi)


Lesenswert?

Achso:

uint8_t ist auf den allerallermeisten CPUs nix anderes wie ein unsigned 
char. Damit ist halt besser ausgedrückt, was konkret benötigt wird.

Mit uint16_t sagt der Programmier dem C-Compiler, dass er definitiv 
einen unsigned int mit 16 Bit haben möchte. Das läuft meistens auf einen 
unsigned short int hinaus.

von B e r n d W. (smiley46)


Angehängte Dateien:

Lesenswert?

Hallo  sepp

Bist Du Dir sicher, daß in den Bedingungen das 0x stehen muß? Die grüne 
Kurve besteht aus Dezimalzahlen und die blaue aus Hexwerten. Die 
Dezimale macht irgendwie mehr Sinn.

Ich mach mal mit diesen Werten weiter.
84, 106, 128, 168, 207, 256, 305

Wie es scheint, ist jeder zweite Wert linear interpoliert. Man könnte 
über eine Funktion direkt das richtige Ergebnis erhalten, ohne Tabelle. 
Dann hätte das Ergebnis 1% Auflösung (rel.Hum).

Als Polynom 2.er Ordnung, (Fehler 0,5%):
h = ((long)160*x*x/1000 - (long)1286*x/10 + 89380) / 1000;

Als Gerade (Fehler 1,3%):
h = (long)-63*x/1000 + 84

Mfg. Bernd

von rechnen (Gast)


Lesenswert?

Oft ist es gut, die werte mal zu zeichnen.

Der zusammenhang scheint linear zu sein, daher ist die
berechnung einfach:

h = -0.024 * erg_luft + 82,6

Diese Berechnung mit Festkomma oder (besser) longint
optimieren und fertig.

von B e r n d W. (smiley46)


Lesenswert?

Die Gerade kann man noch weiter vereinfachen:

Aus
h = (long)-64*erg_luft/1024 + 84
wird
h = 84 - (erg_luft>>4);

Vier mal nach rechts schieben entspricht einer Division durch 16, 
genauso wie 64/1024.

Gruß, Bernd

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.