Forum: Mikrocontroller und Digitale Elektronik Frequenzgenerator mit variablem Duty-Cycle


von Markus B. (scrap)


Lesenswert?

Hallo
Ich möchte gern einen einfachen Frequenzgenerator (Rechteck) bauen mit 
variablem Duty-Cycle.
Ich habe das heute schon programmiert mit einem Attiny25:
PWM im CTC Modus
Lässt sich mit verschiedenen Prescalern in einem weitem Frequenzbereich 
einstellen.
Nun stellt sich mir die Frage, bekommt man die Auflösung genauer hin?
sowohl von Duty als auch von der Frequenz? (denn je höher die Frequenz 
in einem Prescalerbereich, desto schlechter die Duty-Auflösung)

konkret möchte ich einen Blitzer machen, welcher GENAU! 50hz macht (und 
noch andere Sachen)
Ich habe hier leider nur Quarze mit 4,8,12,16Mhz

Mit einem 16Mhz Quarz, einem Prescaler von 2048 bekomme ich 50,08Hz hin, 
genauer wirds nicht, weil immer krumme Zahlen rauskommen.
Selbst wenn ich den Systemtakt massiv runternehmen würde, komme ich 
nicht hin.

Ich hatte mal irgendwo eine Lösung mit 16bit Auflösung gefunden, weiß 
aber nichtmehr ob duty oder frequenz.
gibt es hier noch andere Lösungsansätze?

von John (Gast)


Lesenswert?

Markus B. schrieb:
> Mit einem 16Mhz Quarz, einem Prescaler von 2048 bekomme ich 50,08Hz

Versuch es mal mit einem Vorteiler von 512.

Wie genau soll dein "GENAU!" sein?

Markus B. schrieb:
> gibt es hier noch andere Lösungsansätze?

3,2768 MHz
http://www.reichelt.de/Quarze/3-2768-HC18/3//index.html?ACTION=3&GROUPID=3173&ARTICLE=2376&SEARCH=3%2C2768&OFFSET=16&WKID=0&;

6,5536 MHz
http://www.reichelt.de/Quarze/6-5536-HC18/3//index.html?ACTION=3&GROUPID=3173&ARTICLE=2646&SEARCH=6%2C5536%0A&OFFSET=16&WKID=0&;

von Markus B. (scrap)


Lesenswert?

genau heist genau, also dass ich mit einem geraden zahlenwert 
draufkomme.
3,2768 MHz funktioniert mit 512 prescaler, hab ich aber nicht da und das 
ganze soll eigentlich morgen fertig sein.
ich dachte es würde irgendwie elegant mit software gehen.

von John (Gast)


Lesenswert?

John schrieb:
> Versuch es mal mit einem Vorteiler von 512.

Und dann noch ein 16bit Timer der bis 625 Zählt.

von Thomas E. (thomase)


Lesenswert?

Markus B. schrieb:
> PWM im CTC Modus
Was ist das?
Entweder PWM oder CTC.

mfg.

von Michael H. (dowjones)


Lesenswert?

Markus B. schrieb:
> konkret möchte ich einen Blitzer machen, welcher GENAU! 50hz macht (und
> noch andere Sachen)

Naja, GENAU! wird man das mit einem Quarz ohnehin nicht so ohne weiteres 
hinbekommen, soo furchtbar präzise sind die Dinger ja net.

> gibt es hier noch andere Lösungsansätze?
Wenn's um die Größenordnung von 50 Hz geht kann man das auch locker 
mithilfe von Timerinterrupts "von Hand" erledigen. Dazu müsste man halt 
in jedem Interrupt den Timer für den folgenden Interrupt neu setzen; 
dadurch könnte man (bei einem Systemtakt von 10 MHz) prinzipiell auf 
0,0000001 Hz genau werden - soweit der Quarz das zulässt... Sicher, die 
Flanke würde mal 1/10 Mikrosekunde zu früh und mal 1/10 Mikrosekunde zu 
spät erfolgen, aber es wäre allemal besser als 50,08 Hz.

Wenn ich mich richtig erinnere, dann wird genau dieses Thema in dem 
Artikel "Die genaue Sekunde" behandelt: 
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC

von m.n. (Gast)


Lesenswert?

Markus B. schrieb:
> ich dachte es würde irgendwie elegant mit software gehen.

So geht es mit Steuerspannungen (Poti) 
http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp1
und so, wenn man lange Zeiten braucht, die man per Terminal eingibt 
http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp2

Es sollte nicht schwer fallen, beide Möglichkeiten nach Bedarf zu 
kombinieren.
Falls man höhere Frequenzen oder Auflösung braucht, bietet sich ein 
STM32F4xx an, der seine Timer mit 168MHz laufen lassen kann. Bei der 
Auflösung kommt man damit auf ca. 6 ns.

Soll ich Dir noch ein Programm dafür machen? ;-)

von foo (Gast)


Lesenswert?

Markus B. schrieb:
> Mit einem 16Mhz Quarz, einem Prescaler von 2048 bekomme ich 50,08Hz hin,
> genauer wirds nicht, weil immer krumme Zahlen rauskommen.

Ohne Abgleich wird der Oszillator aber auch nicht sehr viel genauer 
sein.
Kannst du die Oszillatorfrequnz wenigstens genau messen?

