mikrocontroller.net

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


Autor: Jens K. (jens_)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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ß

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Jens K. (jens_)
Datum:

Bewertung
0 lesenswert
nicht 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!?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann wirst du halt noch wo einen Fehler haben :-)

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

Autor: Jens K. (jens_)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>noch die /0 am Ende,

Kleiner Hinweis: Es ist eine "\0".

Autor: Jens K. (jens_)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Oliver (Gast)
Datum:

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

Willkommen im Club :-)

Oliver

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.