Ich fahre über einen Ausgang eine viertel Sinuswelle als PWM-Signal. Dieses Signal wird extern über ein RC-Gleid geschoben, welches mir eine schöne sinusförmige Rampe auf meinem Oszilloskop anzeigt. Ich möchte nun wenn der Sinus oben beim Maximalwert angekommen ist eine pause machen. Das heißt das Signal soll auf maximal stehen bleiben. Dies funktioniert leider nicht. Sobald mein Delay startet ist der Ausgang auf 0 und die Pause wird gemacht befor die neue Viertel Welle abgefahren wird. Also die Pause wird in einem falschen Zustand gemacht. Ich komme an diesem Punkt momentan nicht weiter. Vielleicht kann mir ja jemand helfen. Des Weiteren habe ich noch das Problem, dass in dem viertel Sinus ungefähr in der Mitte ein unerklärlicher Pick nach unten ist. Code im Anhang. benutze ein Attiny44A
:
Bearbeitet durch User
Schreib das
1 | if (i > (0xFF-divider)) |
mal als
1 | if (i > (255-divider)) |
(noch besser wäre
1 | if (i > (sizeof(sinewave) - divider)) |
) Ich bin mir da auch immer ein bischen unsicher, welchen Datentyp das Literal 0xFF eigentlich hat. Da können scheinbar seltsame Dinge passieren, wenn der nach int promoted wird. Die genauen Regeln sind da nicht unbedingt trivial. Alledings gibt es an dieser Stelle überhaupt keinen Grund, da jetzt eine Hex-Zahl zu benutzen.
:
Bearbeitet durch User
Marius D. schrieb: > Ich fahre über einen Ausgang eine viertel Sinuswelle als PWM-Signal. > Dieses Signal wird extern über ein RC-Gleid geschoben, welches mir eine > schöne sinusförmige Rampe auf meinem Oszilloskop anzeigt. Schön. Nur was soll der Sinn einer sinusförmigen Rampe sein? > Ich möchte nun wenn der Sinus oben beim Maximalwert angekommen ist eine > pause machen. Das heißt das Signal soll auf maximal stehen bleiben. Das ist dann schlicht ein übersteuerter Sinus. Kann man ganz leicht erreichen, indem man den Wert aus der Sinustabelle mit einem hinreichend großen Fakter mittels "sättigender" Arithmetik multipliziert. Oder anders ausgedrückt: Man schaltet der Multiplikation eine simple binäre IF-Verzweigung nach, ungefähr sowas: if (value > limit) value = limit; Es ergibt sich genau das, was du willst, ein Sinus mit gekappten Spitzen. > Des Weiteren habe ich noch das Problem, dass in dem viertel Sinus > ungefähr in der Mitte ein unerklärlicher Pick nach unten ist. Dann ist der Code oder die Sinustabelle Rotz.
Marius D. schrieb: > Sobald mein Delay startet ist der Ausgang > auf 0 und die Pause wird gemacht befor die neue Viertel Welle abgefahren > wird. Erst geht der Ausgang auf 0, dann kommt das Delay. > TCCR1A |= (1 << COM1B1) | (1 << COM1B0) | (1 << WGM10); Deine PWM läuft falsch rum. TCCR1A |= (1 << COM1B1) /*| (1 << COM1B0)*/ | (1 << WGM10); mfg.
c-hater schrieb: > Es ergibt sich genau das, was du willst, ein Sinus mit gekappten > Spitzen. Wie kommst du drauf, dass er eine gekappte Spitze will? Er schrieb er will warten bis der Sinus sein Maximum erreicht hat und dann eine gewisse Zeit auf dem Maximum bleiben. Das ist was anderes als eine gekappte Spitze. Ich persönlich würde hier auch nicht mit einem delay() arbeiten sondern warten bis der Sinus seinen Maximalwert hat und dann einen Timer entsprechend anschubsen.
Karl Heinz schrieb > noch besser wäre > if (i > (sizeof(sinewave) - divider)) Hab ich gerade mal mit Dezimalzahl probiert, leider bleibt das Problem bestehen. Thomas E. schrieb: > Deine PWM läuft falsch rum. Danke für den Hinweis. Aber das hat seine Richtigkeit. Drehe das Signal auserhalb des µC. Michael Köhler schrieb: > Ich persönlich würde hier auch nicht mit einem delay() arbeiten sondern > warten bis der Sinus seinen Maximalwert hat und dann einen Timer > entsprechend anschubsen. Wäre eine schönere Variante aber zum Testen müsste es so doch auch funktionieren. c-hater schrieb: > Dann ist der Code oder die Sinustabelle Rotz. Das hat mir sehr viel geholfen. Vielen dank. Habe den Code zum testen mal stark vereinfacht. Im Main habe ich eine dauerschleife und das setzen der Register wie im alten code. (Siehe professionelle Paint Skizze.) Hier nur die Interrupt Routine. •
1 | // i und sinewave sind jetzt globale Variablen.
|
2 | ISR ( TIM1_OVF_vect ) { |
3 | OCR1BL = sinewave[i]; |
4 | if ( i <= (254)) |
5 | i++; |
6 | }
|
Meine Sinuskurve fährt nach oben. Nun sollte sie einfach Oben stehen bleiben. Sie fällt dann sobald die Spitze erreicht ist wieder auf einen Wert der ungfair 1/8 von U_max ist zurück.
Hab jetzt ein Ergebniss mit dem ich fast zu frieden bin. Leider habe ich noch diesen doofen Zacken im Verlauf. Hat wer evtl. Vermutungen wo dieser herkommen könnte? Siehe Bild Habe den Code wie folgt verändert.
1 | while(1) |
2 | {
|
3 | |
4 | if ( pwm_flag == 1 ) |
5 | {
|
6 | //TIMSK1 &= ~( 1 << TOIE1 );
|
7 | OCR1B = 255; |
8 | _delay_ms (4); |
9 | OCR1B = 0; |
10 | _delay_ms (4); |
11 | i = 0; |
12 | pwm_flag = 0; |
13 | //TIMSK1 |= ( 1 << TOIE1 );
|
14 | }
|
15 | }
|
16 | }
|
17 | ISR ( TIM1_OVF_vect ) { |
18 | //if ( pwm_flag =
|
19 | if ( i <= (254)) |
20 | {
|
21 | i++; |
22 | OCR1B = sinewave[i];} |
23 | else
|
24 | pwm_flag = 1; |
25 | }
|
Ich habe mir deinen Code mal angeschaut. Einige Anmerkungen: Hexcode: Macht heute praktisch nur mehr arbeit mit Hexcode zu arbeiten, programmtechnisch hast du keinen Vorteil wenn du 0xCE schreibst, wenn du aber später mal im Code liest musst du erst mal wieder umrechnen. Nicht sehr sinnvoll. TCCR1C sowie OCR1BL werden eh beide mit 0 initialisiert, es macht also keinen Sinn diesen Werten extra noch mal 0 zuzuweisen. Du schreibst DDRB = 0xF. Frage: Welche Pins des Ports B sind nun als Ausgang geschaltet? Thema Hexcode ;). Schreib doch gleich DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3). Ist zwar mehr Schreibarbeit aber wenn du später mal wieder in den Code schaust siehst du auf den ersten Blick, welche Ports du als Ausgang definiert hast. Dein Code schaut eigentlich nicht falsch aus. Hast du dir die PWM auch schon direkt am Ausgangspin angeschaut? Du hast ja nur am Ausgang des TP geschaut.
@Michael Köhler danke für deine Hilfe Habe mir das PWM signal mal genau angeschaut. Das läuft ordnungsgemäß auf den Maximalwert zu. Wenn es oben angekommt, springt das Signal hin und her. Nun wird die Pause gemacht. Dann wird die nächste viertel Welle geschrieben. *Edit Habe noch mal meine Lool-Up-Table überprüft. Dort scheint auch alles in Ordnung zu sein. *Edit2 Der Zacken verschwindet wenn ich nicht bis 255 sonder nur bis 245 laufe. Könnte das ein Bug in der Hardware sein ?
1 | }
|
2 | ISR ( TIM1_OVF_vect ) { |
3 | if ( i <= (245-divider)) |
4 | {
|
5 | OCR1B = sinewave[i]; |
6 | i++; |
7 | }
|
8 | else
|
9 | pwm_flag = 1; |
10 | }
|
:
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.