Forum: Compiler & IDEs "simples" Rechenproblem... Atemga 32


von Jens K. (jens_)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich programmiere gerade einen Atmega 32 und irgendwie will mein Programm 
nicht so richtig das tun was ich will. Hier mal mein Code:


Erklärung: verz() ist lediglich eine while Schleife für delay und die 
if- Schleife ruft ein Menü auf, das in einer anderen Funktion deklariert 
wird (hier lässt sich auch die Variable moment ändern).
moment ist eine globale Variable, die zu Beginn des Programms zum testen 
auf 50 gsetzt wird.

Berechnet wird eine "simple" Geradengleichung:

drehmoment = moment/512*adcergebnis-moment;

adcergebnis ist die Auswertung des Analogports( liegt zwischen 0 und 
1024), typ int
moment ist ein faktor der zwischen 1 und 5000 liegen kann, typ int
drehmoment stellt das Ergebnis dar -> long, da in der rechnung 
kurzzeitig mehr speicher benötigt werden könnt als von einer normalen 
int

drehmoment wird anschließend noch in einen string verwandelt, um dieses 
auf dem Display ausgeben zu können.

Leider funktioniert das ganze nicht - und ich finde meinen Denkfehler 
nicht!
Bei Werten für das Moment bis ca. 10 funktioniert es noch wie es soll - 
darüber nicht mehr, bzw ab Werten ca. 100 stürzt das Display ab und dann 
irgendwann auch der Atmega!?

Was mach ich falsch..
Herzlichen Dank!
Gruß

von Karl H. (kbuchegg)


Lesenswert?

> drehmoment stellt das Ergebnis dar -> long, da in der rechnung
> kurzzeitig mehr speicher benötigt werden könnt als von einer normalen
> int

Das interessiert den Compiler aber beim Bearbeiten
der Berechnung herzlich wenig, wenn deine Ergebnisvariable
vom Typ long ist. Der Compiler richtet sich nach den
Datentypen der an der Operation beteiligten Operanden.
Und da die alle int sind, wird auch die Berechnung in
int gemacht. Erst das komplette Endergebnis wird dann
nach long umgewandelt weil es ja einem long zugewiesen
werden soll.

Wenn du den Compiler dazu zwingen willst, die Berechnung
im Zahlenraum für long durchzuführen, dann muss eine
an der Operation beteiligte Komponente vom Typ long
sein.

  drehmoment = ((long)adcergebnis * moment) / 512;

Jetzt wird die ganze Berechnung in long durchgeführt.

von johnny.m (Gast)


Lesenswert?

Also ein paar Kleinigkeiten fallen mir an dem Code beim Drübersehen 
schon mal auf:
1. Benutze keine Bezeichner, die mit einem Underscore ("_") beginnen. 
Die sind für den Compiler reserviert.

2. Nimm für die Mittelwertbildung vom ADC-Ergebnis besser eine 
Zweierpotenz für die Anzahl der Werte. Da fällt dem Prozessor die 
Division leichter. Division durch 10 ist erheblich komplizierter als 
Division durch 8 oder 16.

3.
> ADMUX != (1 << REFS0)|( 1 << REFS1);
Das kann so nicht gehen. Befasse Dich mal mit der Bedeutung des 
logischen Negierungs-Operators "!". Sonst hast Du immer 0 in ADMUX 
stehen.

tbc...

von Jens K. (jens_)


Lesenswert?

AH - schon mal danke für die Tipps! -> Wurde gerad abgeändert.

@ johnny m. 3. -> da hab ich wohl nen schreibfehler gemacht: das ! solte 
ein | sein :)

Nachdem ich mal eure Tipps beachtet habe, geht der ganze vorgang bei 50 
z.b. wunderbar wie gewollt.
Nur wenn ich den wert im Programmablauf ändere (> 10) und dann wieder 
aus meinem Menü rausgehe - also zurück in die Berechnung - stürzt 
erimmer noch ab!?

von Karl H. (kbuchegg)


Lesenswert?

Dann wirst du halt noch wo einen Fehler haben :-)

Heisse Kandidaten sind, wie immer, Array Überläufe.

von Jens K. (jens_)


Angehängte Dateien:

Lesenswert?

Hi!

Ich hab jetzt mal die Funktion für das entsprechende Untermenü 
angehängt.

Ich habe davor einfach auch das Menü getestet und da hat er mir immer 
die richtigen Werte "gespeichert".

Das Untermenü setzt sich so zusammen, dass man in der sog. reihe 3 werte 
und beim Faktor 4 Werte auswählen kann.

Das Produkt aus beidem ist dann die globale Variable moment.

Wäre super wenn mal jemand kurz drüberschauen könnte, ob er nen Fehler 
entdeckt.
(ich hoffe es ist halbwegs verständlich geschrieben - ich bin aber auch 
dankbar für Hinweise für efektiveres programmieren!)

Danke schon mal :)

von Oliver (Gast)


Lesenswert?

Auf den ersten Blick fällt nur auf, daß deine arrays, in die du mit itoa 
schreibst, aller sehr klein sind. itoa kann aus einem int nunmal mit 
-32768 max. 6 Zeichen erzeugen, dazu kommt dann noch die /0 am Ende, 
ergibt 7. Du musst dir also schon sehr sicher sein, wenn du deine arrays 
kleiner als 7 dimensionierst.

Eine Frage am Rande: Wo kann man eigentlich die prellfreien Taster 
kaufen?

Oliver

von Rahul, der Trollige (Gast)


Lesenswert?

>noch die /0 am Ende,

Kleiner Hinweis: Es ist eine "\0".

von Jens K. (jens_)


Lesenswert?

Hi!

also in itoa werden ja nur die jeweiligen werte der anderen arrays 
geschrieben -> daher ist das längste array dann 5 zeichen lang..
Wegen den tastern: dadurch dass ich immer ne gewisse wartezeit nach 
einem tasterdruck einhalte, habe ich dadurch bisher keine Probleme! 
Funktioniert sogar sehr gut wie ich finde..
Und es gibt auch schon entprellte Taster zu kaufen ( die die ich im 
moment verwende haben keine solche Entprellung)..
Naja - ich probier ma nch weiter oder widme mich erst mal der nächsten 
Aufgabe... :)
MFG und Danke



P.S. Danke - ihr hattet Recht - habs grad gesehen: hab leider 1 Array 
genau 1  zu kurz gemacht -> wie peinlich:)


Danke für eure Hilfe...

von Oliver (Gast)


Lesenswert?

"Danke - ihr hattet Recht - habs grad gesehen: hab leider 1 Array
genau 1  zu kurz gemacht -> wie peinlich:)"

Willkommen im Club :-)

Oliver

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.