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
Achso, ich weiß nicht ob es von Bedeutung ist aber: double schrittWeite; double endeRampe; double Cn; double n; double m; 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.
ICR1 ist für den Compiler ein volatile unsinged int, und dem darf man ohne weiteres einen float zuweisen. Das castet der automatisch richtig. Oliver
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).
Hallo Karl Heinz, Cn ist 32Bit n u. m habe ich 16Bit alle weiteren Variablen die die Schrittzahl representieren sind 16Bit. Gruss Frank
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
1 | temp = temp-((2*temp)/(4*(schrittZaehler - endeRampe3)+1)); |
2 | 14c: 20 91 60 00 lds r18, 0x0060 |
3 | 150: 30 91 61 00 lds r19, 0x0061 |
4 | 154: e0 91 71 00 lds r30, 0x0071 |
5 | 158: f0 91 72 00 lds r31, 0x0072 |
6 | 15c: c8 01 movw r24, r16 |
7 | 15e: b7 01 movw r22, r14 |
8 | 160: 66 0f add r22, r22 |
9 | 162: 77 1f adc r23, r23 |
10 | 164: 88 1f adc r24, r24 |
11 | 166: 99 1f adc r25, r25 |
12 | 168: 2e 1b sub r18, r30 |
13 | 16a: 3f 0b sbc r19, r31 |
14 | 16c: 22 0f add r18, r18 |
15 | 16e: 33 1f adc r19, r19 |
16 | 170: 22 0f add r18, r18 |
17 | 172: 33 1f adc r19, r19 |
18 | 174: 2f 5f subi r18, 0xFF ; 255 |
19 | 176: 3f 4f sbci r19, 0xFF ; 255 |
20 | 178: 40 e0 ldi r20, 0x00 ; 0 |
21 | 17a: 50 e0 ldi r21, 0x00 ; 0 |
22 | 17c: 2c d2 rcall .+1112 ; 0x5d6 <__udivmodsi4> |
23 | 17e: c9 01 movw r24, r18 |
24 | 180: da 01 movw r26, r20 |
25 | 182: e8 1a sub r14, r24 |
26 | 184: f9 0a sbc r15, r25 |
27 | 186: 0a 0b sbc r16, r26 |
28 | 188: 1b 0b sbc r17, r27 |
29 | 18a: 07 c0 rjmp .+14 ; 0x19a <__vector_5+0xfe> |
Das sieht eigentlich schon ziemlich gut aus. Ich denke nicht, dass da noch viel geht.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.