Hallo in die Runde. Ich möchte ein sinusförmiges Ausgangssignal (Grundschwingung) an meinen beiden PWM-Ausgangspins meines Atmega8A erzeugen. Ich verwende den Phase-Correct Modus, 8-Bit Timerauflösung, sowie eine 256-stellige Lookup-Tabelle. Mein Problem: Ich möchte innerhalb 1s einen Hochlauf meiner Ausgangsfrequenz auf den maximalen Wert erreichen. Hierzu Teile ich meine max. Schrittweite (für die Indexauswahl der Lookup-Tabelle) durch meine PWM Frequenz und erhöhe dann bei jedem Timerüberlauf meine Schrittweite bis zum max. Wert. Leider erreiche ich die max. Schrittweite nicht, d.h. meine Ausgangsfrequenz ist deutlich kleiner als gewünscht. Vielleicht erreiche ich auch die max. Schrittweite und das Problem liegt an einer anderen Stelle. Leider weiß ich nicht wo der Fehler im Code liegt. (Ich vermute mal, dass die Umwandlung von 16-Bit in 32-Bit Variablen und umgekehrt die Ursache ist). Bei fester Schrittweite funktioniert das Ganze einwandfrei. Variablen i und j bleiben ungenutzt. Ich habe sie im nachhinein entfernt.
:
Bearbeitet durch User
Debuggen sollte ein Teil der Entwicklung sein. DH Debuggen muss von Begin weg eingeplant werden. Was wurde diesbezueglich unternommen ?
Ich habe das ganze mit dem Atmel Studio 6 erzeugt. Mit dem Software Debugger kann ich allerdings nicht feststellen was in meiner ISR passiert. Debug-Maßnahmen habe ich nicht eingeplant.(So tief bin ich nicht in der Programmiermaterie drin)
Kann die niedrige Ausgangsfrequenz auch daran liegen, dass ich mit 32Bit-Variablen in der ISR rechne?
Martin Kreiner schrieb im Beitrag #3340776:
> Wo wird denn der phaseaccu hochgezählt?
Am Schluss der ISR am Programmende
Wenn ich das jetzt richtig gesehen habe: Der Timer 1 zählt ohne Prescaler von 0 bis 255, dann wieder runter -> Dann kommt der Overflow-Interrupt. (2 * 255) / 3686000 => alle 138 Mikrosekunden. Um die ISR abzuarbeiten werden schon mal mindesten 186 Mikrosekunden gebraucht. Da beißt sich was.
Peter A. schrieb: > Leider weiß ich nicht wo der Fehler im Code liegt. (Ich vermute mal, > dass die Umwandlung von 16-Bit in 32-Bit Variablen und umgekehrt die > Ursache ist). Das denke ich ehrlich gesagt nicht. Ich denke, du hast dich da irgendwo bei der Mathe verhaut. Einen Overflow bei einem Zwischenergebnis nicht bedacht, oder das bei einer Integerdivision keine Kommastellen anfallen, oder sowas in der Richtung. Unglücklicherweise ist der Code etwas ... unübersichtlich und ich hab jetzt ehrlich gesagt auch nicht die Nerven und die Lust um den Code erst mal soweit aufzudröseln um die hier programmierte Idee erkennen zu können, bzw. ob und wenn ja wo bei der Umsetzung der Idee Fehler gemacht wurden, bzw. ob und wo da jetzt arithmetische Probleme auftauchen. Die PWM ist ja nur Nebenschauplatz. Das was dir Sorgen macht, ist doch die Veränderung des OCR Wertes. Das kannst du aber mit einem Testprogramm auf dem PC genausogut erledigen. Denn letzten Endes geht es ja nur darum die Veränderung einiger Kennzahlen nachzuvollziehen.
Der Teil hier
1 | highbyte = (samplesize/comparechange)<<8; // Highbyte der Variable Stepsizemax |
2 | if(samplesize%comparechange>1) // Bedingung, nach Schrittweite |
3 | {
|
4 | lowbyte1 = (samplesize%comparechange*100/comparechange); |
5 | }
|
6 | else
|
7 | {
|
8 | lowbyte1 = (samplesize*100/comparechange); |
9 | }
|
10 | lowbyte0 =((lowbyte1/10)<<4) | (lowbyte1%10); // Zusammensetzen des Lowbytes der stepsizemax Variable |
11 | stepsizemax = highbyte|lowbyte0; |
erscheint mir zb reichlich suspekt. Was immer auch hier ausgerechnet wird, das lässt sich doch sicherlich auch einfacher berechnen.
Martin Kreiner schrieb: > Um die ISR abzuarbeiten werden schon mal mindesten 186 Mikrosekunden > gebraucht. Da beißt sich was. Wie kommst du jetzt konkret auf die 186 Mikrosekunden? In der ISR werden lediglich meine Comparewerte inkrementiert. Mein Timer braucht 138us je Durchlauf meiner Werte. Die ISR selbst kann nicht solange brauchen.
Peter A. schrieb: > In der ISR werden lediglich meine Comparewerte inkrementiert. > Mein Timer braucht 138us je Durchlauf meiner Werte. Die ISR selbst kann > nicht solange brauchen. Nun ja, wenn du meinst.....
1 | if((stepsizecnt/10000)<(stepsizemax)) |
Alleine diese in deinen Augen vielleicht lächerliche Abfrage verheizt
schon mal 163 Mikrosekunden.
> Wie kommst du jetzt konkret auf die 186 Mikrosekunden?
Für soetwas ist der eingebaute Simulator perfekt.
Karl Heinz Buchegger schrieb: > Der Teil hier > erscheint mir zb reichlich suspekt. > Was immer auch hier ausgerechnet wird, das lässt sich doch sicherlich > auch einfacher berechnen. Hier wird meine maximale Schrittweite ausgerechnet. Also konkret der Index meiner samples-Werte. Bsp.: f_pwm = 7200, samples=256-Werte, fout=50: Schrittweite-Indizes=256/comparechange=3,55555555... Als Schrittweite definiere ich dann 0x0355. Aber das Ganze wird nur einmal beim start abgearbeitet und sollte nicht das Problem darstellen.
Martin Kreiner schrieb: > Nun ja, wenn du meinst.....
1 | if((stepsizecnt/10000)<(stepsizemax)) |
> Alleine diese in deinen Augen vielleicht lächerliche Abfrage verheizt > schon mal 163 Mikrosekunden. Ok also ist die 32Bit-Berechnung wohl das Problem. Sind wohl zuviele Speicherzugriffe. Hmm gibt´s da eine sinnvolle alternative? Bitschieberoperanden verwenden?
:
Bearbeitet durch User
Peter A. schrieb: > Bsp.: f_pwm = 7200, samples=256-Werte, fout=50: > Schrittweite-Indizes=256/comparechange=3,55555555... > Als Schrittweite definiere ich dann 0x0355. > > Aber das Ganze wird nur einmal beim start abgearbeitet und sollte nicht > das Problem darstellen. Wenn das Rechenergebnis nicht stimmt, dann ist das schon ein Problem. > Schrittweite-Indizes=256/comparechange=3,55555555... > Als Schrittweite definiere ich dann 0x0355. 0x? (Halte ich jetzt mal wegen stepsizecnt/10000)<(stepsizemax für einen Tippfehler:-) ) Warum schreibst du dann die Berechnung nicht einfach genau so hin, sondern pfriemelst da mit Einzelbytes rum? Im übrigen: 32 Bit Rechnerei in der ISR ist auch nicht so ohne. Da könntest du dir den ganzen Aufwand auch sparen und die Prozentrechnerei (denn nichts anderes ist diese Frequenzzunamhe ja) auch in 16 Bit direkt in der ISR ausrechnen. Grob geschätzt würde sich das nicht um viel reissen.
:
Bearbeitet durch User
Um nochmal zum Anfang zu gehen: > Leider erreiche ich die max. Schrittweite nicht, d.h. meine > Ausgangsfrequenz ist deutlich kleiner als gewünscht. Was meinst du damit? Wann wäre sie denn erreicht? Wenn diese Codezeile hier ausgeführt wird:
1 | else
|
2 | {
|
3 | stepsizecntx=stepsizemax; |
4 | }
|
Diese Zeile wird zumindest im Simulator nach 2,723 Sekunden ausgeführt.
Allgemeiner Tipp: Am Anfang der ISR einen Pin auf High setzen und danach auf Low. Damit kann man Oszi schön sehen, wann die ISR real aufgerufen wird und wie lange sie braucht. Man muss etwas Reserve für die PUSHs am Anfang und POPs am Ende rechnen.
Danke für die vielen Antworten. Ich komm heut leider nicht mehr dazu das Programm abzuändern. Aber ich bin mir ziemlich sicher, dass ich irgendwo, wie Herr Buchegger bereits erwähnt hat, einen Rechenfehler im Code habe. Von den 32-Bit Multiplikationen muss ich auch weg. Das kostet zuviel Zeit. Das mit 0x war kein Tippfehler, ich habe mich da von jemand anderem Einlullen lassen die Nachkommastellen meiner Indexschrittweite in das untere Byte meiner Variable zu schreiben. Das soll den Rundungsfehler verkleinern. Von der korrekten Schrittweite ist das aber bei kleinen Frequenzen meilenweit entfernt.
Martin Kreiner schrieb: > Was meinst du damit? > Wann wäre sie denn erreicht? Wenn diese Codezeile hier ausgeführt > wird:else > { > stepsizecntx=stepsizemax; > } > > Diese Zeile wird zumindest im Simulator nach 2,723 Sekunden ausgeführt. Ja korrekt.
Ich scheine die Probleme in den Griff bekommen zu haben. Der Code ist jetzt deutlich einfacher. Statt multiplikation/division verwende ich jetzt Schieberegister. Ich werde das Ganze jetzt mal am Oszi begutachten, ob ich denn wirklich alles gelöst habe. Anbei die Bilder bei einem Hochlauf auf 100Hz.
:
Bearbeitet durch User
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.