Hallo,
ich habe hier ein seltsames Problem.
Ich möchte in meinem Progamm Daten aus dem PROGMEM verarbeiten und
berechnen. Im PROGMEM habe ich eine Tabelle (eigentlich sind es mehrere
hier nur zur Veranschaulichung des Codes eine) mit 175 Faktoren
hinterlegt.
Das Programm befüllt dann eine Variable im Flash während der Laufzeit
(zu Beginn) aufgrund dieser Daten nach folgender Vorschrift:
Zuvor wegen in ssaTabelle die Daten des aus der PROGMEM-Tabelle 1:1
kopiert (nach dem kopieren steht hier auch 1:1 das drin, habe ich über
UART ausgeben lassen).
Nun kommt dort aber nach der Berechnung nicht das raus, was ich von Hand
zu Fuß rechne. Das kuriose ist, teile ich die Rechnung in einzelne
"Häppchen" und arbeite mit Zwischenergebnisse, rechnet sich alles
korrekt. Obwohl sich meiner Meinung nach die Rechnung mit den
Zwischenergebnissen von den Datentypen her nicht unterscheidet.
Dabei rechne ich wie folgt: (ZWE steht für Zwischenergebnis)
1
uint16_tZWE1=0;
2
int16_tZWE2[ANZAHL2]={0};
3
int32_tZWE3[ANZAHL2]={0};
4
int16_tZWE4[ANZAHL2]={0};
5
ZWE1=((F_CPU*60)/120000);
6
ZWE2[n]=(ssaTabelle[n]+VERSCHIEBEWERT);
7
ZWE3[n]=((int32_t)ZWE1)*ZWE2[n];
8
ZWE4[n]=ZWE3[n]/((n+1)*3);
Anbei der Codeteil des Programms inkl. der Datentypen. Ich habe aufgrund
der Übersicht erstmal die ganzen Initialsierungen rundherum weggelassen
außer die hier verwendeten Variablen/Datentypen. Der Code ist daher so
nicht compilierbar.
Anbei hänge ich auch noch ein Mitschnitt aus der UART (UART-Daten.txt),
worüber ich debugge. Dort werden die Werte sowohl von den
Zwischenergebnissen (Ausnahme ZWE1) ausgegeben und die vom µC
gerechneten (nach obiger "Gesamtformel") Werte, siehe Code-Ausschnitt.
Wie man sieht, unterscheidet sich ZWE4 (das Endergebnis) vom dem
Ergebnis, was vom µC in einem Rutsch nach obiger Formel gerechnet wurde.
Über Hilfe wäre ich dankbar.
Ach ja, Prozessor ist ein Atmega168.
Über jede Hilfe bin ich dankbar.
Beste Grüße
David
Achso, noch etwas.
Wie man sieht, sind manche Werte korrekt berechnet und manche nicht.
Anfangs sind mehr falsche Werte als gegen Ende (siehe UART-Daten.txt)
= 350 Bytes RAM
== 1400 Bytes nur für diese 3 Arrays
> Ach ja, Prozessor ist ein Atmega168.
RAM-Größe = 1024 Bytes
PS:
Und was bitte soll das darstellen?
1
int16_tssaTabelle=0;
2
...
3
ssaTabelle[n]...
Ist ssaTabelle nun ein einzelner int16_t, oder ein ganzes Array?
David Menzeln schrieb:> Der Code ist daher so nicht compilierbar.
Tut mir Leid, da ist mir beim herunterbrechen des Codes für das Forum
hier ein Fehler passiert.
Im eigentlichen Programm ist es ein array und ist so definiert:
int16_t ssaTabelle [ANZAHL2+25] = {0};
Und die ganzen arrays der ZWE sehe ich gerade sind auch [ANZAHL2+25] und
nicht nur [ANZAHL2]
Anbei nochmal die main "korrigiert"
Was mir gerade noch aufgefallen ist beim Durchsehen der UART-Debug
Datei:
Sobald dieser Ausdruck (ssaTabelle[n] + VERSCHIEBEWERT) positiv wird,
scheinen sämtliche Berechnungen zu stimmen. Nur sofern dieser negativ
ist, kommt offensichtlich Datenmüll raus.
David Menzeln schrieb:> David Menzeln schrieb:>> Der Code ist daher so nicht compilierbar.>> Tut mir Leid, da ist mir beim herunterbrechen des Codes für das Forum> hier ein Fehler passiert.
Das mögen wir hier gar nicht, wenn du Code postest, der so nicht auf dem
µC gelaufen ist.
> Im eigentlichen Programm ist es ein array und ist so definiert:> int16_t ssaTabelle [ANZAHL2+25] = {0};>> Und die ganzen arrays der ZWE sehe ich gerade sind auch [ANZAHL2+25] und> nicht nur [ANZAHL2]
Also noch mehr!
Das ändert nichts daran, dass du in Summ schon viel mehr Daten zu
speichern versuchst, als du überhaupt SRAM hast.
David Menzeln schrieb:> Sobald dieser Ausdruck (ssaTabelle[n] + VERSCHIEBEWERT) positiv wird,> scheinen sämtliche Berechnungen zu stimmen. Nur sofern dieser negativ> ist, kommt offensichtlich Datenmüll raus.
ok. das ist ein Hinweis.
WIe ist n definiert?
signed oder unsigned?
Karl Heinz Buchegger schrieb:> Also noch mehr!> Das ändert nichts daran, dass du in Summ schon viel mehr Daten zu> speichern versuchst, als du überhaupt SRAM hast.
Ok, dazu habe ich gleich eine Frage. Beim Compilieren bekomme ich
folgendes angezeigt:
Data: 679 bytes (66.3% Full)
(.data + .bss + .noinit)
Ist das das SRAM?
Darüber hinaus habe ich diese "Geschichte" mit dem ZWE's nur eingefügt,
da die Berechnung in "einem Rutsch"
nicht geklappt hat. Lasse ich diese ganzen ZWE Variablen weg, geht es
ebenso nicht. Da ich den Fehler dort vermutete, habe ich eben diese
ganzen ZWEs hinzuprogrammiert, um zu sehen, in welchem Rechenschritt
sich ein Fehler eingeschlichen hat.
Das kuriose ist ja aber, mit diesen ZWEs, wo der SRAM Speicher ja
überlaufen müsste, funktioniert es, solange man alles nacheinander
berechnet (siehe UART-Mitschnitt).
David Menzeln schrieb:> Ok, dazu habe ich gleich eine Frage. Beim Compilieren bekomme ich> folgendes angezeigt:> Data: 679 bytes (66.3% Full)> (.data + .bss + .noinit)>> Ist das das SRAM?
Ja, aber nur der statische Verbrauch. Die ZWE* sind da nicht mit drin.
David Menzeln schrieb:> Lasse ich diese ganzen ZWE Variablen weg, geht es> ebenso nicht.
Da auch ssaTabelle eine dynamische Variable ist, bist du auch schon ohne
die ZWE "drüber".
PS: Ok, sehe gerade, dass Letzteres eher nur geraten ist. Anhand deines
Pseudo-Codes lässt sich nämlich gar nicht sagen, ob sie statisch oder
dynamisch ist.
Stefan Ernst schrieb:> Da auch ssaTabelle eine dynamische Variable ist, bist du auch schon ohne> die ZWE "drüber".
Und welche Variablen sind dann dort mit drin? Wenn du von dynamischen
sprichst, werden es wohl die statischen sein. Aber welche sind die
statischen, woran erkenne ich sie?
Und kann daher der Fehler kommen? Aber wieso ist die Berechnung dann
richtig, wenn ich es in "Häppchen" unterteile?
David Menzeln schrieb:> Stefan Ernst schrieb:>> Da auch ssaTabelle eine dynamische Variable ist, bist du auch schon ohne>> die ZWE "drüber".>> Und welche Variablen sind dann dort mit drin? Wenn du von dynamischen> sprichst, werden es wohl die statischen sein. Aber welche sind die> statischen, woran erkenne ich sie?>> Und kann daher der Fehler kommen? Aber wieso ist die Berechnung dann> richtig, wenn ich es in "Häppchen" unterteile?
Weil du zufällig auf irgendwelchen SRAM Zellen agierst, auf denen sonst
nichts liegt.
Das ist doch alles Stochern im Nebel.
Bau ein ordentliches Testprogramm, das man starten, testen und debuggen
kann.
David Menzeln schrieb:> Und welche Variablen sind dann dort mit drin? Wenn du von dynamischen> sprichst, werden es wohl die statischen sein. Aber welche sind die> statischen, woran erkenne ich sie?
Die Variablen, die Du außerhalb von Funktionen definierst sind statisch.
Sie sind die ganze Programmlaufzeit über vorhanden. Deren
Speicherverbrauch wird nach dem Compilieren angezeigt.
Die "dynamischen" (besser: automatischen) Variablen sind die, die Du
(ohne static) innerhalb einer Funktion definierst. Die existieren nur,
solange die Funktion läuft und werden auf dem Stack angelegt. Wie viel
Platz die verbrauchen kann man nach dem Compilieren nicht sagen, weil
das davon abhängt, welche Funktionen Du in welcher Reihenfolge aufrufst,
was wiederum von Benutzereingaben etc. abhängen kann. Deshalb siehst Du
deren Speicherverbrauch nicht. Das gilt übrigens auch für Variablen, die
Du in der main-Funktion definierst ...
Wenn Du Dir nur Zwischenergebnisse zum Debuggen ausgeben willst,
brauchst Du doch aber keine riesigen Arrays anlegen. Es reicht eine
einzelne Variable für jedes Zwischenergebnis. Erstell am besten ein
lauffähiges Minimalbeispiel, das Dein Problem zeigt. Vielleicht findest
Du den Fehler ja sogar selber, wenn Du nach und nach alle Schritte
weglässt, die den Fehler nicht verursachen.
Leider bin ich noch nicht weiter, aber ich habe wunschgemäß
compilierbaren Code erzeugt aus dem Pseudo Code mit gleichem Ergebnis.
Das Programm ist nur mit UART ausgestattet (Lib von Peter Fleury).
In dem nun angehängten Fall habe ich wieder die Zwischenrechnungen
eingefügt. Diese sind korrekt und entsprechen einer Hand zu Fuß. Die
Rechnung der "in einem Rutsch" Formel ist dennoch anders.
Anbei hierzu auch, was der UART ausgibt in der UART-Daten1.txt
Damit keine Probleme bezüglich des SRAMs auftreten können, folgt gleich
noch das selbe Programm ohne die Zwischenrechnungen nur mit dem einen
Array int16_t ssaTabelle [ANZAHL2+25] = {0};
So und nun das ganze ohne die Zwischenrechnungsschritte.
Was man dem UART entnehmen kann, dass egal ob ich die Zwischenrechnung
Arrays einfüge, das Ergebnis der "in einem Rutsch" Formel ist immer
gleich (falsch).
d.h. ich berechne zwar die Zwischenergebnisse ZWE* aber lasse die
Ausgabe der Zwischenergebnisse per UART weg, so kommt hier ebenfalls ein
falsches Ergebnis raus (UART-Auswertung anbei als txt, ebenso die
vollständige main, uart.c und uart.h identisch).
Demnach scheint es irgendwie nicht an den Zwischenergebnissen zu liegen,
sondern die dazwischen liegende UART Ausgabe führt zum richtigen
Ergebnis. Aber wieso?
Ich nutze AVR Studio 5 und den darin enthaltenen GCC Compiler, falls das
eine Rolle spielt.
Kann es sein, dass der Compiler irgendetwas fehlintepretiert von den
Datentypen her?
Ich habe ja festgestellt, dass wenn dieser Ausdruck
1
(ssaTabelle[n]+VERSCHIEBEWERT)
nicht mehr negativ ist, sondern >= 0, rechnet der µC richtig. Nur bei
negativem Vorzeichen kommt nicht das richtige Ergebnis raus. Daher habe
ich die vage Vermutung, dass es irgendwo mit Vorzeichen etwas zu tun
haben muss.
mal aus dem main raus und mach sie global.
Und dann siehst du dir deine Memory Statstik an, wie weit dein SRAM
gefüllt ist.
Alleine diese 4 Arrays sind 1000 Bytes. Wenn da jetzt von der UART noch
was dazu kommt, du sonst noch ein bischen was brauchst und der Stack
auch noch dazu kommt, dann könnte das schon eng werden.
Oder noch einfacher:
Wenn du wissen willst, ob deine Berechnung irgendwo schief geht, dann
specke halt dein Programm NUR auf die Berechnung ab. Um die Berechnung
zu testen, brauchst du die ganzen Arrays nicht! Die sind erst mal nur
etwas, was dir Ärger im Speicher machen kann, weil sie so groß sind!
Zum Testen geht man auf die einfachste Variante, die man sich vorstellen
kann. Jedes zusätzliche Teil ist nur wieder eine potentielle
Fehlerquelle mehr. Testprogramme können gar nicht einfach genug sein!
David Menzeln schrieb:> Daher habe> ich die vage Vermutung, dass es irgendwo mit Vorzeichen etwas zu tun> haben muss.
Die Vermutung ist zwar naheliegend, aber sie ist nicht die einzige
Vermutung die man machen kann.
Denn deine 'negativen Werte' haben auch gemeinsam, dass sie allesamt am
Anfang deines Progmem Arrays stehen. D.h. wenn du dir ungewollt den
Speicher niederbügelst, dann kann es sich zufällig auch so ausgehen,
dass du genau diesen Speicherbereich niedermähst, in der zufällig genau
diese Werte stehen.
David Menzeln schrieb:> Kann es sein, dass der Compiler irgendetwas fehlintepretiert von den> Datentypen her?
Welche Optimierung hast du eingeschaltet?
Wie sieht das Assemblerlisting aus?
Was kommt eigentlich da raus: ((n+1)*3)
Spätestens beim uint8_t n=85 könnte das interessant werden...
Hallo Karl-Heinz,
erst einmal nochmals danke für den erneuten Post und Weiterverfolgung
des Themas und das Engagement, dass du hier im Forum an den Tag legst.
Ich hatte gestern Abend diese Variante bereits versucht und habe die
Zwischenergebnisse ZWE* als ganz normale Variablen (keine Arrays*)
definiert:
1
int16_tZWE2=0;
2
int32_tZWE3=0;
3
int16_tZWE4=0;
4
int16_tssaTabelle[ANZAHL2+25]={0};
Leider kam das gleiche falsche Ergebnis raus.
Und hier war ich bei 2+4+2+400 = 408 bytes + ein bisschen aus dem UART.
Und wie auch am 08.01.2013 22:03 Uhr gepostet, selbst wenn ich die
ganzen ZWE* weglasse und nur die normale Berechnung mache (also
Minimal+UART) wird das Ergebnis falsch.
Ich bin auch gerne für Vorschläge offen, etwas zu testen und poste das
Ergebnis dann. Aber im Moment weiß ich nicht mehr weiter bzw. wo ich
noch ansetzen sollte.
Dein Programmvorschlag werde ich testen. Dies kann ich aber erst gegen
späten Nachmittag tun. Berichte dann hier weiter.
*Die Arrays habe/hatte ich nur drin, da ich das debuggen per LCD gemacht
hatte und Schritt für Schritt die Werte ausgeben wollte (Index habe ich
über "Taster-gesteuert" hochgezählt für die Ausagbe). Da ich aber für
hier die Ergebnisse für einen Post hier im Forum sichtbar machen wollte,
schrieb ich sie später auf die UART-Schnittstelle, damit ich sie
kopieren und posten kann.
___________________________
Hallo Lothar,
ich habe an dem Grundeinstellung von AVR-Studio erste einmal nichts
geändert. Daher weiß ich nicht, welche Optmierung da eingeschaltet ist,
muss ich nachsehen…(ich glaube aber Standard ist 0s, oder?) Ich habe ein
Projekt erstellt, die beiden Dateien UART-Dateien hinzugefügt und
compiliert. Ein seperates makefile habe ich nicht erstellt. Kann das
automatisch erstelle makefile aber gerne dazu mal anhängen.
Bezüglich des Assemblerlistings: Kann ich gerne posten, aber ebenfalls
frühstens gegen späten Nachmittag (bin vorher nicht zu Hause).
Das ((n+1)*3) müsste ich noch auf die Schnittstelle schreiben.
Das Problem tritt ja aber bereits früher in der Rechnung ab n=25.
Die "höheren" n's rechnet er ja richtig (sobald der Ausdruck
(ssaTabelle[n] + VERSCHIEBEWERT) >=0 wird). Ein Versuch ist es Wert.
Testweise kann ich n ja auch mal als uint16_t deklarieren.
Danke.
wieso tut ihr Euch das eigentlich an?
Solange der TO keinen kompilierbares (und kurzes!) Programm postet dass
den Fehler zeigt ist es doch Masochismus sich zu bemühen
Bernd schrieb:> wieso tut ihr Euch das eigentlich an?> Solange der TO keinen kompilierbares (und kurzes!) Programm postet dass> den Fehler zeigt ist es doch Masochismus sich zu bemühen
Ab 22:03 habe ich (TO) 3x kompilierbare (kurze!) Programme gepostet
inkl. der Ausgaben auf der UART-Schnittstelle.
Lothar Miller schrieb:> Welche Optimierung hast du eingeschaltet?
Unter Vorbehalt sage ich mal, dass dies das Problem war.
Optimierung war auf -O1. Augenscheinlich auf -Os funktioniert es
(zumindest UART-Ausgabe von oben gepostetem Code ist nun richtig
berechnet).
Das Programm in seinem vollen (nicht abgespeckt) teste ich heute noch,
dann gebe ich nochmal Bescheid.
So noch abschließend: Mit der -Os läuft das ganze auch im vollständigen
Programm richtig berechnet.
Nochmals danke an alle beteiligten, die sich mit Geduld hier Mühe machen
in Ihrer Freizeit.
Damit ist das Problem aber nicht gelöst, sondern nur verdeckt. Wenn das
Programm korrekt ist, muss es mit jeder Optimierungseinstellung
funktionieren. Früher oder später fliegt Dir das wieder um die Ohren,
wenn Du den Fehler nicht behebst.
Oder mache int32_t ssaTabelle[n] statt int16_t
Du erwartest bei n=24 folgende Werte:
ZWE2[n]=(ssaTabelle[n] + VERSCHIEBEWERT);
= -190 + 120 = -70
ZWE3[n]= ((int32_t)ZWE1)*ZWE2[n];
= 8000 * -70 = -560000 FFFFFFFFFFF77480
ZWE4[n]= ZWE3[n]/((n+1)*3);
= -560000 / 75 = -7466,666 FFFFFFFFFFFFE2D6
Es kommt aber 19621 0x4CA5 heraus.
hier immer 74
||
n= vv
24 19621 *25*3= 1471575 0x00167457
25 11305 *26*3= 881790 0x000D747E
26 3604 *27*3= 291924 0x00047454
27 -3546 *28*3= -297864 0xFFFB7478
28 -10204*29*3= -887748 0xFFF2743C
29 -16417*30*3=-1477530 0xFFE97466
30 -22230*31*3=-2067390 0xFFE07442
^^^^
dieser Wert wird um 9 weniger
> sobald der Ausdruck (ssaTabelle[n] + VERSCHIEBEWERT) >=0 wird
das ist ab n=85+24=109 der Fall (-120+120=0). n: 109 µC gerechnet:
-14696*110*3=-4849680 = FFB5FFF0
> mal aus dem main raus und mach sie global.
D.h. schreibe sie vor der main hin!
Versuchsweise mal
#include<math.h> benutzen!
Karl Heinz Buchegger schrieb:> Was spricht dagegen, wenn dein erstes Testprogramm mal so aussieht
was spricht dagegen den Vorschlag von Karlheinz mal auszuprobieren und
das Ergebnis zu posten?
Nichts.
Ich hatte nur bis dato gedacht, dass durch die Optimierungsumstellung
das Problem gelöst sei und der Vorschlag dadurch "hinfällig" ist weiter
zu verfolgen.
Ich weiß nicht, ob ich heute dazu komme (eher nicht), aber ich werde
spätestens morgen den Vorschlag umsetzen und das Ergebnis posten.
David Menzeln schrieb:> Ich hatte nur bis dato gedacht, dass durch die Optimierungsumstellung> das Problem gelöst sei und der Vorschlag dadurch "hinfällig" ist weiter> zu verfolgen.
Das ist die "Kopf in den Sand" Taktik eines Straußes(*). Und in einem
Jahr musst du aus irgenwelchen Gründen eine andere Optimierung
einstellen, und wunderst dich dann, dass nichts mehr geht...
(*) die so allerdings gar nicht stimmt:
http://de.answers.yahoo.com/question/index?qid=20060709112056AAgLqJQ
Hallo Lothar,
ich wusste nicht, dass es auf allen Optimierungen laufen muss. Ich hatte
selbiges mal bei einer Inbetriebnahme eines LCDs und dort wurden die
delays wegoptimiert. Es ging nur auf bestimmten
Optimierungseinstellungen. Daher meine Unwissenheit, dass es daran
liegt.
Das Programm von Karl Heinz (main.c, UART-Daten4) habe ich compiliert.
Die Werte sind ok.
Programm anbei. Die UART.c und UART.h spare ich mir mal mit dem
anhängen.
Ich poste gleich noch das Programm von Karl Heinz erweitert, bis der
Fehler auftritt. Mache aber dies getrennt, um jedes Programm separat
erst einmal anzuhängen mit dem UART-Mitschnitt.
So und nun habe ich das Programm um diese Variable erweitert:
1
int32_twert2;
In die Variable wird folgendes geschrieben (ebenfalls ergänzt im
Programm):
1
wert2=((F_CPU*60)/120000L)*((int32_t)wert);
Sonst habe ich, bis auf weitere UART-Ausgaben nichts ergänzt.
wert ist dabei das int16_t aus dem Programm von Karl Heinz (und wird
soweit auch noch in diesem Programm richtig berechnet, siehe
UART-Mitschnitt). Zur Sicherheit habe ich es auf ein int32_t gecastet.
((F_CPU*60)/120000L) ist konst = 8000.
Diese Berechnung geht allerdings in die Hose, siehe UART-Daten5.txt
wert2 hat nicht den Wert, welches es haben sollte. Ich habe bei der
UART-Ausgabe den Variablen-Namen davor ergänzt und auch die Zählvariable
n zur Übersicht noch mit ausgeben lassen.
Optimierungseinstellung auf -O1.
Besserwisser schrieb:
Habe ich gerade versucht, liefert das gleiche falsche Ergebnis wie das
Programm vom Post Datum: 10.01.2013 17:04.
Anbei wie gehabt Programm+UART-Mitschnitt.
Auffällig ist halt, dass die unteren 24 Bit des Ergebnisses stimmen, nur
die oberen 8 Bit sind falsch:
Dezimal: Binär:
Korrekt: -560000 1111 1111 1111 0111 0111 0100 1000 0000
Falsch: 16217216 0000 0000 1111 0111 0111 0100 1000 0000
Funktioniert das jetzige Programm denn, wenn Du die Optimierung auf -Os
stellst? Was ist, wenn Du (F_CPU * 60 / 120000UL) durch 8000L ersetzt?
Oder wert2 einfach mal -560000 zuweist, wird das wenigstens richtig
ausgegeben?
Probier auch mal die Berechnung von wert2 direkt vor den Aufruf von
ltoa() zu stellen. Passiert das gleiche? Eventuell überschreibt eine
Funktion fälschlicherweise das oberste Byte von wert2.
Fabian O. schrieb:> Funktioniert das jetzige Programm denn, wenn Du die Optimierung auf -Os> stellst?
Ja, das geht.
Fabian O. schrieb:> Was ist, wenn Du (F_CPU * 60 / 120000UL) durch 8000L ersetzt?
Das gleiche (falsche) Ergebnis.
Fabian O. schrieb:> Probier auch mal die Berechnung von wert2 direkt vor den Aufruf von> ltoa() zu stellen. Passiert das gleiche? Eventuell überschreibt eine> Funktion fälschlicherweise das oberste Byte von wert2.
Funktioniert ebenfalls leider nicht. Habe dieses Programm anbei gehängt
inkl. UART-Mitschnitt und darin ist übrigens auch (F_CPU * 60 /
120000UL) durch 8000L ersetzt.
Bernd schrieb:> wert2 = -560000
Ja, ltoa() macht das richtig, auf der Schnittstelle landet -560000.
Das Programm läuft auch nicht richtig mit diesem berechneten (falschen)
Wert auf -O1. Daher traue ich auch ltoa(), denn wäre der Wert richtig,
nur falsch gewandelt/ausgegeben, würde das Programm sauber laufen, wie
es mit -Os tut.
stell mal die Ausgabe um auf CR-LF und lasse die Bezeichner weg, damit
es besser lesbar wird:
uart_puts_P("\n"); ---> uart_put(13);uart_put(10);
Bitte erstelle ein File mit n und den erwarteten gewünschten Werten
wert1, wert2 etc.
mache wert zu int_32
Wozu ist das ganze? Stepper-Delay?
Ich habe mal versucht das Problem bei mir zu reproduzieren. Ich habe
allerdings nur Xmega-Hardware hier, daher musste ich andere
UART-Routinen benutzen. Es kommen aber unabhängig von der
Optimierungseinstellung die richtigen Ergebnisse raus.
Hast Du vielleicht noch einen anderen Mikrocontroller, mit dem Du es
testen kannst? Nicht, dass genau die eine SRAM-Zelle defekt ist ... Auch
wenns wohl ziemlich unwahrscheinlich ist, aber mehr fällt mir leider
nicht mehr ein.
Nochmal ein Danke für alle Mühe bis dato.
Ich habe das schon auf zwei verschiedenen Atmega168 versucht, beide mit
gleichem Problem.
Chips waren fabrikneu.
Ich könnte es mal auf einem Atmega8 versuchen, dazu brauche ich aber 1-2
Tage, da ich die Schaltung auf dem Steckbrett mit THT Bauteilen
nachstellen müsste, da ich die jetzige Hardware auf einer fertigen LP
aufgelötet habe als SMD mit TQFP Atmega168, das ist schwierig den Chip
umzufummeln.
@eProfi
Tut mir Leid, das habe ich nicht ganz verstanden, was ich machen soll.
geht es wieder nicht (siehe UART-Daten9.txt).
Gleichzeitig habe ich heute einen Atmega8 angeschmissen, auch bei ihm
verhält sich das gleich. Es scheint ein Problem mit dem Compiler zu
sein.
Ich nutze AVR-Studio 5 mit AVRGCC V.3.3.1.27
Hmm. Hab den Thread jetzt längere Zeit nicht beobachtet und heute keine
Zeit mehr, da selbst mal ein paar Versuche anzustellen.
Aber, probier mal n auf einen int8_t zu ändern. Also einen Wechsel von
unsigned Datetyp zu signed. Schön langsam kann ich mich mit der These,
dass da im Compiler irgendwas schief läuft anfreunden.
Gedankenspiele!
wert2 ist laut code ein int32_t.
David Menzeln schrieb:> (((int32_t) (F_CPU * 60 / 120000UL))*wert2)
Hier wird ein int32_t mit einem int32_t multipliziert. Das Ergabnis
könnte also im Zahlenraum eines int64_t liegen. Ich gehe davon aus, dass
der Compiler das berücksichtigt.
Das ganze wird aber wert2 zugewiesen. Hier wird implizit ein Cast auf
int32_t gemacht, also die oberen 32 bit weggeworfen. Keine Ahnung, ob
hier auf Vorzeichen geachtet wird.
> wert2 = (((int32_t) (F_CPU * 60 / 120000UL))*wert2)/((n+1)*3);
Hier wird direkt ein int64_t durch ein int16_t dividiert (n = int8_t *
int8_t). Das Ergebnis könnte ebenfalls im Zahlenraum int64_t liegen.
Auch hier wird ein impliziter Cast auf int32_t gemacht. Jedoch an
anderer Stelle.
Gedankenspiel schrieb:> Gedankenspiele!>> wert2 ist laut code ein int32_t.>> David Menzeln schrieb:>> (((int32_t) (F_CPU * 60 / 120000UL))*wert2)>> Hier wird ein int32_t mit einem int32_t multipliziert. Das Ergabnis> könnte also im Zahlenraum eines int64_t liegen. Ich gehe davon aus, dass> der Compiler das berücksichtigt.
Sollte eigentlich nicht sein. Die C-Regeln sind da recht eindeutig. Das
Ergebnis kann nur wieder den Datentyp int32_t haben. Damit sollte
eigentlich die Zuweisung an die Variable keine Rolle spielen, weil damit
keine Casting-Aktion verknüpft ist.
Ich hab da noch was in Erinnerung, dass vor nicht all zu langer Zeit mal
dem Compiler Mixed Arithmetikroutinen mitgegeben wurden, mit denen er
Operationen auch auf Ausdrücken mit gemischten Datentypen durchführen
kann, ohne erst alles auf die gleiche Datentypbasis bringen zu müssen.
Ich könnte mir vorstellen, dass da in dieser avrgcc Version noch
irgendwo ein Wurm drinnen ist.
Karl Heinz Buchegger schrieb:> Hmm. Hab den Thread jetzt längere Zeit nicht beobachtet und heute keine> Zeit mehr, da selbst mal ein paar Versuche anzustellen.
Ich habe gestern die Version von "Datum: 08.01.2013 22:03" (war zu dem
Zeitpunkt die einzige vollständige Version ohne "RAM-Problem") im
Simulator ausprobiert, und konnte keinerlei Problem feststellen. Sowohl
die berechneten Werte, als auch die Ausgaben (natürlich keine echten
Ausgaben, da Simulator, sondern den Inhalt von buffer1 betrachtet) waren
korrekt.
Und nachdem ich nun heute das hier
> Ich nutze AVR-Studio 5 mit AVRGCC V.3.3.1.27
gesehen habe, denke ich, dass sich das Problem mit einem Update in Luft
auflösen wird.
Stefan Ernst schrieb:> Und nachdem ich nun heute das hier>> Ich nutze AVR-Studio 5 mit AVRGCC V.3.3.1.27> gesehen habe, denke ich, dass sich das Problem mit einem Update in Luft> auflösen wird.
Ich denke auch schön langsam, dass es tatsächlich eine Compiler Sache
ist.
Edit:
Ooops
3.3?
Die ist doch himmelalt, oder nicht?
Wird AVR-Studio 5 wirklich mit diesem alten Hadern ausgeliefert?
Bernd schrieb:> David Menzeln schrieb:>> wert2 = (((int32_t) (F_CPU * 60 / 120000UL))*wert2)/;
Nein, das lässt sich natürlich nicht compilieren, das ist leider
passiert, durch die ganze hin und her Bastelei, da ich das umgestellt
habe für den Test, siehe Beitrag. Offensichtlich habe ich die falsche
Datei "zwischengespeichert" um hier anzuhängen. Denke den Schräger weg,
dann lässt es sich compilieren.
Bezüglich Update:
Ich werde mir mal die neueste Version ziehen und es damit probieren.
Ich glaube auch nun wirklich nicht mehr, dass es am Code liegt.
Fabian O. (xfr) hat es ja gestern auch problemlos auf einem XMega laufen
lassen. Und im Simulator scheint es ja auch zu gehen.
Werde trotzdem noch die vorgeschlagenen Sachen versuchen (mehr als
nichts kann es nicht sein) und weiter berichten.
Karl Heinz Buchegger schrieb:> Edit:> Ooops> 3.3?> Die ist doch himmelalt, oder nicht?> Wird AVR-Studio 5 wirklich mit diesem alten Hadern ausgeliefert?
Die Version die ich damals so runtergeladen habe von Atmel
offensichtlich ja (siehe Anhang)
Karl Heinz Buchegger schrieb:> Ooops> 3.3?> Die ist doch himmelalt, oder nicht?> Wird AVR-Studio 5 wirklich mit diesem alten Hadern ausgeliefert?
Ne, so alt nun auch wieder nicht. Das ist die Versionsnummer der
Atmel-Toolchain (nicht des avr-gcc). Da ist AFAIK ein avr-gcc 4.5 drin.
Stefan Ernst schrieb:> Karl Heinz Buchegger schrieb:>> Ooops>> 3.3?>> Die ist doch himmelalt, oder nicht?>> Wird AVR-Studio 5 wirklich mit diesem alten Hadern ausgeliefert?>> Ne, so alt nun auch wieder nicht. Das ist eine Atmel interne> Versionsnummer der Atmel-Toolchain.
grrr.
und ich dachte schon.
Ein schneller Google Scan auf "avrgcc 3.3" brachte Einträge von 2002 zu
Tage :-)
Karl Heinz Buchegger schrieb:> Sollte eigentlich nicht sein. Die C-Regeln sind da recht eindeutig.
Naja, soweit ich mich erinnere ist ein Signed Overflow "undefined
behaviour", was spricht eigentlich dagegen, diese ganze "Wurst" mal in
einzelne Operationen zu zerlegen (mit jeweils passenden Datentypen) und
sich die Zwischenergebnisse auszugeben?
Uncool weil es nicht mehr so wahnsinnig genial aussieht? Zuwenig platz
in der Höhe auf dem Monitor? Festplattenplatz und/oder Variablen sparen?
Wieso wird diese komische Konstrukt mit < 24? Was bedeutet diese "magic
number" und wieso startet nicht einfach der Schleifenzähler bei 24? Die
schleife scheint mir doch sehr suspekt...
Ich hab das mal etwas umgestellt, allerdings ungetestet nur so als
Anregung:
Ich hoffe ich hab das jetzt so frei Hand korrekt umgesetzt, du solltest
versuchen sowas mehr zu strukturieren und Variablen so lakl wie möglich
zu halten, printVal entweder als Funktion oder Makro noch hinzufügen...
Läubi .. schrieb:> Karl Heinz Buchegger schrieb:>> Sollte eigentlich nicht sein. Die C-Regeln sind da recht eindeutig.>> Naja, soweit ich mich erinnere ist ein Signed Overflow "undefined> behaviour",
ok, ich gebe zu, dass ich die Zahlen nicht gecheckt habe. (Sollte man
mal tun)
Allerdings ist der Wertebereich von int32_t schon so groß, dass ich
nicht denke, dass man hier in einen Overflow läuft. Die großen Zahlen
tauchen ja nur bei der Frequenzrechnerei auf und die müsste sich IMHO
eigentlich ausgehen. Zudem sind das alles Konstanten, d.h. da gäbs
sicher eine Warnung vom Compiler.
> was spricht eigentlich dagegen, diese ganze "Wurst" mal in> einzelne Operationen zu zerlegen (mit jeweils passenden Datentypen) und> sich die Zwischenergebnisse auszugeben?
Irgendwo weiter oben gibt es einen Post mit so einem Ansatz.
> Wieso wird diese komische Konstrukt mit < 24? Was bedeutet diese "magic> number" und wieso startet nicht einfach der Schleifenzähler bei 24? Die> schleife scheint mir doch sehr suspekt...
Yep. Ging mir genau so.
Drum hab ich auch angeregt, diesen ganzen Palawatsch mit dem Versatz und
den zusätzlichen Arrays einfach mal zu eliminieren und sich nur auf die
Berechnung zu konzentrieren.
Läubi .. schrieb:> ncool weil es nicht mehr so wahnsinnig genial aussieht? Zuwenig platz> in der Höhe auf dem Monitor? Festplattenplatz und/oder Variablen sparen?
Nein, im Gegenteil. Diese "lange Schlange" finde ich natürlich auch
unübersichtlich bzw. nicht nachvollziehbar. Ich habe mir dazu vorab
Gedanken gemacht und die Rechnung möglichst auf einem Blatt Papier so
zusammengestückelt, um eben Platz bzw. Variablen zu sparen. Lesbarer ist
sicherlich das Schritt für Schritt zu machen.
Läubi .. schrieb:> Was bedeutet diese "magic> number"
Offensichtlich erkennt man noch, dass es sich im Grunde um eine
Frequenzberechnung handelt. Ziel ist es, diese ab einer bestimmten
Frequenz etwas zu manipulieren.
Mein Weg hierzu war, eben, diese Manipulation erst ab einer bestimmten
Frequenz zu machen, ab der "magic number" 24. Das Programm addressiert
über den einen Tabellenindex, der sich aus der Frequenz ergibt, dann
eben den Wert, mit welchem manipuliert werden soll. Liegt dieser Index
bei <=24, soll eben nur mit dem "Standard" Verschiebewert manipuliert
werden. Spielt im Grunde aber keine Rolle. Wollte hier nur etwas Licht
ins dunkle bringen zum Nachvollziehen.
Dass dies fehlt
1
((n+1)*3)
habe ich gesehen und ergänzt.
Verzeiht mir, dass ich keine /n und /r nutze, aber mein Terminalprogramm
(hterm) zeigt diese Umbrüche nicht an, deswegen gebe ich ein paar
Leerzeichen aus, um das zu trennen.
Ich habe das ganze durch AVR-Studio 5 gejagt und zusätzlich mal meinen
alten Laptop angeschmissen, wo AVR Studio 4 installiert ist.
Der Compiler in AVR Studio 4 rechnet richtig mit gleicher
Optimierungseinstellung -O1. AVR Studio 5 tut es nicht.
David Menzeln schrieb:> Der Compiler in AVR Studio 4 rechnet richtig mit gleicher> Optimierungseinstellung -O1. AVR Studio 5 tut es nicht.AVR Studio ist nur die Entwicklungsumgebung. Entscheidend ist die
Version des avr-gcc.
Schau jeweils im Output-Fenster nach, unter welchem Pfad der jeweilige
avr-gcc liegt und ruf ihn in einem CMD-Fenster mit der Option --version
auf. Beispiel
1
"C:\Programme\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe" --version
> Verzeiht mir, dass ich keine /n und /r nutze, aber mein Terminalprogramm> (hterm) zeigt diese Umbrüche nicht an, deswegen gebe ich ein paar
Versuche es mal mit
uart_put(13);uart_put(10);
oder heißt es uart_putc oder uart_putch?
zur Ausgabe meinte ich, es reicht doch so:
pgmWert pgmVerschoben frequenzWert finalerWert (diese Zeile nur
einmal)
-185 -65 8000 -6933
-185 -65 8000 -6666
-184 -64 8000 -6320
-184 -64 8000 -6095
etc.
Probier mal statt
for (uint8_t n=0; n<ANZAHL2+25; n++){ --->
for (uint16_t n=0; n<ANZAHL2+25; n++){ oder
for (uint32_t n=0; n<ANZAHL2+25; n++){
und dann mal statt
int16_t pgmWert; ---> int32_t pgmWert;
Ich weiß gar nicht, was dieses ganze "versuch mal" und "mach mal" hier
überhaupt noch soll. Studio5 hat erwiesenermaßen diverse Bugs, sowohl in
der IDE, als auch in der enthaltenen Toolchain. Er soll einfach auf 6
updaten, und wenn es dann noch Probleme gibt, DANN wird es wieder
interessant.