Dann kannst du einen Interrupthandler bauen, der mit viel geringerem 
Vorteiler z.B. 64 auskommt.
Diesen 250kHz Interrupt lässt du eine 4 Byte Addition so machen, dass 
die Summe alle 20ms überläuft.
Das MSB kopierts du einfach auf den Output-Pin.

Z.B. sind bei 250kHz 250000/50 = 5000 Additionen pro Periode 
erforderlich.

Bei einer 4-Byte Addition sollte jedes Mal  4294967296 / 5000 = 
858993,4592 addiert werden.
Nächste Näherung für den Summanden ist 858993 und somit passiert der 
Überlauf tatsächlich nach 5000,0026728972180215671140509876  Interrupts.
Das bedeutet dass die Ausgangsfrequenz meist bei genau 16E+6/(5000*64)= 
50Hz liegt und gelegentlich ein 4µs längerer Zyklus von 16E+6/(5001*64)= 
49,99Hz stattfindet.
Der Vorteil ist, dass man auch bei ungenauen Quarzfrequenzen die 
Ausgangsfrequenz sehr präzise einstellen kann, indem man nur den Wert 
858993 etwas ändert.

von Oldie (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Entweder PWM oder CTC.
Das ist Quatsch. Es gibt bei einigen µCs die Möglichkeit, den
Max-Count festzulegen (CTC) und innerhalb dieses Zählablaufs
PWM-Aufgaben zu erledigen.

Jetzt aber zum Wunsch von  Markus B. (scrap):
> konkret möchte ich einen Blitzer machen, welcher GENAU!
  50hz macht (und noch andere Sachen)

Da möchte jemand ALLES und zwar SOFORT, aber kann nicht mal
mitteilen, was da nun an Frequenz- und PWM-Auflösung feht.
Und das alles nur mit einem Tiny25 und Software, wobei die
Software aber nicht zu viel Gehirnschmalz kosten darf...

Grundsätzlich (wenn der Tiny25 sonst nicht viel zu tun hat),
ist das möglich, kostet aber Gehirnschmalz...

Man könnte einen kleineren Vorteilerfaktor nehmen, das erhöht
die Frequenzauflösung.

Z.B. 16.000.000 Hz / 256 = 62.500 Hz

62.500 Hz / 1250 = 50,000 Hz

Das sind 5 Zählerdurchläufe (CTC) von 0...249

Wenn der Blitz nur 0...3,9 ms lang sein soll,
musst du die Durchläufe mitzählen und bei jeden 5.
Durchlauf die PWM aktivieren (Auflösung = 16 µs).

Oder geschickt mit Compare-Match-Interrupts arbeiten.

von Markus B. (scrap)


Lesenswert?

danke oldi, auf so eine idee bin ich noch garnicht gekommen.

ich sehe aber schon ich komme für "einfach" wohl um ein "krummes" quarz 
wohl nicht drumrum.
die quarzgenauigkeit ist mir hinreichend genau. jetzt noch toeranzen und 
temperaturabhänigkeiten ins spiel zu bringen ist overkill. aber wenn ich 
feststelle dass ich schon rein rechnerisch keine chance hab mein ziel zu 
erreichen ist es eben unbefriedigend.

von Thomas E. (thomase)


Lesenswert?

Oldie schrieb:
> Das ist Quatsch. Es gibt bei einigen µCs die Möglichkeit, den
> Max-Count festzulegen (CTC) und innerhalb dieses Zählablaufs
> PWM-Aufgaben zu erledigen.
Der einzige Quatsch ist das, was du hier erzählst.
Im CTC gibt es Clear, Set und Toggle. Das ist kein PWM, da der Ausgang 
nicht am Anfang des Zyklus gesetzt oder je nach Mode gelöscht wird. Mag 
sein, dass es Controller gibt, die das können. AVRs gehören nicht dazu.

Der Maxcount für  PWM wird nicht im CTC-Mode festgelegt, sondern im 
entsprechenden PWM-Mode.

Das, was du oben vorschlägst, ist ganz normale Software-PWM.

mfg.

von m.n. (Gast)


Lesenswert?

Markus B. schrieb:
> ich sehe aber schon ich komme für "einfach" wohl um ein "krummes" quarz
> wohl nicht drumrum.

Wie kommst Du darauf?
Weiter oben hatte ich doch auf Programme verwiesen, die bestens ein 
genaues Timing erzeugen, auch mit einem ATtiny25 mit 8-Bit Timer.
Hast Du das garnicht gelesen oder hat Dich die Lektüre überfordert?

von Thomas E. (thomase)


Lesenswert?

1
#define MAX F_CPU / 1000 / 50
2
unsigned int nDuty = 10;
3
4
void InitTimer(void)
5
{
6
  TCCR0B = (1 << CS01);
7
  TCCR0A = (1 << WGM01);
8
  OCR0A = 124;
9
  TIMSK |= (1 << OCIE0A);
10
  DDRB |= (1 << 0);
11
}
12
ISR(TIMER0_COMPA_vect)
13
{
14
  static unsigned int nCount = 0;
15
  nCount++;
16
  if(nCount == MAX - nDuty)
17
  {    
18
    TCCR0A |= (1 << COM0A1) | (1 << COM0A0);
19
  }
20
  else if(nCount == MAX)
21
  {
22
    PORTB &= ~(1 << 0);    
23
    TCCR0A &= ~((1 << COM0A1) | (1 << COM0A0));    
24
    nCount = 0;
25
  }
26
}

Auflösung 62,5 µs bei 16 MHz.

mfg.

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
Noch kein Account? Hier anmelden.