Hallo, ich möchte mit einem ATmega328 zwei komplementäre Rechtecksignale erzeugen (D=50%). Für ein einzelnes Signal ist der CTC modus mit toggel on compare match natürlich am einfachsten. Jetzt hab ich mir die Frage gestellt ob ich OC0A und OC0B mit dem selben T/C gleichzeitig toggeln kann. Aus dem Datenblatt entnehme ich auf den ersten Blick nichts was dagegen spricht. Wenn ich die Pins gegengleich initialisiere sollte ich so 2 komplementäre Signale haben. Geht das oder lässt sich pro T/C immer nur ein OC0x Pin toggeln? LG
Jannik schrieb: > ich möchte mit einem ATmega328 zwei komplementäre Rechtecksignale > erzeugen (D=50%). Dann tu das doch. > Für ein einzelnes Signal ist der CTC modus mit toggel > on compare match natürlich am einfachsten. Das ist egal. CTC ist nur dahin anders, als daß man die Periodendauer feiner einstellen kann. > Jetzt hab ich mir die Frage > gestellt ob ich OC0A und OC0B mit dem selben T/C gleichzeitig toggeln > kann. Sicher. Warum nicht? > Aus dem Datenblatt entnehme ich auf den ersten Blick nichts was > dagegen spricht. Wenn ich die Pins gegengleich Gegengleich? Eher invers, invertiert. > initialisiere sollte ich > so 2 komplementäre Signale haben. Geht das Ja. >oder lässt sich pro T/C immer > nur ein OC0x Pin toggeln? Nein. Warum probierst du das nicht einfach aus? Das dauert keine 3 Minuten.
Moin Falk, danke für die Antwort. Habs jetzt mal ausprobiert allerdings bekomme ich zwei identische Signale statt ein invertiertes. Ich wollte das ja realisieren indem ich einen Ausgang initial high und den anderen low setze. Kann es sein, dass dadurch: "If one or both of the COM0A1:0 bits are set, the OC0A output overrides the normal port functionality of the I/O pin it is connected to". - meine high/low Initialisierung verloren geht? LG
Jannik schrieb: > Habs jetzt mal ausprobiert allerdings bekomme ich > zwei identische Signale statt ein invertiertes. Ich wollte das ja > realisieren indem ich einen Ausgang initial high und den anderen low > setze. Guck' Dir nochmals den Abschnitt "19.7.3 Fast PWM Mode" im Datenblatt an, ibs. Figure 19-6. Fast PWM Mode, Timing Diagram. OCnx: (COMnx[1:0] = 0x2) /OCnx: (COMnx[1:0] = 0x3) Ich vermute, dass das nur im Fast PWM Mode funktioniert. > Kann es sein, dass dadurch: "If one or both of the COM0A1:0 bits are > set, the OC0A output overrides the normal port functionality of the I/O > pin it is connected to". - meine high/low Initialisierung verloren geht? Nein, das heißt nur, dass Du den jeweiligen Pin nicht mehr über DIR oder OUT steuern kannst. Grüßle, Volker P.S.: Wie so oft in diesem Forum wäre es hilfreich wenn Du Deinen Code zeigen würdest, denn das mit dem Hellsehen klappt nur sehr eingeschränkt...
:
Bearbeitet durch User
Jannik schrieb: > Kann es sein, dass dadurch: "If one or both of the COM0A1:0 bits are > set, the OC0A output overrides the normal port functionality of the I/O > pin it is connected to". - meine high/low Initialisierung verloren geht? Ja, dass ist so. Entweder nimmst du die Fast-PWM mit Top = 0xff oder mit Timer1 Top = ICR1 und dann Fast-PWM Mode, Duty je 50% und Abfahrt... Die 8 Bit Timer der alten AVR sind da etwas zäh. Die neuen AVRs können einfach einen IO invertieren, damit wäre das kein Problem.
:
Bearbeitet durch User
Beitrag #7430491 wurde vom Autor gelöscht.
Ingo L. schrieb: > und dann Fast-PWM Mode, Duty je 50% und Abfahrt... Lt. Datenblatt Figure 19-7. Phase Correct PWM Mode, Timing Diagram kann auch im Phase Correct PWM Mode ein komplementäres Signal an OC0A und OC0B ausgegeben werden. Grüßle, Volker
Beitrag #7430493 wurde vom Autor gelöscht.
Volker B. schrieb: > Lt. Datenblatt Figure 19-7. Phase Correct PWM Mode, Timing Diagram kann > auch im Phase Correct PWM Mode ein komplementäres Signal an OC0A und > OC0B ausgegeben werden. Ja, dass geht ebenfalls.
Jannik schrieb: > Kann es sein, dass dadurch: "If one or both of the COM0A1:0 bits are > set, the OC0A output overrides the normal port functionality of the I/O > pin it is connected to". - meine high/low Initialisierung verloren geht? Benutze einfach Force Output Compare, dann kannste einen der beiden Ausgänge umschalten, was du vermutlich auch vor hattest ;)
:
Bearbeitet durch User
1 | sbi DDRD,6 |
2 | sbi DDRD,5 |
3 | puti TCCR0A,(1<<COM0A0)+(1<<COM0B0)+(1<<WGM01) |
4 | puti OCR0A,123 |
5 | puti TCCR0B,(1<<CS00)+(1<<FOC0B) ; ! |
Leider müssen die Signale 125kHz haben, da sind die PWM modi zu langsam. Force output compare sehe ich mir mal an. Ob die Initialisierung verloren geht da seid ihr euch offenbar uneinig :D
1 | // 8-bit T/C0 -> toggle OCR0A & OCR0B for 125 kHz constant signal
|
2 | |
3 | DDRD |= (1<<DDD5)| (1<<DDD6); // Pin 5 6 output |
4 | |
5 | TCCR0A = 0; |
6 | TCCR0B = 0; |
7 | |
8 | TCCR0A |= 1 << COM0A0; // Toggle OC0A on compare match |
9 | TCCR0A |= 1 << COM0B0; // Toggle OC0B on compare match |
10 | TCCR0A |= 1 << WGM01; // CTC Mode |
11 | |
12 | TCCR0B |= 1 << CS00; // no prescaler |
13 | |
14 | OCR0A = 63; // count 32-1 times to generate 125kHz output, 250kHz toggle for 125kHz square wave |
15 | OCR0B = 63; // count 32-1 times to generate 125kHz output, 250kHz toggle for 125kHz square wave |
16 | |
17 | PORTD &=~(1 << PD5); // set pin 5 low OC0B |
18 | PORTD |= (1<<PD6); // set pin 6 high OC0A |
Beitrag #7430538 wurde vom Autor gelöscht.
an Jannik: Es sollte kein Problem darstellen, das gezeigte Assemblerprogramm auf C umzusetzen.
Beitrag #7430543 wurde vom Autor gelöscht.
Was für Hinweise, Volker B.? Ich folge den ursprünglichen Anforderungen von Jannik.
Jannik schrieb: > Force output compare sehe ich mir mal an. OMG! > Ob die Initialisierung verloren geht da seid ihr euch offenbar uneinig Welche Initialisierung denn? Die vom Port.OUT Register? Ja, die hat keine Bedeutung, wie von Dir weiter oben Zitiert. > TCCR0A |= 1 << COM0A0; // Toggle OC0A on compare match > TCCR0A |= 1 << COM0B0; // Toggle OC0B on compare match OMG! Du willst OC0A setzen und OC0B löschen (und anders herum), also guck' Dir nochmals Table 19-6. Compare Output Mode, non-PWM an: COM0B1 COM0B0 Description ---------------------------------------------- 0 0 Normal port operation, OC0B disconnected. 0 1 Toggle OC0B on Compare Match. 1 0 Clear OC0B on Compare Match. 1 1 Set OC0B on Compare Match. Die Bilder Figure 19-6. und Figure 19-7. Phase Correct PWM Mode, Timing Diagram zeigen m.E. genau das Verhalten, das Du haben willst. Warum initialisierst Du dann TCCR0A nicht genau so, wie dort beschrieben? Grüßle, Volker
:
Bearbeitet durch User
S. L. schrieb: > an Jannik: > > Es sollte kein Problem darstellen, das gezeigte Assemblerprogramm auf C > umzusetzen. ...nur dass es auch nicht funktioniert... > Was für Hinweise, Volker B.? Die Hinweise auf das Datenblatt des mega328 Figure 19-7. Phase Correct PWM Mode, Timing Diagram Figure 19-6. Fast PWM Mode, Timing Diagram Grüßle, Volker
:
Bearbeitet durch User
> ...nur dass es auch nicht funktioniert...
?
Natürlich läuft das, ich sehe es doch vor mir.
Volker B. schrieb: > OMG! Du willst OC0A setzen und OC0B löschen (und anders herum), also > guck' Dir nochmals > Table 19-6. Compare Output Mode, non-PWM an: Ich will beides setzen weil ich ja beide Pins toggeln will? (PWM modi sind keine Option!) Der Force Output Compare Einzeiler
1 | TCCR0B |= 1 << FOC0B; |
hat tatsächlich gereicht. Habe jetzt mein gewünschtes Ergebnis. Um ne kurze Erklärung was der Force Output Compare macht wäre ich trotzdem dankbar. Aus dem kurzen Abschnitt im Datenblatt werde ich mit meinen begrenzten Kenntnissen nicht schlau.
S. L. schrieb: > Natürlich läuft das, ich sehe es doch vor mir. Also auf meinem Osci siehts auch gut aus :D
Jannik schrieb: > Um ne kurze Erklärung was der Force Output Compare macht wäre ich > trotzdem dankbar. Aus dem kurzen Abschnitt im Datenblatt werde ich mit > meinen begrenzten Kenntnissen nicht schlau. Es erzwingt einen Compare-Match, was bei deiner Konfiguration ein Pin-Toggle an dem Pin erzwingt. Somit sind die Pins dann automatisch gegenphasig. Volker B. schrieb: > OMG! Gleichfalls Volker B. schrieb: > Warum > initialisierst Du dann TCCR0A nicht genau so, wie dort beschrieben? Weil dann die PWM-Frequenz nicht mehr fein genug eingestellt werden kann, dass hast du offensichtlich nicht bemerkt
:
Bearbeitet durch User
Jannik schrieb: > S. L. schrieb: >> Natürlich läuft das, ich sehe es doch vor mir. > > Also auf meinem Osci siehts auch gut aus :D OK, der Code von S.L. funktioniert auch. Nur darf da nichts dazwischenkommen, also kein Stop des Timers oder Interrupt bei der Initialisierung. Deshalb würde ich dem TO die Initialisierung gem. der mehrfach erwähnten Diagramme aus dem Handbuch empfehlen. Grüßle, Volker.
Volker B. schrieb: > Nur darf da nichts > dazwischenkommen, also kein Stop des Timers oder Interrupt bei der > Initialisierung. Deshalb würde ich dem TO die Initialisierung gem. der > mehrfach erwähnten Diagramme aus dem Handbuch empfehlen.
1 | // 8-bit T/C0 -> toggle OCR0A & OCR0B for 125 kHz constant signal
|
2 | DDRD |= (1<<DDD5)| (1<<DDD6); // Pin 5 6 output |
3 | TCCR0A = 0; |
4 | TCCR0B = 0; |
5 | TCCR0A |= 1 << COM0A0; // Toggle OC0A on compare match |
6 | TCCR0A |= 1 << COM0B0; // Toggle OC0B on compare match |
7 | TCCR0A |= 1 << WGM01; // CTC Mode |
8 | TCCR0A |= (1<<FOC0A); |
9 | OCR0A = 63; // count 32-1 times to generate 125kHz output, 250kHz |
10 | //toggle for 125kHz square wave
|
11 | OCR0B = 63; // count 32-1 times to generate 125kHz output, 250kHz |
12 | //toggle for 125kHz square wave
|
13 | TCCR0B |= 1 << CS00; // no prescaler |
So sollte das ohne Probleme funktionieren. Volker B. schrieb: > Deshalb würde ich dem TO die Initialisierung gem. der > mehrfach erwähnten Diagramme aus dem Handbuch empfehlen. Gemäß Diagrammen lässt sich garnichts initialisieren
:
Bearbeitet durch User
Volker B.:
> Nur darf da nichts dazwischenkommen ...
Ist das jetzt nicht etwas an den Haaren herbeigezogen, "Stop des
Timers"? Und gegen die Unterbrechung während der Initialisierung lässt
sich ja vorbeugen, indem man z.B., wie in meinem Programm, TCCR0A auf
einen Schlag setzt; oder in cli...sei kapselt.
S. L. schrieb: > Volker B.: >> Nur darf da nichts dazwischenkommen ... > > Ist das jetzt nicht etwas an den Haaren herbeigezogen, Weißt Du was der TO programmiert hat?
Ingo L. schrieb: > Volker B. schrieb: >> Deshalb würde ich dem TO die Initialisierung gem. der >> mehrfach erwähnten Diagramme aus dem Handbuch empfehlen. > Gemäß Diagrammen lässt sich garnichts initialisieren OK, Punkt für Dich :-) Also gem. der in Klammern hinter dem jeweiligen Timingdiagramm geschriebenen Hinweisen auf die Initialisierung der COMnx[1:0] Register-Bits. Hoffe, das war jetzt präszise genug!
Jannik schrieb: > Habs jetzt mal ausprobiert allerdings bekomme ich > zwei identische Signale statt ein invertiertes. Ich wollte das ja > realisieren indem ich einen Ausgang initial high und den anderen low > setze. Ne, im PWM-Mode ist das Ausgangsregister wirkungslos. Du kannst aber einen PWM-Ausgang auf invertiert setzen, das geht in allen PWM-Modi.
Peter Dannegger schlug vor: > Du kannst aber einen PWM-Ausgang auf invertiert setzen, > das geht in allen PWM-Modi. Gefordert sind aber zwei Ausgänge bei 125 kHz - wie geht das auf einem ATmega328 mit Timer0 - Beispielprogramm?
S. L. schrieb: > Gefordert sind aber zwei Ausgänge bei 125 kHz - wie geht das auf einem > ATmega328 mit Timer0 - Beispielprogramm? Wurde schon mehrfach geschrieben. Wird nur immer wieder ignoriert. Beitrag "Re: OC0A & OC0B gleichzeitig toggeln?" Ja, dann kann man die Periodendauer NICHT feingranular einstellen, weil der CTC Mode den Kanal A blockiert. Das geht aber mit Timer1, der hat nicht nur 16 Bit sondern auch noch ICR, mit welchem man den CTC Modus auch nutzen kann und GLEICHZEITIG die beiden OCR1A und OCR1B Kanäle gegenphasig laufen lassen kann. RTFM.
> Wurde schon mehrfach geschrieben. Wird nur immer wieder ignoriert. Ich kann rechnen wie ich will, ich erhalte für die 125 kHz einen Systemtakt von 32 MHz. > geht aber mit Timer1 Das ist unbestritten; aber schon im Betreff steht Timer0.
S. L. schrieb: >> Wurde schon mehrfach geschrieben. Wird nur immer wieder ignoriert. > > Ich kann rechnen wie ich will, ich erhalte für die 125 kHz einen > Systemtakt von 32 MHz. Stimmt, hab ich nicht beachtet. >> geht aber mit Timer1 > > Das ist unbestritten; aber schon im Betreff steht Timer0. Dann sind das die Grenzen. Entweder geringere Ausgangsfrequenz oder nur ein Kanal.
... Oder eben die Lösung mit dem 'Force Output Compare' FOC0x.
S. L. schrieb: > ... Oder eben die Lösung mit dem 'Force Output Compare' FOC0x. ??? Wie willst du das bei 125kHz in Software machen? Wenn man denn WIRKLICH zwei komplementäre Ausgänge braucht, kann man einen mittels externem Inverter machen. Fertig.
So ganz verstehe ich die Diskussion jetzt nicht: der Vorschlag kam von Ingo L.,er kam auch von mir, ich sah, dass es funktioniert, Jannik hat das bestätigt, bei ihm läuft es auch - ... ?
S. L. schrieb: > Beitrag "Re: OC0A & OC0B gleichzeitig toggeln?" Hmmm... Im Prinzip richtig, im Detail meiner Meinung nach aber wohl nicht ganz. Kritikpunkte: 1) Das erzeugt nur ca. die Hälfte der gewünschten Frequenz von 125kHz (bei angenommenen 16MHz Systemtakt). Matchfrequenz: 16.000.000 / (123 + 1) = 129.032,... Da mit der gewählten Initialisierung jeder Match nur ein Toggeln des Ausgangs bewirkt, beträgt die Frequenz am Ausgang nur die Hälfte der Matchfrequenz. Also nur ca. 65kHz. 2) Die Flanken der beiden Signale sind um eine Periode des Systemtakts gegeneinander verschoben. Die Signale toggeln beim Compare-Match (des jeweiligen Kanals!). D.h.: damit das Toggeln gleichzeitig erfolgt, müssen beide OCR0x-Register denselben Wert enthalten. 3) Während der Initialisierung gibt es eine kurze Periode, in denen die Signale schon aktiv, aber noch nicht invers zueinander sind. Je nachdem, was dran hängt, kann das u.U. tödlich sein. Ich denke also, das müßte korrekterweise so lauten: [asm] .EQU F_OUT = 125000 ldi R16, (FCLOCK + F_OUT / 2) / (2 * F_OUT) - 1 ; 63 out OCR0A, R16 out OCR0B, R16 ldi R16,(1<<COM0A0) | (1<<COM0B0) | (1<<WGM01) out TCCR0A,R16 ldi R16, (1<<CS00) | (1<<FOC0B) out TCCR0B, R16 sbi DDRD, 6 sbi DDRD, 5 [/asm] Damit ergibt sich dann sogar exakt die gewünschte Frequenz lt. Formel aus dem DB (s.S. 100, fast ganz oben): 16.000.000 ---------------- = 125.000 2 1 (1 + 63) Und dadurch, dass der Match für beide Kanäle gleichzeitig erfolgt (und mittels FOC0B für Kanal B einmal "vorgetoggelt" ist), ist das Signal an OC0B tatsächlich das invertierte Signal von OC0A.
C-hater schrieb:
Verdammt, Quoting für die Formel vergessen. Also die nochmal:
1 | 16.000.000 |
2 | ---------------- = 125.000 |
3 | 2 * 1 * (1 + 63) |
Hallo, den Timer sollte man immer zum Schluss starten. Dann spielt die Reihenfolge der Konfiguration keine Rolle und man hat keine negative Effekte.
Veit D. schrieb: > den Timer sollte man immer zum Schluss starten. Dann spielt die > Reihenfolge der Konfiguration keine Rolle und man hat keine negative > Effekte. Nein, das ist leider falsch. Die Signale sind timerseitig aktiv ab dem Moment, in dem die COM-Bits geschrieben werden, nicht erst ab dem Moment, in dem der Timer gestartet wird. Am einfachsten läßt sich das Problem umgehen, indem man erst zum Schluß die Pins als Ausgänge schaltet.
an C-hater: Sie lesen den Thread auch nicht erstmal durch, bevor Sie schreiben, wie Falk Brunner oder Peter Dannegger?: Zum Zeitpunkt meines Programmes war die Forderung nach 125 kHz noch gar nicht bekannt, ich hatte den Wert 123 mehr oder weniger aus der Luft gegriffen, in Anlehnung an Janniks Benutzernamen 'user_name123'. Für Ihre Punkte 2 und 3 bräuchte ich mehr Zeit (und Motivation) - vielleicht später.
:
Bearbeitet durch User
S. L. schrieb: > Zum Zeitpunkt meines Programmes war die Forderung nach 125 kHz noch > gar nicht bekannt Stimmt, diese Angabe kam erst im nächsten Posting nach deinem. > Für Ihre Punkte 2 und 3 bräuchte ich mehr Zeit (und Motivation) - > vielleicht später.
Ursprünglich hatte ich da 200 drinstehen, aber dann fand ich 123 netter. Nur nebenbei: den Wert kann ohnehin nur Jannik vorgeben, nur er weiß (bislang), wie hoch sein Systemtakt ist - allenfalls aus seinem Halbsatz "da sind die PWM modi zu langsam" könnten wir versuchen, Rückschlüsse zu ziehen; für einen genauen Wert reicht's trotzdem nicht.
S. L. schrieb: > Ursprünglich hatte ich da 200 drinstehen, aber dann fand ich 123 netter. > Nur nebenbei: den Wert kann ohnehin nur Jannik vorgeben, nur er weiß > (bislang), wie hoch sein Systemtakt ist - allenfalls aus seinem Halbsatz > "da sind die PWM modi zu langsam" könnten wir versuchen, Rückschlüsse zu > ziehen; für einen genauen Wert reicht's trotzdem nicht. Stimmt, deswegen habe ich beides in meinem Verbesserungsvorschlag auch variabel ausgelegt. Zur Perfektion fehlt allerdings noch eine Warnung, die "Unzulässigkeit" anzeigt. Ausserdem war das simple Umkopieren der beiden sbi's zur Pinfreischaltung an's Ende der Initialisierung auch auch noch nicht das Wahre. Wenn man's wirklich richtig machen will, müßte das natürlich auch für beide Kanäle gleichzeitig erfolgen. Also etwa so: [asm] in R16, DDRD ori R16, (1<<DDD6) | (1<<DDD5) out DDRD, R16 [/asm]
In der Zeit, in der hier herumdiskutiert wird, hätte man das Problem auch mit einem popeligen Inverter lösen können. Bei 125 kHz kann man den mit einem Transistor aufbauen, man kann aber auch einen 74xx04 oder eine Ein-Gatter-Variante davon verwenden. Aber das wäre vermutlich alles viel zu einfach, oder ist, weil Hardware, vieeeeeeel zu kompliziert.
Harald K. schrieb: > Aber das wäre vermutlich alles viel zu einfach, oder ist, weil Hardware, > vieeeeeeel zu kompliziert. Warum zum Taufel sollte man zusätzliche Hardware verbauen, wenn die bereits existierende Hardware die Funktion durchaus bereitstellen kann? Insbesondere: allein durch ihre sachgerechte Nutzung, nicht durch irgendwelche wilden Hacks jenseits ihrer Specs? Das ergibt doch keinen Sinn. Höchstens für Leute, die halt nicht in der Lage sind, die vorhandene Hardware sachgerecht zu benutzen...
So, also:
Ihr Punkt 2 stimmt natürlich; und gestern hatte ich nachfolgend auch
das Gefühl, dass da rein programmsymmetrisch etwas nicht stimmt. Aber
bei dem hohen Compare-Wert sah ich den Versatz auf meinem
(Analog-)Oszilloskop nicht.
Zu Punkt 3: ich hatte mir bislang keine Gedanken darüber gemacht, wann
das TCCR0A bezüglich der Ausgänge greift, war irgendwie naiv davon
ausgegangen, dass das erst mit dem Aktivieren des Timers, also mit
TCCR0B, erfolgt - danke für den Hinweis.
Und damit ich selbst auch noch etwas Sinnvolles beitrage, im Anhang für
Jannik die C-Version (so ungefähr) Ihres Programmes (so gut ich's eben
konnte).
an Harald K.:
> ... oder ist, weil Hardware, vieeeeeeel zu kompliziert.
Sie ist hier schlicht unnötig. Und wenn Ihnen die Diskussion zu
langatmig sein sollte, brauchen Sie ja nicht mitzulesen.
Wenn man einen zusätzlichen I/O-Pin zum sinnlosen Verballern freihat, dann kann man das natürlich tun. Andere arbeiten ressourcensparend und versuchen nicht, teure I/Os für Banalitäten zu vergeuden. Klar, für unbenutzte I/O-Pins bekommt man ebensowenig Geld zurück wie für leergelassenes Flash-ROM, aber das ist halt nicht immer der Fall. Hier wäre es interessant zu wissen, wofür der Threadstarter das Komplementärsignal zu benötigen meint.
an Harald Kirnbichler: Also was mich betrifft, so versuche ich grundsätzlich so weit wie möglich auf den Fragesteller einzugehen - und da steht nun mal im Betreff "OC0A & OC0B". Es ist nicht meine Intention, sein Projekt zu verbessern (was ich in meiner Unkenntnis für 'Verbesserung' halte). Ihnen aber steht es natürlich frei, mit Jannik darüber eine längere Diskussion zu beginnen.
Harald K. schrieb: > Wenn man einen zusätzlichen I/O-Pin zum sinnlosen Verballern freihat, > dann kann man das natürlich tun. Genau. Deswegen würde ich über einen zusätzlichen Inverter allenfalls dann nachdenken, wenn's mit den Pins knapp wird. Und auch dann vermutlich zuerst darüber, ob man nicht besser andere Pins funktional "sharen" könnte (ohne zusätzliche Hardware verbauen zu müssen). Grundprinzip ist: Jede zusätzliche Hardware erhöht die Kosten und die Ausfallwahrscheinlichkeit.
S. L. schrieb: > Also was mich betrifft, so versuche ich grundsätzlich ... Das kannst Du gerne tun. Andere hören halt nicht gleich mit dem Denken auf, sondern überlegen, wie man das eigentliche Problem lösen kann. Denn wie die Erfahrung zeigt, die manch einer hier hat (auch ein "C-Hater" hat Erfahrung!), haben viele Fragesteller sich in einer Problemlösung verrannt und versuchen ein Problem zu lösen, das sich entweder mit minimalem Aufwand anders lösen ließe oder letztlich gar nicht besteht, weil an anderer Stelle ein Designfehler vorliegt. Ein Beispiel dafür sind die verschiedenen Versuche eines einzelnen, das trivale Thema "Tastenabfrage" zu lösen ... dem einen oder anderen mögen die diversen Threads zum Thema noch in Erinnerung sein, ist noch gar nicht so lange her. Ob das hier der Fall ist, weiß ich natürlich nicht, aber meiner Ansicht nach ist jemandem besser geholfen, wenn ihm nicht nur wortgetreu seine Aufgabe gelöst wird, sondern auch Lösungsalternativen vorgestellt werden und sogar Rückfragen gestellt werden, wozu das ganze überhaupt gut sein soll.
C-hater schrieb: > Grundprinzip ist: Jede zusätzliche Hardware erhöht die Kosten und die > Ausfallwahrscheinlichkeit. In der Theorie und der Massenproduktion. In der Praxis des Bastlers und der Kleinstserien ist das bedeutungslos. "Ich bin dafür, die Dinge so weit wie möglich zu vereinfachen. Aber nicht weiter." Albert Einstein
Falk B. schrieb: > C-hater schrieb: >> Grundprinzip ist: Jede zusätzliche Hardware erhöht die Kosten und die >> Ausfallwahrscheinlichkeit. > > In der Theorie Nein, auch in der Praxis. > und der Massenproduktion. Nö, da wird es halt nur statistisch unwiderlegbar nachweisbar. Diese Erkenntnisse aus der Massenproduktion für Einzelstücke zu ignorieren, ist trotzdem nur genau eins: ziemlich idiotisch... Denn das Gesetz gilt natürlich auch für das Einzelstück. Es ist halt nur nicht nachweisbar, dass es dafür genauso gilt. Es gibt allerdings auch keinerlei logischen Grund, warum es dafür nicht genauso gelten sollte...
Es gibt auch AVRs, die haben extra invertierte Ausgänge, z.B. ATtiny85, ATtiny861. Und zusätzlich einen Dead-Time Generator. Der ATtiny861 hat sogar 3 OC1x /OC1x Paare (x = A, B, D).
Harald K. schrieb: > Wenn man einen zusätzlichen I/O-Pin zum sinnlosen Verballern freihat, > dann kann man das natürlich tun. Wenn eine Platine schon fertig ist, wird es schwieriger, einen 74HC... zu schalten, als das Programm etwas zu ändern. Wenn ein I/O-Pin unbenutzt bleibt, gibt man 1/28 des Preises von ATMega328 leider nicht zurück :) Ansonsten plädiere ich als Amateur, der keine Serienfertigung macht, dafür, MK mit mehr Pins als ATMega328 zu wählen. Ich selbst nehme so gut wie immer ATMega1284 oder ab und zu ATMega2560. Die Beschränkung auf 2 MK bringt für Amateur mehrere Vorteile.
:
Bearbeitet durch User
Peter D. schrieb: > Es gibt auch AVRs, die haben extra invertierte Ausgänge > Und zusätzlich einen Dead-Time Generator Timer/Counter Type D (TCD) Generating Complementary Driving Signals https://ww1.microchip.com/downloads/en/Appnotes/TB3212-Getting-Started-with-TCD-DS90003212.pdf
Moin zusammen, ich melde mich auch mal wieder. Ich habe nach den ersten Hinweisen erstmal weiter programmiert und stand jetzt vor dem Problem, dass der FOC0B teilweise aufgibt und wieder das nicht invertierte Signal an PD5 geliefert wird. (So wie Volker B. das denke ich vorhergesehen hat) Das wäre tatsächlich fatal, da ich mal eine Phase-Shifted-PWM Ansteuerung einer Vollbrücke ausprobieren wollte (mit den Optionen die ich hier habe=>Arduino Nano) und naja wenn beide Mosfets einer Halbbrücke durchschalten gibt's ja bekanntlich nen Kurzschluss. Wie die Vollbrücke schon vermuten lässt habe ich auch T/C2 genau gleich programmiert. Also insgesamt 4 125kHz Signale. FOC2B funktioniert einwandfrei. OCR2A & OCR2B werden nach dem setup nicht mehr geändert. Das Problem von FOC0B kommt denke ich daher, dass ich OCR0A & OCR0B in der main des öfteren um 1 erhöhe bzw verringere und in einer Compare Match ISR wieder auf den Ursprungs Wert zurücksetze um die Phasenverschiebung zu Erzeugen. Eine andere Möglichkeit könnte am ADC liegen, da die Ausgangsspannung am Ende über den Phase-shift geregelt werden soll. Kann das daran liegen oder hat jemand eine andere Vermutung? Eigentlich denke ich mir, dass FOC0B den Pin einmal anfangs toggelt und das später keinen Einfluss mehr haben sollte
:
Bearbeitet durch User
Wenns noch um den Mega328 geht, mein FU Projekt hat das vor Jahren schon mit 3 Timern gemacht. Jeder Timer hat komplementäre Ausgänge und alle 3 laufen synchron: https://www.mikrocontroller.net/articles/3-Phasen_Frequenzumrichter_mit_AVR
> OCR0A & OCR0B in der main des öfteren um 1 erhöhe bzw verringere
Es muss natürlich sichergestellt sein, dass dies nicht unmittelbar vor
Erreichen des Compare-Match geschieht - wie sieht die Stelle in der
Main-Schleife denn aus?
Jannik schrieb: > Das Problem von FOC0B kommt denke ich daher, dass ich OCR0A & OCR0B in > der main des öfteren um 1 erhöhe bzw verringere und in einer Compare > Match ISR wieder auf den Ursprungs Wert zurücksetze um die > Phasenverschiebung zu Erzeugen. Ja, das ist natürlich tödlich. Zumal es völlig unmöglich ist, beide Register wirklich gleichzeitig zu schreiben. Da kann man nicht einfach wild drauflosschreiben, man muss sicherstellen, dass beide Schreibvorgänge abgeschlossen sind, bevor der nächste Compare-Match passiert. Am einfachsten geht das, wenn man ausschließlich in der ISR in diese Register schreibt, denn dann ist relativ sicher, dass der Match eben gerade passiert ist, bis zum nächsten also das Maximum an "Luft" bleibt. Um dasselbe in Main zu erreichen, ist sehr viel mehr Aufwand nötig.
S. L. schrieb: > wie sieht die Stelle in der > Main-Schleife denn aus?
1 | // ISR to reset OCR0A/B after the compare match value was reached
|
2 | // -> to keep 125kHz frequency
|
3 | ISR(TIMER0_COMPA_vect) { |
4 | uint8_t ui8_sreg = SREG; |
5 | OCR0A = OCR0B = 63; |
6 | SREG = ui8_sreg; |
7 | }
|
8 | |
9 | // ISR to count up
|
10 | ISR(TIMER1_COMPA_vect) { |
11 | uint8_t ui8_sreg = SREG; |
12 | ui32_counter++; |
13 | SREG = ui8_sreg; |
14 | }
|
15 | |
16 | void loop() { |
17 | |
18 | // Synchronize the signals of the two timer/counters
|
19 | if(syncSig == true) { |
20 | TCNT0 = 0; |
21 | TCNT2 = 0; |
22 | OCR0A = OCR0B = 129; // 129 for 0° phase shift // 65 = 0° |
23 | syncSig = false; |
24 | startUp = true; |
25 | }
|
26 | |
27 | // PWM hart programmiert langsam hochfahren
|
28 | // 1 count = 3° & 62,5ns delay / 8 counts = 23° & 500ns delay
|
29 | if(startUp == true) { |
30 | if(ui32_counter >= 360) { // wait for 2s increase phase shift 180*2 180 counts = 1s |
31 | OCR0A = OCR0B = OCR0A + 1; |
32 | ui8_end++; // count the number of shifts |
33 | ui32_counter = 0; // reset counter |
34 | }
|
35 | |
36 | if(ui8_end >= 8) { // after 8 shifts (500ns) end the startup |
37 | startUp = false; // end start up |
38 | voltReg = true; // enter regulation via ADC |
39 | ui32_counter = 0; // reset counter |
40 | ui8_end = 0; // reset shift counter |
41 | }
|
42 | }
|
43 | |
44 | // set PWM by ADC voltage
|
45 | if((voltReg == true)) { |
46 | |
47 | if(ui32_counter >= 180) { |
48 | ADCSRA |= (1<<ADSC); //start conversion |
49 | while(ADCSRA&(1<<ADSC)); // wait till conversion is finished |
50 | ui16_adcVal = ADCL | (ADCH << 8); // save adc value |
51 | Serial.println(ui16_adcVal); |
52 | |
53 | if(ui16_adcVal > ui16_adcTop) { // if voltage is greater than treshold reduce signal shift |
54 | |
55 | OCR0A = OCR0B = OCR0A - 1; // set both in one line |
56 | }
|
57 | |
58 | if(ui16_adcVal < ui16_adcBottom) { // if voltage is smaller than treshold increase signal shift |
59 | |
60 | OCR0A = OCR0B = OCR0A + 1; |
61 | }
|
62 | |
63 | ui32_counter = 0; |
64 | ui8_end = 0; |
65 | }
|
66 | }
|
(Was das Programm genau macht, muss und will ich jetzt nicht verstehen) Wie bereits geschrieben, und von C-hater näher erläutert, muss gewährleistet sein, dass TCNT0 beim Schreiben von OCR0A hinreichend unter dem alten wie dem neuen Wert von OCR0A liegt. Was bei den verfügbaren 64 Takten (oder noch weniger im Verlauf?) Sorgfalt verlangt. Übrigens: Retten von SREG in der ISR - ich dachte, solchen Kleinkram nimmt C dem Programmierer ab?
Jannik schrieb: > [c] > > ISR(TIMER0_COMPA_vect) { > uint8_t ui8_sreg = SREG; > ... > ... > SREG = ui8_sreg; > } S. L. schrieb: > Übrigens: Retten von SREG in der ISR - ich dachte, solchen Kleinkram > nimmt C dem Programmierer ab? Hallo, nimmt es auch. Innerhalb einer ISR ist sowas nicht notwendig.
Also, um genau zu sein: die 64 bezog sich auf die Gesamtzeit; wenn das Schreiben von OCR0A im Main erfolgen soll/muss, dann ist/sind die ISR noch abzuziehen - das könnte eng werden.
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.