Forum: Mikrocontroller und Digitale Elektronik Berechnugsproblem


von Maximilian S. (maxsarges)


Angehängte Dateien:

Lesenswert?

Hallo liebe Gemeinde,

Ich bin an einem Punkt angekommen wo ich einfach nicht mehr weiter weis 
(wahrscheinlich ist es ein ganz dummer fehler den ich einfach übersehe).

Kurz zur Hardwar:

STK500 Mit Atmega 16 und 16MHZ Quarz
LM335 an PORTA.1 (Anschluss überprüft und gemessen, stimmt alles)
Poti an PORTA.0

ADC Einstellungen:
128 Prescaler = 125KHz
AVCC als Ref

Ansonsten nutz ich den ADC Code aus dem Tutorial.

Ich versuche nun seit ein paar Tagen die gemessene Temperatur an meinen 
PC zu senden, aber es kommen immer die falschen Werte.

Habe schon einiges ausprobiert aber es will einfach nicht.

Der Poti soll zu testzwecken nur eine LED Dimmen was auch einwandfrei 
funktioniert, desweiteren hab ich noch ein wenig mit Interrupts 
experementiert was auch einwandfrei klappt, nur der Richtige Temp Wert 
will nicht.

Was auch extrem komisch ist, wenn ich simuliere werden die variablen 
nicht initialisiert (Wenn ich simuliere setze ich die Werte auf z.B 610 
o.ä) und der Simulator springt kurz in die if Abfrage und arbeitet da 
drei Zeilen ab obwohl er das nicht soll.

Achso nutze AVR Studio 5

Anbei der Code.

Hoffe einer hat ne Idee warum ich immer die Falschen werte bekomme.

Danke!

von Karl H. (kbuchegg)


Lesenswert?

> acttemp = (ADC_Read_Avg(1,4)*1000);

ADC_Read_Avg liefert zb einen Wert von 600.
Mal 1000 macht dann 600000. UNd das ist zu viel. Bei 65535 ist Schluss.

Das du das Ergebnis danach an einen long zuweist, ist uninteressant. Die 
Berechnung wird in int gemacht, weil

* ADC_Read_Avg einen int (unsigned) liefert    und
* 1000  ebenfalls ein int ist

Damit stehen die beiden Teilnehmer an der Multiplikation fest, beide 
sind int  (bzw. unsigned int), daher wird eine 16 Bit int Multiplikation 
gemacht.

Wenn du eine long Multiplikation erzwingen willst (weil du sie brauchst, 
damit das Ergebnis noch darstellbar ist), dann musst du einen der 
Teilnehmer als long ausführen. Die 1000 würden sich anbieten
1
  acttemp = (ADC_Read_Avg(1,4)*1000L);


> (wahrscheinlich ist es ein ganz dummer fehler den ich einfach übersehe).

In Berechnungen müssen alle Zwischenwerte im gültigen Wertebereich 
liegen. Auch der Wert der rechten Seite einer Zuweisung ist erst mal nur 
ein Zwischenwert, der dann an das Ziel zugewiesen wird.

von Karl H. (kbuchegg)


Lesenswert?

>
>  long tempout = 0;
> ...
>      itoa(tempout,Buffer,10);


No.
Wie das "i" in "itoa" schon sagt, ist die Funktion itoa für int 
zuständig. Du hast keinen int, du hast einen long! Die dafür zuständige 
Funktion heißt ltoa, mit einem "l" am Anfang,wie "long"

(und für unsigned int würde die Funktion utoa heissen. "u" wie "unsigned 
int")

von Karl H. (kbuchegg)


Lesenswert?

>      itoa(tempout,Buffer,10);
>      for (int a=0;a<3;a++)            // Wert auf UART ausgeben
>      {
>        uart_putchar(Buffer[a]);
>        if (a == 1)
>        {
>          uart_putchar(44);          // Leerzeichen ausgeben
>        }
>      }

Woher weißt du, dass dein Ergebnisstring 3 Zeichen umfasst? Was ist mit 
negativen Temperaturen? Was ist mit einstelligen Temperaturen?

Das ist ein bischen sehr brutal, was du da machst.

von Maximilian S. (maxsarges)


Lesenswert?

Ohh mein Gott,

vielen lieben Dank, natürlich geht es jetzt ^^. So ein dummer Fehler 
-_-.

Nach derartigen Fehlern hab ich auch schon gesucht, deshalb hab ich auch 
zu Testzwecken mal alle Variablen als Long deklariert.

Danke nochmal!

von Maximilian S. (maxsarges)


Lesenswert?

Hi, ja das mit negativen Tempereraturen und die ganzen anderen Fälle 
werd ich die Tage mal machen, erstmal wollt ich nur sehen ob das 
überhaupt klappt was ich mir ja so zusammengeschrieben habe ^^.

Gruß Max

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.