Hallo,
ich würde gerne mal wissen wieviele Takte meine Routine benötigt. Ich
takte einen Schrittmotor und berechne zu jedem Schritt den neuen
Matchwert des Timer1 16 Bit im fast PWM-Modus. Bei größter
Winkelgeschwindigkeit hätte ich zwischen jeden Interrupt ca. 800 Takte
in denen er alles neu berechnet und noch einige andere Sachen macht.
Atmega8 16MHz
Inhalt der Routine:
{
schrittWeite++;
if (schrittWeite < endeRampe)
{
Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));
ICR1 = Cn;
}
else //Endesequenz einleiten
}
Ich hoffe ihr könnt mir da helfen. Mich würde auch echt mal
interessieren wie sowas berechnet wird.
Gruss
Frank
Um die Zeit zu Messen einfach vor der zu messenden Routine PIN auf High
legen und danach auf Low Oszi ran und dann hast du deine zeit mit
eventuellen Jittern und anderem hässlichem Kram. Oder du guckst dir nach
dem compilieren den Maschinencode an schlägst die Befehle nach wieviele
Takte die brauchen und addierst die Anzahl der Takte.
Die Oszi-Variante geht schneller.
Ja das hat eine Bedeutung denn floating point Operationen dauern immer
länger als integer Operationen. Die Frage wäre auch noch was für einen
Prozessortypen du verwendest und wie der getaktet ist.
Hi, danke für die Antworten.
Also, ich habe einen myAVRUSB-Board mit einem Atmega8 16PU, statt der
3,6864MHz habe ich einen 16 Mhz draufgelötet.
Habe gerade kein Oszi da. Maschinencode...oha ;-)
Gruss
Frank
Stefan Kunz schrieb:
> Um die Zeit zu Messen einfach vor der zu messenden Routine PIN auf High> legen und danach auf Low Oszi ran und dann hast du deine zeit mit> eventuellen Jittern und anderem hässlichem Kram. Oder du guckst dir nach> dem compilieren den Maschinencode an schlägst die Befehle nach wieviele> Takte die brauchen und addierst die Anzahl der Takte.> Die Oszi-Variante geht schneller.
Yep. Außerdem ist im Handbuch Assembler-Befehle nachschlagen nicht so
schön wie im Labor mit dem Oszi zu werkeln :-)
^^ Stimmt die Zeit benutzt man lieber für andere Sachen. Man könnte auch
den Timer des AVR nehmen. Zwar dann ein wenig unhandlicher weil man mehr
Quellcode schreiben muss und dadurch ein etwas ungenaueres Ergebnis
bekommt abber möglich.
Wenn du mit den 800 Takten nicht zurecht kommst solltest du überlegen
weg von den double-Werten zu gehen. Integer-Berechnungen sind um ein
vielfaches schneller besonders wenn man im "nativen" Zahlenbereich des
Prozessors bleibt. Außerdem ist ein Oszi eigentlich Pflicht wenn man was
mit µC.
Man kann natürlich auch im AVR-Studio im Debugger einen Breakpoint an
den Anfang der Routine setzen, sich den Counter merken, bis ans Ende der
Routine durchsteppen (oder durchlaufen lassen) und mit dem Endstand
vergleichen. AVR-Studio ist sogar so freundlich und rechnet das in eine
Zeit um, wenn man ihm nur die Taktfrequenz des Prozessors richtig
einstellt.
-ich programmiere mit Xcode auf einem Macbook und kann AVR-Studio nicht
laufen lassen.
-Assembler programmieren kann ich nicht.
-Ein Assembler Handbuch habe ich auch nicht.
Bleibt also nur die Oszi - Methode, dann werde ich das mal probieren.
Gruss
Frank
Ok, eine Frage hätte ich da noch.
Wenn ich einen Pin toggle um die Zeit zu messen, wie viele Takte brauche
ich für das Toggeln, damit ich das am Ende subtrahieren kann?
z.B: PORTB = PINB^(1 << PB1);
Gruss
Frank
>Wenn ich einen Pin toggle um die Zeit zu messen, wie viele Takte brauche>ich für das Toggeln, damit ich das am Ende subtrahieren kann?
Ignoriere es einfach. Der Rest dauert wesentlich länger.
Macht also kaum was aus.
Mir ist nur überhaupt nicht klar, warum man das in floating point
rechnen sollte.
Edit:
und mit emulierten floats brauchst du hier garantiert locker mehr als
800 Tajkte, wenn du das in Inegern rechnen würdest, wärens vielleicht
50.
>(2 * Cn-1)
das ist auch leicht irreführend, bist du sicher, dass das das macht, was
du willst?
Da nichts in der Funktion von äusseren Ereignissen abhängt, kann man das
auch ganz schlicht durch den Simulator vom Studio jagen. Der zeigt die
Takte an.
bei so gestellten sachen muss man immer aufpassen, dass man sinnvoll
volatile einsetzt, so das der compiler weder alles wegoptimiert, noch
durch ein falsches volatile gar nicht optimiert.
Hat mich schon manchmal fast den Verstand gekostet, wenn ich irgend was
messen wollte.
Hi an Alle,
danke erstmal für die Antworten.
Vlad-> ich dachte mit den Float-Werten bin ich auf der richtigen Seite.
(2 * Cn-1) ist soweit richtig, ich habe alles vorher ausgerechnet
und
komme genau am ende der Rampe auf meine Frequenz.
Alle Variablen sind Global und als Volatile gekennzeichnet,
wollte
hier nur nicht alles dazuschreiben.
A.K.-> ich arbeite mit einem Mac und habe kein AVR Studio.
So, werde gleich mal mit dem Oszi ein abgespecktes Programm messen. Ich
gebe dann mal das Ergebnis bekannt.
Gruss
Frank
Nur so als Größenordnung: Eine float-Addition benötigt um die 180 Takte,
eine Division ca. 500, usw.
Damit reichen 800 Takte für die ganze Berechnung bei weitem nicht aus.
Oliver
FrankH schrieb:
> Hi an Alle,> danke erstmal für die Antworten.> Vlad-> ich dachte mit den Float-Werten bin ich auf der richtigen Seite.
Aufpassen.
float ist nicht automatisch die Lösung aller Probleme.
Mit naivem Einsatz von float kannst du dir ganz schnell einen komplett
neuen Sack an Problemen aufmachen, an die du vorher noch nicht mal im
Traum gedacht hast. Und Rechenzeit ist da noch das kleinere Übel.
Oder wenn man Pech hat fallen sie einem erstmal gar nicht auf.
Bei Integer Berechnung kann man die Zahlen bequem anpassen, außerdem
fallen dort Überläufe und nicht berücksichtbare kleine Zahlenbreiche
schneller auf als bei Float.
Der Informationsgehalt der verschiedenen Zahlen Defenetionen bei
gleicher Bitanzahl ist eh gleich. Float verleitet einfach dazu es zu
benutzen um weniger denken zu müssen oder wenn man Ressourcen ohne Ende
hat.
Ok, ihr habt recht und ich ein Problem.
ich brauche ca. 500µs für die Berechnung.
bei 16MHz -> 2 Takte je Periode -> 1 Takt=31,25ns
500µs/31,25ns=16000 Takte
mir stehe bei größter Winkelgeschwindigkeit im fast PWM-Modus
aber nur 50µs zwischen den Takten bzw. eher 40µs zur verfügung.
Ich kann also bis 1280, besser aber so 800 Takte verwenden.
ich muss aber mit großen Zahlen rechnen.
mein SchrittZähler geht bis 11000 Schritte und
Cn kann ja bis 0xffff zählen und
n und m können theoretisch auch Werte bis 11000 annehmen.
Wie komme ich denn jezt mit Integerwerten zurecht, da fehlt mir gerade
das Verständnis für.
Ich hoffe ihr könnt mir da Tipps geben.
Gruss
Frank
So wie ich das mit dem kleinen Ausschnitt sehe, muss schrittWeite und
endeRampe schon mal nicht float sein.
Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));
das müsste man jetzt mal analysieren. Was ist die mathematische Idee
hinter dieser Formel, wie kommt sie zustande? Was sind n und m? Wieviele
Kommastellen benötigst du für Cn, damit sich der Fehler bei einer Rampe
nicht zu unwägbar grossen Werten aufschaukelt.
Na die Berechnung :
Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));
sollte doch wohl noch in Ganzzahl gehen. Bei der division das "/" durch
ein "div" ersetzen.
aha schrieb:
> Na die Berechnung :> Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));> sollte doch wohl noch in Ganzzahl gehen.
Nicht unbedingt.
Das ist offensichtlich eine iterative Berechnung. Wenn man zuviele
Nachkommastellen unter den Tisch fallen lässt, schaukeln sich
Ungenauigkeiten auf.
> Bei der division das "/" durch> ein "div" ersetzen.
In Pascal vielleicht. Das hier ist aber C.
"div" funktioniert mit C irgendwie nicht, ist mir auch nicht bekannt.
ok,ich versuche das mal zu erklären.
Grundlage:
Mit dem Schrittmotor verfahre ich einen Tisch an meinem Linearteststand.
Der Schrittmotor hat eine eingestellte Auflösung von 1000 Schritte die
Umdrehung.
Der Verfahrweg ist auf 1,21m begrenzt und das Antriebsrad hat r=0,0175m
bzw. U=0,11m.
Mein Verfahrweg beträgt demnach 11000 Schritte.
Formel:
{
//aktueller Schritt auf dem Verfahrweg
schrittWeite++;
//endeRampe begränzt die die lineare beschleunigung
if (schrittWeite < endeRampe)
{
//Cn ist der aktuelle berechnete Zählwert für Timer1
//Cn-1 ist demnach der vorherige Zählwert
//n ist eigentlich die schreittWeite, brauche ich aber wegen
//mehrfachbeschleunigungen in einem Fahrprofil
//m brauche ich um von einer Geschwindigkeit V auf 0 zu verzögern
//m entspricht der Schritt in dem V = 0 sein soll
Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));
//ICR1 ist der Zählwert des Timer1
ICR1 = Cn;
}
else //Endesequenz einleiten
}
Die Formel habe ich unter anderem von
AVR446: linear speed control of stepper motor
oder auch hier
http://www.embedded.com/columns/technicalinsights/56800129?_requestid=208248
Gruss
Frank
Nur mal als Frage
Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));
ICR1 = Cn;
ICR1 ist doch sicherlich ein Register im AVR. Mich wundert, dass das so
einfach hinnimmt das dort eine float-Zahl reingeschrieben werden soll.
Ich kann mich auch täuschen, da ich bis jetzt nur mit ARM Erfahrung
habe,
aber das sollte eigentlich funktionieren, da dass der Wert des Timers
ist bis wohin er zählen soll und eine float Zahl, in dem Fall als double
deklariert sollte eigentlich zu einem falschen Ergebnis führen.
FrankH schrieb:
> //n ist eigentlich die schreittWeite, brauche ich aber wegen> //mehrfachbeschleunigungen in einem Fahrprofil> //m brauche ich um von einer Geschwindigkeit V auf 0 zu verzögern> //m entspricht der Schritt in dem V = 0 sein soll
n und m sind mir noch unklar.
Was sind so typische Wertebereiche für die beiden?
>oder auch hier>http://www.embedded.com/columns/technicalinsights/...
"Oder auch hier" beginnt mit:
>A new algorithm for stepper-motor acceleration allows speed profiles to >be
parameterized and calculated in real time. This algorithm can run on a >low-end
microcontroller using only simple fixed-point arithmetic >operations and no data
tables. It develops an accurate approximation for >the timing of a linear ramp
with constant acceleration and deceleration.
Der Algorithmus ist also explizit für die Verwendung von
Fixed-Point-Arithmetik geeignet. Keine floats erforderlich.
Oliver
> (2 * Cn-1) ist soweit richtig, ich habe alles vorher ausgerechnet
ok, die schreibweise/formatierung lässt vermuten, dass Cn-1 als erstes
ausgerechnet werden soll.
FrankH schrieb:
> Die Formel habe ich unter anderem von
Da hast sie aber nicht richtig übernommen.
Beachte, dass C mit dem Index (n - 1) nicht dasselbe ist, wie Cn - 1
Die Umsetzung lautet ganz einfach
Cn = Cn - ((2 * Cn)/( 4 * (n - m) + 1));
Und freundlicherweise wird im Artikel auch erwähnt, dass es sich um 24.8
Fixed Point Arithmetik handelt. Also 8 Bit für den Nachkommaanteil, oder
anders ausgedrückt: Alles mal 256
Hallo Karl Heinz,
eigentlich steht dort das C mit dem Index(n-1), zB. wenn x = (n-1) wäre,
dann lautet die Formel:
Cn = Cx - ((2 * Cx)/(4 * (n - m) + 1));
ich habe auch extra nochmal nachgesehen, oder habe ich Tomaten auf den
Augen ;-) (kleiner Scherz)
Aber ihr habt ja alle recht, ich kann natürlich mit Ganzzahlen rechnen,
das beschleunigt ja ungemein.
Frage:
Wenn ich mit 16Bit Werten rechne, dann komme ich von der Zeit in meiner
Interrupt-Routine sehr gut hin, aber wie ist es denn, wenn im jetzigen
Beispiel Cx den Wert 50000 hat und ich es mit 2 multipliziere (2 * Cx)
Wäre es dann nicht ein 32Bit Wert?
Also der Gesamtwert der Bruchrechnung ergibt ja wieder ein Wert der
16Bit entspricht. Im Bruch selber werden Werte berechnet die über 16Bit
liegen.
Rechnet der µC trotzdem richtig oder können dort noch Tricks angewendet
werden?
Gruss
Frank
>Und freundlicherweise wird im Artikel auch erwähnt, dass es sich um 24.8>Fixed Point Arithmetik handelt.>Frage:>Wenn ich mit 16Bit Werten rechne, dann komme ich von der Zeit in meiner>Interrupt-Routine sehr gut hin,
Antwort: Das passt halt nicht zusammen :-)
Dummerweise dauert die 32-Bit-Integer-Rechnerei (24.8 ist 32 bit)
(erheblich) viel länger als 16 bit. Da musst du nochmals über das
gesamte Konzept nachdenken.
Oliver
Hi ich noch einmal,
danke wieder für die gegebenen Antworten und Tipps.
Stand der Dinge:
Mit den 32Bit-Werten liege ich auch gerade noch so in meinem geforderten
Bereich.
Ich habe es noch einmal nachgerechnet und gemessen.
zwischen jeden Auslösen des Interrupts im fast PWM Modus liegen 54µs bei
größter benötigter Winkelgeschwindigkeit. Die Berechnung der Formel mit
32Bit Werten bräuchte ca. 44µs, sind also noch 10µs "Luft".
ich würde aber wenn es geht noch ein wenig mehr Zeit raus holen. Wäre es
nicht schneller wenn ich die Berechnung im Assembler-Code schreibe?
Wenn ja, könnte mir jemand die folgende Berechnung mal als
Assembler-Code schreiben
schrittWeite++;
if (schrittWeite < endeRampe)
{
Cn=Cn-1 - ((2 * Cn-1)/( 4 * (n - m) + 1));
ICR1 = Cn;
}
Müsste ich noch irgendwas includen oder kann ich ein Assembler Codeteil
in meinem C-Code einbinden?
Ich würde gerne mal sehen ob es da Unterschiede in der Berechnungszeit
gibt.
Gruss
Frank
ich glaube nicht das asm hier viel schneller ist, da du alles mit 32bit
machen willst ist der asm-code nicht garde überschaubar und auch recht
kompleex im vergleich zu dem C code.
Schau doch mal in die lss Datei, dort siehst du den code den den
compiler erzeugt hat.
Wichtig wäre mal zu wissen, ob die variabeln nicht etwas volatil sind.
So, habe mich mal hier angemeldet.
Peter schrieb:
> Wichtig wäre mal zu wissen, ob die variabeln nicht etwas volatil sind.
Ja, die Variablen sind global und alle volatile. Hat das irgendwelche
Auswirkungen? Ausser das ich sie in einem Interrupt verwenden kann.
Gruss
Frank
> Ja, die Variablen sind global und alle volatile. Hat das irgendwelche> Auswirkungen
ja, und zwar gute und schlechte.
Die schlechte ist, das sie jedes mal aus dem speicher gelesen wird wenn
du sie verwendest.
Mache mal den vergleich und schau dir den asm code an. Einmal mit
volatil und einmal ohne.
Und dann am besten das mal als vergleich
{
int32_t tmp = Cn;
tmp =tmp -1 - ((2 * tmp -1)/( 4 * (n - m) + 1));
ICR1 = tmp ;
Cn = tmp;
}
Hi Peter,
Peter schrieb:
> Und dann am besten das mal als vergleich> {> int32_t tmp = Cn;> tmp =tmp -1 - ((2 * tmp -1)/( 4 * (n - m) + 1));> ICR1 = tmp ;> Cn = tmp;> }
alles klar, werde ich morgen gleich testen.
Gruss
Frank
Als erstes muss ich mich mal bei den Leuten hier bedanken, ihr seit echt
hilfsbereit. Wenn ich mich weiter eingearbeitet habe, hoffe ich auch
anderen hier im Forum genauso helfen zu können.
Peter schrieb:
> Mache mal den vergleich und schau dir den asm code an. Einmal mit> volatil und einmal ohne.
Leider kenne ich mich mit dem Assembler - Code nicht aus.
Ich habe aber deinen Tipp mit der temporären Variable umgesetzt und
konnte damit 1 µs gewinnen.
Danke dafür.
Zur Zeit ist m eine globale volatile Variable, im nächsten Schritt
wollte ich eine Struct anlegen, in dem wichtige Werte ( zB. m ) für die
einzelnen Phasen meiner Fahrrampe hinterlegt sind. Meine Fragen hierzu
wären:
Kann ich aus einem Interrupt auf eine Struktur zugreifen?
Wenn ja, muss ich die Variablen auch mit einem volatile kennzeichnen?
Gibt es dabei Wichtiges zu beachten?
Gruss
Frank
> Leider kenne ich mich mit dem Assembler - Code nicht aus.> Ich habe aber deinen Tipp mit der temporären Variable umgesetzt und> konnte damit 1 µs gewinnen.> Danke dafür.
Dann stellt doch den asm code einfach mal hier rein.
ein Struct ist erstmal eine normale variabel es gibt dafür erstmal keine
einsränkung was Interupts angeht.
Wie es sich aber mit volatil verhählt kann ich auch nicht sage. Ob die
ganze struct oder nur einzelene members volatil sein sollten.
Ich finde es eh sinvoller sich erstmal mit asm auf einem µC zu
beschäftigen, damit versteht man besser warum mancher C-Code nicht
optimal ist.
Ja würde ich gerne, nur müsste ich wissen welcher der asm-Code ist? ;-)
Ist das main.hex oder main.0, sorry ich programmiere auf dem Mac mit
Xcode und kenne mich noch nicht wirklich aus.
Gruss
Frank
Ich kenn es nur vom GCC da wird ein lss file erzeugt.
Schau mal in alle Dateien rein. Asm sollte so in der art ausehen.
ldi temp1, 1<<LED
out led_ddr, temp1
ldi temp1, $00
out key_ddr, temp1
ldi temp1, $FF
out key_port, temp1
mov key_old, temp1
Bevor man jedem einzeln die Grundlagen mühsam erklärt, wäre es
nicht effizienter, sich erst mal die einschlägigen Tutorials
(z.B. hier im Forum) reinzupfeifen, und dann noch offene Fragen
erklären lassen?
Klaus Wachtler schrieb:
> Bevor man jedem einzeln die Grundlagen mühsam erklärt, wäre es> nicht effizienter, sich erst mal die einschlägigen Tutorials> (z.B. hier im Forum) reinzupfeifen, und dann noch offene Fragen> erklären lassen?
Hi,
ich glaube nicht das ich ein Anfänger bin dem man noch die Grundlagen
erklären muss nur weil ich mich noch nicht mit Assembler programmieren
beschäftigt habe.
Gruss
Frank
FrankH schrieb:
> Mit den 32Bit-Werten liege ich auch gerade noch so in meinem geforderten> Bereich.
Was hast du jetzt alles auf 32 Bit gehoben?
Frage: Müssen m und n 32 Bit sein, oder reichen dort auch 16 Bit?
Cn wird wohl auf 32 Bit bleiben müssen. Obwohl: Du benutzt ja zur Zeit
gar keine Fixpunkt-Arithmetik!
> ICR1 = Cn;
Sonst müsste hier sowas in der Art von
ICR1 = Cn / 256;
stehen.
Daher nochmal die Frage: Welche Werte (Wertebereich) können Cn, n und m
annehmen. Das ist insofern wichtig um entscheiden zu können, welche
Teile der Berechnung unbedingt in 32 Bit und welche zb noch in 16 Bit
erledigt werden können. Zb. kann ich mir gut vorstellen, dass es kein
Problem ist
n - m
als 16 Bit berechnen zu lassen, solange n und m immer im 16 Bit
Wertebereich ist.
So, ich habe das mal hier auf dem Windowscomputer in Notepad
kompilliert, dort waren dann auch die gewünschten Files. Unter Xcode
konnte ich die nicht finden.
Gruss
Frank
Frank H. schrieb:
> ich glaube nicht das ich ein Anfänger bin dem man noch die Grundlagen> erklären muss nur weil ich mich noch nicht mit Assembler programmieren> beschäftigt habe.
So wie es aussieht, bist du im Teilbereich Fixpunkt-Arithmetik noch
Anfänger.
sorry, ich wollte nicht beleidigend werden.
Manches steht aber halt auch in der Doku zum jeweiligen Compiler
etc. (z.B. welche Dateien welche Bedeutung haben und sowas).
Frank H. schrieb:
> Hallo Karl Heinz,> Cn ist 32Bit> n u. m habe ich 16Bit> alle weiteren Variablen die die Schrittzahl representieren sind 16Bit.
Habs mir gerade aus dem Assembler zusammengereimt.
hier ist die bewusste Sequenz
Karl heinz Buchegger schrieb:
> So wie es aussieht, bist du im Teilbereich Fixpunkt-Arithmetik noch> Anfänger.
Stimmt, leider bin ich kein Informationsschwamm der alles in ms
aufsaugen kann. ;-)
Gruss
Frank
> So, ich habe das mal hier auf dem Windowscomputer in Notepad> kompilliert
Wusste gar nicht das das notepas Kompileren kann...
aber die lss Datei ist die richtige. Daran sieht man recht deutlich das
man da nicht mehr viel optimieren kann. Die meiste zeit geht bei der
Division drauf der rest ist vernachlässigbar.
Wenn du also nicht die Division wegbekommt, geht da nichts mehr
schneller.
Klaus Wachtler schrieb:
> sorry, ich wollte nicht beleidigend werden.>> Manches steht aber halt auch in der Doku zum jeweiligen Compiler> etc. (z.B. welche Dateien welche Bedeutung haben und sowas).
Kein Problem.
Gruss
Frank
Peter schrieb:
>> So, ich habe das mal hier auf dem Windowscomputer in Notepad>> kompilliert> Wusste gar nicht das das notepas Kompileren kann...
Programmers Notepad [WINAVR], dann oben auf Tools und dort hast
du(zumindest ich hier)
[WINAVR] Make All
[WINAVR] Make Clean
[WINAVR] Program
Gruss
Frank
Hallo Leute,
bis jetzt bin ich gut vorangekommen. Wie in dem oben beschrieben Artikel
benutze ich jetzt die 24.8 Arethmetik (zumindest versuche ich das),
klappt auch ganz gut nur bei der Verzögerungsrampe habe ich ein Problem.
Kann auch sein das ich den englischen Text nicht richtig lesen kann.
n ist der aktuelle Schritt
m ist das Ende der Rampe
Bei der Beschleunigung ist m=0, bei der Verzögerung bekommt m den
Endwert der Fahrstrecke zugewiesen (m > n).
temp = temp-((2*temp+rest)/(4*( n-m )+1));
rest=((2*temp+rest)%(4*(n-m)+1));
Kann es sein das rest=(positiver Wert)%(negativer Wert) ein generelles
Problem ist?
Die Berechnung liefert mir in einem C-Code auf der Konsole die richtigen
Werte, jedoch im µC funktioniert das nicht.
Ich habe auch versucht den negativen Wert zu negieren (-(negativer
Wert)), hat mir aber nicht geholfen. Vielleicht hat jemand einen Tipp.
Gruss
Frank
Frank H. schrieb:
> Die Berechnung liefert mir in einem C-Code auf der Konsole die richtigen> Werte, jedoch im µC funktioniert das nicht.
Lass doch mal dein Programm ansehen, wie es jetzt aussieht.
Langsam müsstest du schon begriffen haben, dass auch Details wichtig
sein können, wie zb die verwendeten Datentypen.
Ein Unterschied zwischen PC und µC ist zb, dass ein int auf dem PC
heutzutage meist 32 Bit ist, während er auf deinem AVR nur 16 Bit ist.
Das kann den alles entscheidenden Unterschied machen, wenn während einer
Berechnung ein Zwischenergebnis entsteht, welches überläuft.
> Ich habe auch versucht den negativen Wert zu negieren (-(negativer> Wert)), hat mir aber nicht geholfen. Vielleicht hat jemand einen Tipp.
Der einzig sinnvolle Tip lautet:
Verschaff dir eine Möglichkeit, wie du Zwischenergebnisse irgendwo
anzeigen lassen kannst. Momentan stocherst du im Nebel. Das führt zu
nichts, wenn du anstatt einer roten eine blaue Stange zum stochern
benutzt. Du musst den Nebel beseitigen! Das bedeutet nun mal: die
verwendeten Zahlenwerte und Zwischenergebnisse müssen her um sie
studieren zu können.
Oha,
am liebsten würde ich meine letzte Frage zurückziehen ;-(
Der Fehler war so simpel, das es mir schon peinlich ist.
Da habe ich doch seit gestern das Problem gesucht und erst jetzt
gefunden.
Wie soll die Variable rest auch negative Werte annehmen können, wenn es
eine uint16_t - Variable ist. Ich habe den Code trotzdem mal angehängt.
tztztztz
Karl Heinz-> Du hast natürlich recht, ich habe auch angefangen mein
Programm in Teilprogramme zu spalten die ich nach einer Veränderung erst
teste. Auch ist mir nun klar wie wichtig die Datentypen sind, ich denke
das ich mich da langsam aber sicher hineinfuxen werden.
Gruss vom ständig Lernenden
Frank
;-)
Es gibt da übrigens im AVR-studio eine coole funktion: nennt sich
simulator.
würde ich mal ausprobieren, kann man auch im einzelschritt durchs
c-programm und man kann die prozessorzyklen dabei zählen, sogar in zeit
umgerechnet sehen
>Er programmiert auf einem Mac.
Die Auswahl des richtigen Werkzeugs war schon immer entscheidend. Auch
wenn ein Mac ein toller Rechner ist, mit einem Simulator wäre er jetzt
schon längst fertig.
Oliver