Wieder mal Zeit für eine Anfängerfrage :)
Kann es passieren, das wenn der SRAM voll ist (Arbeitsspeicher) meine
Variabeln durcheinanderkommen, das zum Beispiel zwei variabeln ihre
werte vertauschen und einer der beiden sogar einen dementsprechenden, zu
kleinen Wert bekommt ? So passiert nämlich bei mir. Es kann auch ein
echt peinlicher programmierfehler sein, aber ich habe soetwas
merkwürdiges bisher noch nicht gehabt
Ich habe einen ATmega644P , und die Compilermeldung am Schluss sagt mir
das der Speicher ca. 23% voll ist. Aber das wird wahrscheinlich der
Programmflash sein.
ich arbeite fast ausschliesslich mir float Werten, was aber auch sein
muss.
Ich habe schon versucht Globale variablen und statics so gut es geht zu
vermeiden.
Habe ich eine möglichkeit meinen Arbeitspeicherbedarf abzuschätzen ?
Welche effekte treten bei Speichervermischung auf, denke die lassen sich
sehr schlecht vorhersagen, wenn überhaupt.
Wieder einmal danke fürs lesen ;)
gruss Maggus
> fast ausschliesslich mir float Werten, was aber auch sein muss.
Na gut. Wat mut, dat mut.
Dir ist schon klar, dass du mit float eine wesentlich geringere
Genauigkeit hast, als mit 32-Bit longs? Nur der Dynamikbereich ist
größer.
Ich vermute, dass dein Stack in deine Variablen hineinwächst?
Man kann nur raten, daher:
Vermutung 1: Stack (der von zuoberst im Speicher wächst) wird so gross,
dass er mit dem Heap (der von unten im Speicher wächst) kollidiert.
Vermutung 2: Pointer auf lokale Variable, der nach dem Verlassen der
betreffenden Funktion weiterverwendet wird.
> Ich habe schon versucht Globale variablen und statics so gut es geht zu> vermeiden.
Das ist nicht unbedingt besser: Bei globalen Variabeln und statics
kannst du den Speicherbedarf genau abschätzen. Um den Speicherbedarf
lokaler Variabeln zu bestimmen, muss man hingegen die genaue
Funktionsaufrufreihenfolge kennen. In ungünstigen Fällen kann sich das
extrem aufblasen.
>Welche effekte treten bei Speichervermischung auf, denke die lassen sich>sehr schlecht vorhersagen, wenn überhaupt.
Die Effekte sind einfach: Absturz des Programs.
>Ich habe einen ATmega644P , und die Compilermeldung am Schluss sagt mir>das der Speicher ca. 23% voll ist. Aber das wird wahrscheinlich der>Programmflash sein.
avr-size (falls du WInAVR nutzt) gibt am Ende mehrere Werte aus. Der,
bei dem steht: ".tetxt + .data + .bss" ist der für das SRAM. Was wird
denn da angezeigt?
Oliver
Bei dem Verhalten ist ein Stacküberlauf oder fehlerhafte
Pointerbehandlung sehr wahrscheinlich.
Warum muss Float sein?
Es gibt KEINEN Grund auf einem Integer µC mit floating points zu
rechnen.
Der µC kann kein Floating point, also wird in einer Library ( vom
Compiler geliefert ) die Berechnung in eine Integerberechnung
umgewandelt.
Nachteil: Du hast keinen EInfluß darauf wie das geschieht.
Du hast zwar Floating Point im C-Code aber es wird NICHT mit Floating
Point gerechnet !!!!!!
Besser du nutzt Intergerarithmetik. Es gibt dazu genug links, auch hier
im Forum.
Vorteil: Du hast selbst in der Hand mit welcher Auflösung,Genauigkeit
und Resourcenbedarf der µC rechnet.
>Du hast zwar Floating Point im C-Code aber es wird NICHT mit Floating>Point gerechnet !!!!!!
???
Der µC kann auch keine 32-bit-Integerberechnungen. Muß man deshalb jetzt
alles in 8 bit rechnen?
>Es gibt KEINEN Grund auf einem Integer µC mit floating points zu>rechnen.
Selbstverständlich gibt es dafür Gründe. Ob die hier gegeben sind, ist
eine andere Frage.
Oliver
>Du hast zwar Floating Point im C-Code aber es wird NICHT mit Floating>Point gerechnet !!!!!!>???>Der µC kann auch keine 32-bit-Integerberechnungen. Muß man deshalb jetzt>alles in 8 bit rechnen?
Unsinn, das ist einfaches Schieben mit Übertrag, kann jeder µC
>Es gibt KEINEN Grund auf einem Integer µC mit floating points zu>rechnen.>Selbstverständlich gibt es dafür Gründe. Ob die hier gegeben sind, ist>eine andere Frage.
Welche ?
Ralph wrote:
>>Es gibt KEINEN Grund auf einem Integer µC mit floating points zu>>rechnen.>>>Selbstverständlich gibt es dafür Gründe. Ob die hier gegeben sind, ist>>eine andere Frage.>> Welche ?
"Floating Point" heißt sinngemäß übersetzt "Gleitkomma" und bedeutet
nichts anderes, als dass es eben keine feste Anzahl an (Nachkomma-)
Stellen gibt wie bei Festkommaarithmetik, sondern dass das
Dezimaltrennzeichen je nach geforderter Auflösung dynamisch verschoben
werden kann. Das macht dann Sinn, wenn Werte verarbeitet (miteinander
verrechnet) werden sollen, die einen über mehrere Größenordnungen
verteilten Wertebereich haben. Das geht mit Festkommaarithmetik nur
bedingt bzw. in gewissen Bereichen nur mit geringer Auflösung.
In den meisten realen Anwendungsfällen kann bzw. sollte man ohne
Gleitkommaarithmetik arbeiten, da es dadurch tatsächlich bei höherem
Resourcen-Aufwand möglicherweise ungenauer wird, aber es gibt
Anwendungsfälle, bei denen eigentlich kein (sinnvoller) Weg daran
vorbeiführt. Und ob man mit üblen Verrenkungen händisch eine
Gleitkomma-Arithmetik "simuliert" oder auf erprobte Bibliotheken
zurückgreift, die das alles automatisch machen, wobei der Code
übersichtlich bleibt, ist schon ein Unterschied...
Eine Crux beim WINAVR ist nach wie vor die nicht vorhandene
64-Bit-Gleitkomma-Unterstützung (double wird wie float behandelt).
Abgesehen davon ist Gleitkommaarithmetik auch auf einer fixed-point-CPU
kein Hexenwerk oder Teufelszeug. Man muss nur wissen, was man tut und
dass in den meisten Fällen die Festkommaarithmetik tatsächlich der
sinnvollere Weg ist, zumal der auch beim WINAVR 64-bittig verwendet
werden kann.
Ralph wrote:
> Der µC kann kein Floating point, also wird in einer Library ( vom> Compiler geliefert ) die Berechnung in eine Integerberechnung> umgewandelt.> Nachteil: Du hast keinen EInfluß darauf wie das geschieht.
Doch, wenn eine standardkonforme Implementierung vorliegt, weiß man
genau, daß sich die Software-Version genauso verhält wie eine
Hardware-Version per FPU. Nämlich IEEE-konform. Der Unterschied liegt
dann nur im Resourcen-Verbrauch (Zeit, Code, Ram, ...)
Es gibt auch Float-Implementierungen, die zugunsten der System-Tesourcen
auf IEEE-Konformität verzichten, aber auch da wird nicht einfach auf
ganze Zahlen abgebildet, sondern mit Exponent und Mantisse gerechnet,
ebenso wie es in einer FPU geschieht (die dann sogesehen auch alles in
Integerberechnung umwandelt).
> Du hast zwar Floating Point im C-Code aber es wird NICHT mit Floating> Point gerechnet !!!!!!
Doch, klaro. Oder was hast du für nen seltsamen Compiler?
Johann
mr.chip wrote:
> Man kann nur raten, daher:>> Vermutung 1: Stack (der von zuoberst im Speicher wächst) wird so gross,> dass er mit dem Heap (der von unten im Speicher wächst) kollidiert.>> Vermutung 2: Pointer auf lokale Variable, der nach dem Verlassen der> betreffenden Funktion weiterverwendet wird.>
Vermutung 3: Array Überläufe
> das zum Beispiel zwei variabeln ihre werte vertauschen und einer der> beiden sogar einen dementsprechenden, zu kleinen Wert bekommt ?> So passiert nämlich bei mir.
Immer nach/an der selben Programmstelle/Funktion/Interruptroutine?
Vermutung 2a und 3a: Amoklaufender Pointer
> von Oliver>> avr-size (falls du WInAVR nutzt) gibt am Ende mehrere Werte aus. Der,> bei dem steht: ".tetxt + .data + .bss" ist der für das SRAM. Was wird> denn da angezeigt?
Das hier ist die Compilermeldung
1
AVR Memory Usage
2
----------------
3
Device: atmega644p
4
5
Program: 10436 bytes (15.9% Full)
6
(.text + .data + .bootloader)
7
8
Data: 540 bytes (13.2% Full)
9
(.data + .bss + .noinit)
> Vermutung 1: Stack (der von zuoberst im Speicher wächst) wird so gross,> dass er mit dem Heap (der von unten im Speicher wächst) kollidiert.
- Das wollen wir mal nicht hoffen ;)
> Vermutung 2: Pointer auf lokale Variable, der nach dem Verlassen der> betreffenden Funktion weiterverwendet wird.
- Ich benutze keine Pointer
> Vermutung 3: Array Überläufe
- Das wäre auch gut möglich, kontrolliere ich gleich mal
> Vermutung 2a und 3a: Amoklaufender Pointer
- Ich benutze keine Pointer
Markus wrote:
> Data: 540 bytes (13.2% Full)> Vermutung 2a und 3a: Amoklaufender Pointer> - Ich benutze keine Pointer
Du benutzt keine Strings?
Ich tendiere immer mehr zu Variante 3: Array Überläufe.
Und wenn ich raten müsste: Irgendwo wird es eine 'String-Variable'
geben, in die du einen zu langen String hineinstopfst.
Wie schon mehrfach angenommen: Vielleicht überschreibt der Stack Teile
vom Heap? Das führt nicht zwangsläufig zum Programmabsturz, die Daten im
Heap sind aber trotzdem korrupt. Die statische Info von avr-size ist
dazu als Diagnose leider recht unbrauchbar. Am besten den Controller mal
mit mem-check von
http://www.roboternetz.de/wissen/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc
laufen lassen. Damit kannst Du die Stack/Heap-Problematik schon mal
klären. Ansonsten weitere Fehlersuche.
Servus
Michael
Also ich beschreibe mal was ich überhaupt gemacht habe.
Ich verwende in dem Projekt keine Strings. es handelt sich hier um ein
Technikerprojekt für die Schule. Ich kopier einfach mal den text aus
einem anderen threat :P
>> Aufbau :>>>> Eine bewegliche Platte kann auf zwei Achsen (X,Y) über Servos gekippt>> werden. Auf der Platte ist ein IR Touchpad geschraubt, das Seriell>> (UART0 ,9600Baud) die Position einer rollenden Kugel an den ATmega644P>> übermittelt.>> Das soll/wird über einen Software PID Regler geregelt. Ziel ist das>> halten der Kugel auf eine festgelegte Sollposition auf der Platte>> (Positionsregelung).
Um die Kugelbewegung zu kompensieren, benutze ich eine Art "Kaskadierten
Regler" , das heisst meine Regeldifferenz wird durch die
kugelgeschwindigkeit beeinflusst. Soweit ok.
Die Kugelgeschwindigkeit bestimme ich über die differenz zwischen
Aktueller Kugelposition und der letzten. und genau darin liegt das
folgende Problem :
Das ding Zappelt manchmal wie Wild herum. Das liegt daran, das manchmal
falsche Tocuhplate Nachrichten empfangen werden. ( Keine
Checksummenformeln vorhanden ). Um solche Fehlsendungen zu kompensieren
nehm ich aus 7 Empfangenen X- und Y- positionen jeweils einen
mittelwert.
Diese mittelwertberechnung wollte ich über 2 Static float Arrays
bewerkstelligen. Aber irgendwie kam er dabei durcheinander, wie ich oben
beschrieben hab.
Jetzt habe ich die Arrays durch einzeln Deklarierte variablen ersetzt,
und im moment scheints zu klappen. Die Werte der variablen stimmen und
(freu) die falschen Signale werden ausgefiltert.
so, soviel dazu.....
>Und wenn ich raten müsste: Irgendwo wird es eine 'String-Variable'>geben, in die du einen zu langen String hineinstopfst.
Da es sich hierbei um eine Regelung handelt die ausser zahlenwerte
nichts ausgibt, habe ich wirklich keine Strings ;)
Also vermute ich , das es an falschen Array zuweisungen gelegen hatte.
Leider hab ich den alten Code nichtmehr, weil ich zu spät ins Forum
geschaut hatte.
im Moment schaut die Funktion die diese probleme verursachte so aus :
1
/*
2
* Berechnet den mittelwert aus der Anzahl von "Fifo_Groesse" der Geschwindigkeitswerten
3
*
4
* @value = Wert der Gemittelt werden soll
5
* @achse = Achse für die der Wert gemittelt werden soll
// .... wie für Achse 1 , nur anstatt x wird ein y in die Array namen eingetragen
31
}
32
33
returnsum;
34
}
ich verstehe nicht wo hier der Fehler gelegen haben sollte. Das problem
hat sich aber , meiner Meinung nach , durch das ändern der Funktion
verbessert. An die Arraygrenzen hab ich mich gehalten, habe auch nicht
mit schleifen gearbeitet oder dergleichen. Zum besseren verständinis
hier nochmal der aufrufende Code.....
1
// Wertet den Berührungsstatus aus
2
newState.state=msgPlate[2];
3
// Wertet den X-Wert aus
4
newState.x_pos=((msgPlate[3])+(256*msgPlate[4])+1);//+1 da die PC-Technik von 0 beginnt zu zählen
5
// Wertet den Y-Wert aus
6
newState.y_pos=((msgPlate[5])+(256*msgPlate[6])+1);//+1 da die PC-Technik von 0 beginnt zu zählen
7
8
9
// Berechnet die gemittelte X - Geschwindigkeit der kugel
> static float Fifo_x[4];> Fifo_x[4] = value;
Und da ist er! Du deklarierst ein Array mit 4 Elementen, die die Indizes
0...3 haben. Dann weist Du dem Element mit dem Index 4, das gar nicht
existiert (bzw. dessen Speicherplatz vermutlich in einer anderen
Variable liegt), einen Wert zu und BUMM...
Das letzte Element in Fifo_x ist Fifo_x[3]!
Das wäre nach Karl heinz Buchegger (9:18) ein Kategorie-3-Fehler...
Michael Wilhelm wrote:
> Zu der neuen Funktion:>> nimm 8 Elemente und teile dann mit >> 3. Ist schneller.
Schneller schon. Aber leider falsch.
(Wann wird man endlich diesen Unsinn, eine Division durch eine
Schiebeoperation zu ersetzen, ausrotten können. WENN eine
Schiebeoperation möglich ist UND das tatsächlich schneller ist DANN wird
der Compiler/Optimizer das von sich aus ersetzen! Du gewinnst nichts
dadurch, dass du selbst die Schiebeoperation hinschreibst, Compiler
machen diese Ersetzung seit mehr als 20 Jahren routinemässig. Du kannst
aber alles verlieren wenn, wie in diesem Fall, die Schiebeoperation
nicht funktioniert weil er keine int sondern float hat)
Michael Wilhelm wrote:
> Ok, zu flüchtig gelesen. Stellt sich jetzt die Frage, was ein> IR-Touchpad als Koordinatendaten ausspuckt. Fließkomma?
Auch wenn es int sind, ist der Mittelwert aus
1 2 1 2 1 2
keine ganze Zahl.
Ob er die Kommastelle braucht, muss der TO selbst entscheiden.
(Ich bin bei dir: wenn man auf eine Kommastelle aus ist, wäre Fixpoint
Artihmetik auf einem AVR besser, da schneller)
Johannes M. wrote:
> Man muss nur wissen, was man tut und> dass in den meisten Fällen die Festkommaarithmetik tatsächlich der> sinnvollere Weg ist, zumal der auch beim WINAVR 64-bittig verwendet> werden kann.
Wobei die natürlich keineswegs ressourcenschonender als 32-bit-
Gleitkomma ist, sowohl hinsichtlich Rechenzeit als auch Speicherplatz-
bedarf.
Jörg Wunsch wrote:
> Wobei die natürlich keineswegs ressourcenschonender als 32-bit-> Gleitkomma ist, sowohl hinsichtlich Rechenzeit als auch Speicherplatz-> bedarf.
Klar, aber es sind ja auch doppelt so viele Bits...
Jörg Wunsch wrote:
> Johannes M. wrote:>>> Man muss nur wissen, was man tut und>> dass in den meisten Fällen die Festkommaarithmetik tatsächlich der>> sinnvollere Weg ist, zumal der auch beim WINAVR 64-bittig verwendet>> werden kann.>> Wobei die natürlich keineswegs ressourcenschonender als 32-bit-> Gleitkomma ist, sowohl hinsichtlich Rechenzeit als auch Speicherplatz-> bedarf.
In dieser Hinsicht fällt mir eine Frage ein.
Jörg, weißt du was? Wird der WinAvr je richtige double bekommen?
> Ok, zu flüchtig gelesen. Stellt sich jetzt die Frage, was ein> IR-Touchpad als Koordinatendaten ausspuckt. Fließkomma?
zwei bytes für jeweils eine Achse. die position errechnet sich dann wie
folgt :
byte1 = 0-255 = msgPlate[3]
byte2 = 0-15 = msgPlate[4]
position ist dann :
newState.x_pos = ( (msgPlate[3]) + (256 * msgPlate[4]) + 1)
>Und da ist er! Du deklarierst ein Array mit 4 Elementen, die die Indizes>0...3 haben. Dann weist Du dem Element mit dem Index 4, das gar nicht>existiert (bzw. dessen Speicherplatz vermutlich in einer anderen>Variable liegt), einen Wert zu und BUMM...
Boah, wie konnt ich´n den Fehler machen !! Da muss ich nochmal
nachlesen.....
Hab gerade mal nachgeschaut.
Vb.net --------------------------------------------------
1
dim arr(5) as integer = indizies arr(0)....arr(5)
C -------------------------------------------------------
1
intarr[5]=indiziesarr(0)....arr(4)
Wenn das mal keine Stolperfalle ist !! jetz muss ich erstmal den ganzen
C-Code nach grenzverletzungen durchsuchen.....