Forum: Mikrocontroller und Digitale Elektronik ATmega644 Timer: PWM mit gleicher Frequenz?


von A. P. (adrian_p)


Lesenswert?

Hallo

Ich habe kürzlich mit der Mikrocontroller-Programmierung angefangen und 
versuche gerade einen Brushless-Controller zu bauen. Im Moment teste ich 
die MOSFETs + PWM mit ein paar in Serie geschalteten LEDs.

Mir ist aufgefallen, dass (bei gleichem Prescaler und Output 
Compare-Wert) die LEDs bei den von Timer1 gesteuerten MOSFETs blinken. 
Bei den von Timer2 gesteuerten MOSFETs hingegen lassen sich die LEDs 
ohne sichtbares Blinken dimmen. Wenn ich den Prescaler bei Timer1 tiefer 
setze, habe ich dieses Problem nicht mehr. Da es sich um zwei 
verschiedene Timer handelt (16 und 8bit) nehme ich an, dass ich gewisse 
Einstellungen vornehmen muss, damit beide die gleiche Frequenz ausgeben 
können. Ich habe schon ein paar Modi (Phase Correct, Fast Pwm) 
durchprobiert, jedoch konnte ich dieses Problem einfach nicht lösen.

Könnte mir jemand mit der Lösung dieses Problem helfen? Mein Ziel ist 
es, dass beide Timer bei gleichem Prescaler und OCRxx *die gleiche 
Frequenz ausgeben* (wenn dies überhaupt möglich ist). Ich benutze einen 
ATmega644 und habe zuletzt erfolglos diese Einstellungen verwendet:
1
//PWM initialisieren
2
inline void initialize_MOSFET_PWM()
3
{
4
  //Timer 1 (16Bit): Fast-PWM, 8bit bis 255
5
  TCCR1A = (1<<WGM22) | (0<<WGM21) | (1<<WGM20) | (1<<COM2B1) | (1<<COM2A1);
6
  TCCR1B = PRESCALER_256;
7
8
  //Timer 2 (8Bit): Fast-PWM bis 255
9
  TCCR2A = (1<<WGM21) | (1<<WGM20) | (1<<COM2B1);
10
  TCCR2B = PRESCALER_256;
11
}

Ich bin neu auf dem Gebiet. Seid also nicht zu hart zu mir :)

Gruss
Adrian

von H.Joachim S. (crazyhorse)


Lesenswert?

quick & dirty:
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 46,875 kHz
// Mode: Phase correct PWM top=0xFF
// OC0A output: Inverted PWM
// OC0B output: Inverted PWM
TCCR0A=0xF1;
TCCR0B=0x04;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 46,875 kHz
// Mode: Ph. correct PWM top=0x00FF
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xA1;
TCCR1B=0x04;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

Das ist das, was CodeVision ausspuckt (bei eigenen Projekten ersetz ich 
das entsprechend durch lesbare Einstellungen)
Richtig ist es aber i.a., hab noch nie einen Fehler entdeckt.

von Stefan E. (sternst)


Lesenswert?

1
  TCCR1A = (1<<WGM22) | (0<<WGM21) | (1<<WGM20) | (1<<COM2B1) | (1<<COM2A1);
Drei WGM-Bits in einem Register? Sicher nicht.
Und was haben die ganzen 2en da drin zu suchen? Die Bit-Positionen der 
unterschiedlichen Timer müssen nicht zwangsläufig übereinstimmen.

1
  TCCR1B = PRESCALER_256;
2
...
3
  TCCR2B = PRESCALER_256;
Die Prescaler-Einstellung der beiden Timer unterscheidet sich. Wenn du 
den gleichen Wert in beide Register schreibst, dann hast du 
unterschiedliche Einstellungen.


Allgemein: du musst mehr ins Datenblatt schauen.
"Ach, wenn diese beiden WGM-Bits in dem Register liegen, dann sind 
sicher die anderen auch dort."
"Ach, wenn dieser Wert den Prescaler dieses Timers auf 256 stellt, dann 
wird der selbe Wert das bei dem anderen Timer wohl auch machen."
Du kannst nicht einfach auf der Basis von Annahmen programmieren.

von H.Joachim S. (crazyhorse)


Lesenswert?

ups, Timer 1 und 2...

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 46,875 kHz
// Mode: Ph. correct PWM top=0x00FF
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xA1;
TCCR1B=0x04;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 46,875 kHz
// Mode: Phase correct PWM top=0xFF
// OC2A output: Non-Inverted PWM
// OC2B output: Non-Inverted PWM
ASSR=0x00;
TCCR2A=0xA1;
TCCR2B=0x06;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

von A. P. (adrian_p)


Lesenswert?

1
//PWM initialisieren
2
inline void initialize_MOSFET_PWM()
3
{
4
  //Timer 1 (16Bit): PhaseCorrect-PWM, 8bit bis 255
5
  TCCR1A = (0<<WGM11) | (1<<WGM10) | (1<<COM1B1) | (1<<COM1A1);
6
  TCCR1B = PRESCALER_256;
7
8
  //Timer 2 (8Bit): PhaseCorrect-PWM bis 255
9
  TCCR2A = (0<<WGM21) | (1<<WGM20) | (1<<COM2B1);
10
  TCCR2B = PRESCALER_256_8bit;
11
}

Dankeschön!

Es lag daran, dass derselbe Prescaler bei den jeweiligen Timern durch 
verschiedene Bitfolgen definiert ist. Während vorhin der eine mit 
Prescaler 1024 lief, hatte der andere gar keinen drinn => LEDs mit 
Prescaler blinken.

Auf jeden Fall danke für die schnelle Hilfe!

Gruss
Adrian

von H.Joachim S. (crazyhorse)


Lesenswert?

PRESCALER_256_8bit....
Damit hast beim nächsten Mal mit Timer0 ein Problem. Der ist 8bit, 
dennoch ist die prescaler-Einstellung anders.
Keine gute Idee das ganze:-)

von A. P. (adrian_p)


Lesenswert?

1
  TCCR2B = PRESCALER_64_Timer2;

Stimmt. Danke! Timer0 brauch ich später auch noch.

Wer auch immer auf die Idee gekommen ist, diese Einstellungen 
unterschiedlich zu definieren... :)

von H.Joachim S. (crazyhorse)


Lesenswert?

Hm, naja.
Du bist meines Wissens nach der erste, der dafür ne Konstante/define 
einsetzen will.
Will man das nicht unbedingt, ist es auch kein Problem.

Du schreibst wohl was in der Art:

#define PRESCALER_64_Timer2 1<<CS22|1<<CS21     //clk/256
.
.
TCCR2B=PRESCALER_64_Timer2;

Da du das aber nirgendwo anders brauchst - schreib doch gleich:
TCCR2B=1<<CS22|1<<CS21;     //clk/256

von A. P. (adrian_p)


Lesenswert?

Ich bin noch daran einen geeigneten Prescaler für den Brushless-Motor zu 
finden. Ich habe ein paar Prescaler definiert, damit ich später ohne 
Mühe und schnell zwischen den verschiedenen Prescalern wechseln kann und 
immer weiss, welcher ausgewählt ist.

Schlussendlich, im Endprodukt, ist dies natürlich unnötig. Da hast du 
recht.

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.