Hi Leute :),
ich habe hier ein kleines Projekt mit einem Mega16 am laufen bei dem ich
einen Gleichstrommotor mit 9V bidirektional ansteuer. Ich hatte bereits
ne Softwarelösung für die PWM und das hat wunderbar funktioniert. Jetzt
bin ich aber auf FastPWM umgestiegen und habe ein kleines Problem.
Mein Motortreiber (selbstgebaute H-Brücke) wird über zwei Signale
angesteuert. die dürfen nicht gleichzeitig high sein, sonst geht die
H-Brücke drauf.
Beim Richtungswechsel muss ich also die PWM für den einen Pin abschalten
und dann beim anderen Pin starten. Genau da liegt auch mein Problem. wie
bekomme ich die PWM abgeschaltet? Also, dass der abgeschaltete Pin auf
low bleibt und der andere zu arbeiten beginnt?
Ich habe das Programm mal stark abgespeckt. es geht mir eigentlich nur
um die Zeile mit "Hier möchte ich die PWM-Ausgabe an dem OC1B pin
stoppen"
1
intmain(void)
2
{
3
DDRD=0b11111111;
4
PORTD=0b00000000;
5
srand(get_seed());
6
intdauer,dir,speed,i,count,changeid;
7
charspeedstring[2];
8
9
10
//FastPWM Einstellung
11
DDRD=0b00110000;
12
PORTD=0b00000000;
13
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
14
TCCR1B=(1<<WGM12)|(1<<CS11);
15
16
17
while(1)
18
{
19
20
change(&speed,&dir);
21
dauer=rand()%15+1;
22
23
if(dir==0)//Rückwärts-Modus
24
{
25
TCCR1A=(1<<COM1A1);
26
TCCR1A&=~(1<<COM1B1);//Hier möchte ich die PWM-Ausgabe an dem OC1B pin stoppen
Das mit "TCCR1A &= ~(1<<COM1B1);" war nur ein versuch um es zu stoppen.
hat aber nicht hingehauen. gebt es vielleicht anders eine möglichkeit
die pwm zu stoppen?
Juli D. schrieb:> Das mit "TCCR1A &= ~(1<<COM1B1);" war nur ein versuch um es zu stoppen.> hat aber nicht hingehauen.
Doch, sollte gehen.
Nur sollte man erst den einen abschalten und danach den anderen ein.
Dazwischen ein kleines Delay kann auch nicht schaden.
Juli D. schrieb:> TCCR1A = (1<<COM1A1);
Setzt das komplette Register, (1<<WGM10) wird gelöscht und der CTC modus
wird gesetzt.
TCCR1A |= ( 1 << COM1A1 ) wolltest du vermutlich schreiben ?
Sehe ich es richtig das der Timer als Fast PWM, 8-bit mit Top 0x00FF
eingestellt ist ?
Danke euch beiden.
@Thomas Eckmann:
Das habe ich gerade ausprobiert und es klappt einwandfrei. Gestern Abend
hatte ich das schon probiert und hatte wohl noch einen anderen Bug drin.
Schaltet der µC denn pro Periode kurz ein und sofort wieder aus oder
geht er gar nicht erst auf high?
@Peter Dannegger:
Thomas Eckmanns Lösung funktioniert ja soweit ganz gut. Ich werde aber
trotzdem noch kurz probieren die "alte" Methode zum laufen zu bringen.
Danke dir
@Holger L:
achso, du meinst, wenn ich "TCCR1A = (1<<COM1A1)" verwende beschreibe
ich das ganze Register und die vorherigen Einstellungen (zb (1<<WGM10) )
werden mit 0 überschrieben?
Juli D. schrieb:> ich habe hier ein kleines Projekt mit einem Mega16 am laufen bei dem ich> einen Gleichstrommotor mit 9V bidirektional ansteuer. Ich hatte bereits> ne Softwarelösung für die PWM und das hat wunderbar funktioniert. Jetzt> bin ich aber auf FastPWM umgestiegen und habe ein kleines Problem.>> Mein Motortreiber (selbstgebaute H-Brücke) wird über zwei Signale> angesteuert. die dürfen nicht gleichzeitig high sein, sonst geht die> H-Brücke drauf.>> Beim Richtungswechsel muss ich also die PWM für den einen Pin abschalten> und dann beim anderen Pin starten. Genau da liegt auch mein Problem.
Das ist aber eigentlich überhaupt kein Problem. Man muß nur zwei
Eigenschaften der AVR-Timer-PWM kennen:
1) Es gibt immer genau einen OCR-Wert, bei dem die PWM garnichts macht,
der Pegel am OCx-Pin also konstant ist.
2) In allen PWM-Modi (also auch bei Fast-PWM) werden neu zugewiesene
Werte
der OCR-Register von der Hardware immer synchron übernommen und zwar
an
einem ganz bestimmten Punkt des PWM-Zyklus (der sich allerdings je
nach
PWM-Modus unterscheiden kann).
Das alles steht haarklein im Datenblatt aufgedröselt für jeden zum
Nachlesen.
Der einzige kritische Punkt bei der Ansteuerung eine DC-Motors könnte
also beim Richtungswechsel sein, wenn die Software nix taugt, die ihn
ansteuert, also dein Werk. Die muß einfach nur folgendes sicherstellen:
1) Die OCR-Werte für beide Bewegungsrichtungen sind immer
"gleichzeitig"
zu schreiben
2) Mindestens für eine Bewegungsrichtung muß immer der "neutrale"
OCR-Wert geschrieben werden.
2) ist absolut trivial zu erreichen, 1) hingegen erfordert eine
Synchronisation des Schreibvorgangs der OCR-Register mit dem PWM-Zyklus
der Hardware und die Herstellung der Sicherheit, dass dieser
Schreibvorgang durch nichts und niemanden unterbrochen wird.
Sprich: eine exclusiv ausgeführte ISR. Und zwar idealerweise eine, die
möglichst kurz nach dem Zeitpunkt ausgeführt wird, zu dem die Hardware
die OCR-Werte für den aktuellen Zyklus übernommen hat.
> wie> bekomme ich die PWM abgeschaltet?
Das ist die falsche Frage. Weil: sie muß überhaupt nicht abgeschaltet
werden, um dein Problem sinnvoll zu lösen, ganz im Gegenteil, die
Hardware gibt hier vor, dass die beste, sinnvollste und effizienteste
Lösung ist, genau das nicht zu tun...
c-hater schrieb:> 1) Es gibt immer genau einen OCR-Wert, bei dem die PWM garnichts macht,> der Pegel am OCx-Pin also konstant ist.
Aber nicht im fast Mode, da gibt es bei 0 einen Spike:
"If the OCR1x is set equal to BOTTOM (0x0000) the output will be a
narrow spike for each TOP+1 timer clock cycle. Setting the OCR1x equal
to TOP will result in a constant high or low output (depending on the
polarity of the output set by the COM1x1:0 bits.)"
Auch sollte man nicht vergessen, das man mit den COM Bits den Ausgang
lediglich an den Timer koppelt.
Wird der Pin durch löschen der COM Bits wieder vom Timer abgekoppelt,
ist noch lange nicht sicher gestellt, dass der Pin danach auch wieder
auf low ist. Die COM Bits sorgen dafür, dass vom Timer das PORT Register
angesteuert wird. Will man also sicher gehen, dass der Pin nach dem
Lösen vom Timer auf Low ist, dann muss man im PORT Register das
jeweilige Ausgabebit löschen.
Peter D. schrieb:> c-hater schrieb:>> 1) Es gibt immer genau einen OCR-Wert, bei dem die PWM garnichts macht,>> der Pegel am OCx-Pin also konstant ist.>> Aber nicht im fast Mode, da gibt es bei 0 einen Spike:
Wer hat behauptet, daß der Wert, bei dem garnichts passiert, immer Null
wäre?
Noch viel schlimmer: Die Lösung postest du doch auch gleich in deinem
eigenen Zitat mit:
> Setting the OCR1x equal> to TOP will result in a constant high or low output (depending on the> polarity of the output set by the COM1x1:0 bits.)"
Wie doof muß man nach meiner doch ziemlich expliziten Ansage eigentlich
sein, um sie nicht zu erkennen? OK, man muß wohl C-Fetischist sein,
zumindest das wird hier wohl doch irgendwie endgültig klar...
Paßt nicht zu Implementierung der vorhandene Lib, also geht's nicht,
mehr noch: es kann generell garnicht gehen...
Genau das ist, was ich so vehement anprangere: die Vernichtung der
Fantasie und des gesunden Menschenverstandes allein durch die excessive
und exclusive Verwendung von C. Das macht offensichtlich einfach nur
dumm und unflexibel. Nicht mehr und nicht weniger.
c-hater schrieb:> Wie doof muß man nach meiner doch ziemlich expliziten Ansage eigentlich> sein, um sie nicht zu erkennen? OK, man muß wohl C-Fetischist sein,> zumindest das wird hier wohl doch irgendwie endgültig klar...>> Paßt nicht zu Implementierung der vorhandene Lib, also geht's nicht,> mehr noch: es kann generell garnicht gehen...>> Genau das ist, was ich so vehement anprangere: die Vernichtung der> Fantasie und des gesunden Menschenverstandes allein durch die excessive> und exclusive Verwendung von C. Das macht offensichtlich einfach nur> dumm und unflexibel. Nicht mehr und nicht weniger.
Deine Domina immer noch im Urlaub?
Warum soll der von dir beschriebene Kleinkram in C nicht gehen?
mfg.
Thomas E. schrieb:> Warum soll der von dir beschriebene Kleinkram in C nicht gehen?
Weil er sich unbedingt eine ISR einbildet, die dann auch noch möglichst
schnell sein muss, weil er genau weiss, dass der C Compiler am Anfang
einer ISR ein paar Register pusht, die er sich in Assembler sparen kann.
ISR braucht da überhaupt keiner. Die eine PWM abschalten (aber richtig),
die andere anschalten und gut ists. Dazwischen noch ein kleines Päuschen
einlegen, denn ein Motor wird da nicht so glücklich darüber sein, wenn
man aus Vollgas/links in einem Zug auf Vollgas/rechts umschaltet.
Eine andere Möglichkeit wäre wohl die PWM zu invertieren. Aber dann wird
es zu Hardware-Umbauten kommen. Da es aber bei einem Motor nicht
zeitkritisch ist, ob da beim Umschalten eine PWM Periode komplett
ausfällt, geht es auch so. Er muss nur dafür sorgen, dass er keine
0-Spikes hat, während die andere PWM arbeitet. Denn sonst: 2 mal High
(wenn auch nur für kurze Zeit) -> nicht gut für die H-Brücke.
Und wie meistens: Mit C hat das ganze wieder mal nur insofern zu tun,
dass man die Syntax zum Setzen und Löschen von Bits kennen sollte.
Abgesehen davon, würde man das in Assembler genau gleich machen.
Thomas E. schrieb:> Warum soll der von dir beschriebene Kleinkram in C nicht gehen?
Das habe ich an keiner Stelle behauptet. Natürlich geht das auch in C.
Ich kann es in C genauso umsetzen wie in Assembler.
Nur sind offensichtlich die reinen C-ler zu dumm dazu, es umzusetzen und
darüber hinaus sogar dazu, auch nur die Möglichkeit zu erkennen, es
umsetzen zu können. Genau das war der Punkt.
Deine frechen Lügen und Unterstellungen werden dir hier nicht helfen,
der Thread spricht für sich selber. Im entscheidenden Posting findest du
nichtmal eine Erwähnung irgendeiner Programmiersprache, sondern allein
eine Darstellung der hardwaretechnisch gegebenen Sachverhalte.
Quasi eine Anleitung für alle Leute mit hinreichender Eigenintelligenz,
das Problem auf einem AVR8 zu lösen. Ganz egal in welcher Sprache.
Karl H. schrieb:> Weil er sich unbedingt eine ISR einbildet, die dann auch noch möglichst> schnell sein muss, weil er genau weiss, dass der C Compiler am Anfang> einer ISR ein paar Register pusht, die er sich in Assembler sparen kann.
???
Mir scheint, du hast immer noch nicht mal annähernd das Konzept der
Lösung verstanden. Der Trick dabei ist ja gerade: Sie läßt sich selbst
in C völlig problemlos umsetzen. Es ist eben gerade kein sehr kritisches
Software-Timing erforderlich, weil man die größten Timing-Probleme mit
dieser Lösung an die Hardware delegiert, wo sie eigentlich hingehört.
Du bist also doch sehr viel dümmer, als ich eigentlich dachte...
c-hater schrieb:> Du bist also doch sehr viel dümmer, als ich eigentlich dachte...
Ja schon gut.
Wer unbedingt eine ISR propagiert, wo es ein 4 Zeiler auch tut ....
Karl H. schrieb:> Wer unbedingt eine ISR propagiert, wo es ein 4 Zeiler auch tut ....
Nochmal ein Tick dümmer. Nein, der "Vierzeiler" (vermutlich gemeint: die
eigentliche Aktion in einen cli/sei-Rahmen verpacken) tut es eben nicht
immer.
Die Hardware interessiert sich bei der Übernahme der OCR-Werte nämlich
rein garnicht für eine bestehende Interruptsperre. "Sicher" ist der
Schreibvorgang deshalb nur, wenn die Hardware möglichst wahrscheinlich
gerade nicht die "OCR-Shadow-Register" liest, also zeitlich möglichst
kurz nachdem sie das zuletzt getan hat. Und die beste (wenn natürlich
auch immer noch nicht perfekte) Möglichkeit dazu ist nunmal eine ISR.
Immerhin kann man dieser ISR ja zusätzlich beibiegen, notfalls auf den
nächsten "sicheren" Punkt zu warten, wenn sie durch die indifferente
variable Latenz des genauso idiotisch programmierten restliche C-Codes
erst zu einem Zeitpunkt aktiv wird, wenn es nicht mehr sicher ist. Das
ist absolut trivial und spätestens dann wirklich sicher (deshalb hier
ohne Anführungszeichen).
Kann man eigentlich noch deutlicher zeigen als du, daß man eigentlich
keine Ahnung von hardwarenaher Programmierung hat?
Karl H. schrieb im Beitrag #4303166:
> Und die Leute bei Atmel sind alle Volltrottel.
Das habe ich wo behauptet? Und welches paper von Atmel gibt auch nur im
entferntesten eine Rechtfertigung auch nur für die Andeutung, daß ich
eine solche Meinung über die Leute von Atmel hätte?
Oder auch nur dafür, das das vorgestellte Konzept ineffizient wäre oder
sogar nicht funktionieren würde? Es resultiert doch einfach nur aus den
Fakten zur Hardware, die die AVR-Datenblätter selber liefern...
Karl H. schrieb:> Wird der Pin durch löschen der COM Bits wieder vom Timer abgekoppelt,> ist noch lange nicht sicher gestellt, dass der Pin danach auch wieder> auf low ist.
Der Pin geht dann sofort auf den Pegel des PORTx.y-Bits ohne
Verzögerung.
Man kann also bequem die eine PWM abschalten, die Zeit zum Sperren der
H-Brücke abwarten und dann die andere einschalten.
Man muß nichtmal die Werte in den OCR1x Registern ändern, sondern läßt
die PWMs einfach intern weiter laufen.