Forum: Mikrocontroller und Digitale Elektronik PWM auf PB3 Atmega 328 P


von Herrmann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich verstehe nicht warum mein Code nicht funktioniert.
Ich bekomme einfach keinen Output auf PB3 was ist mein Fehler?
Für Hilfe wäre ich sehr Dankbar.

Viele Grüße Herrmann

von Herrmann (Gast)


Lesenswert?

Hier der Code nochmal in Text Form

1
 //Achte immer darauf welche Pwm Pins welche Timer benötigen!
2
3
void setup(){ 
4
  // WGM22/WGM21/WGM20 all set -> Mode 7, fast PWM
5
  // Set OC2B at bottom, clear OC2B at compare match
6
  TCCR2A = 0;
7
  TCCR2B = 0;
8
  //Fast PWM Mode
9
  TCCR2B |= (1<<WGM22);
10
  TCCR2A |=(1<<WGM21);
11
  TCCR2A |=(1<<WGM20); 
12
  TCCR2A |= (1<<COM2A1);
13
    
14
  // prescaler = 8
15
  TCCR2B &= ~(1<<CS22);
16
  TCCR2B |= (1<<CS21);
17
  TCCR2B &= ~(1<<CS20);
18
  
19
  
20
  
21
  //Hier Frequenz einstellen wir lassen aber auf 10 kHz  
22
  OCR2A = 100;
23
  //Hier von 0-200 Dutycycle einstellen
24
  OCR2B = 0;
25
  //So schalten wir die Pwm ein bzw. aus
26
 
27
  DDRB |= (1<<PB3);
28
29
 
30
} 
31
void loop() {
32
 
33
 //Loop wird hier stark verlangsamt
34
 OCR2B = map(analogRead(A0),0,1023,0,200);
35
  
36
  }

von S. Landolt (Gast)


Lesenswert?

> Ich bekomme einfach keinen Output auf PB3 was ist mein Fehler?

PB3 ist OC2A, offenbar soll die Pulsbreitenmodulation aber auf OC2B 
erfolgen,.

von Herrmann (Gast)


Lesenswert?

S. Landolt schrieb:
> PB3 ist OC2A, offenbar soll die Pulsbreitenmodulation aber auf OC2B
> erfolgen,.

Je genau deswegen schreibe ich ja auch :
1
TCCR2A |= (1<<COM2A1);

von S. Landolt (Gast)


Lesenswert?

Aber für OC2A ist das SFR OCR2A zuständig, und dieses ist im Modus 7 der 
TOP-Wert.

von Arno (Gast)


Lesenswert?

OC2A (der Pin) wird abhängig von OCR2A (dem Register) gesetzt/gelöscht. 
Nicht abhängig von OCR2B.

Ich hab das im Datenblatt nicht geprüft, vermute aber anhand der 
Kommentare "Frequenz einstellen", du hast einen CTC-Modus ausgewählt, 
d.h. der Timer läuft hoch bis OCR2A. Dann kannst du OC2A nicht als 
PWM-Ausgang verwenden, weil der Timer nie größer wird als OCR2A.

Das ist mit etwas anderen Worten das gleiche, was S. Landolt auch schon 
gesagt hat.

Es ergibt ferner im CTC-Modus keinen Sinn, wenn OCR2A 100 ist, in OCR2B 
Werte bis 200 zuzulassen. Der Timer läuft eh nur bis 100.

MfG, Arno

von Herrmann (Gast)


Lesenswert?

okay entschuldige ich bin etwas neu im programmieren mit Registern. Was 
muss ich jetzt schreiben um eine PWM an PB3 zu bekommen? :)

von Herrmann (Gast)


Lesenswert?

Arno schrieb:
> Es ergibt ferner im CTC-Modus keinen Sinn, wenn OCR2A 100 ist, in OCR2B
> Werte bis 200 zuzulassen. Der Timer läuft eh nur bis 100.

das ist richtig hier habe ich einen fehler gemacht ich wollte
1
OCR2A = 100;
 schreiben

von Herrmann (Gast)


Lesenswert?

korrigiere OCR2A = 200;

von S. Landolt (Gast)


Lesenswert?

Also entweder PWM im Modus 7 auf OC2B, das liegt auf PD3, oder PWM im 
Modus 3 auf OC2A (PB3), dann allerdings lässt sich die Frequenz nur sehr 
grob per Vorteiler einstellen.

von Georg M. (g_m)


Lesenswert?

S. Landolt schrieb:
> PB3 ist OC2A

Richtig.

OC2A ---> PB3
OC2B ---> PD3

von S. Landolt (Gast)


Lesenswert?

> Was muss ich jetzt schreiben um eine PWM an PB3 zu bekommen?

Als erster Versuch: Modus 3 verwenden, d.h. 'TCCR2B |= (1<<WGM22)' 
weglassen und 'OCR2A = map(analogRead...' schreiben.

von Herrmann (Gast)


Lesenswert?

S. Landolt schrieb:
> Also entweder PWM im Modus 7 auf OC2B, das liegt auf PD3, oder PWM im
> Modus 3 auf OC2A (PB3), dann allerdings lässt sich die Frequenz nur sehr
> grob per Vorteiler einstellen.

Okay Danke also vielleicht erkläre ich mal mein Vorhaben. Ich möchte auf 
PB1,PB2 und PB3 eine PWM ausgeben im Mode 3 kann ich keinen Dutycycle 
einstellen. Ich benötige allerdings eine Frequenz von 10 kHz und einen 
variablen Dutycycle.

von S. Landolt (Gast)


Lesenswert?

Für diese Anforderungen sehe ich bei den Gegebenheiten keine Lösung.

Timer2 im Modus 3, mit Vorteiler 1024 bei (vermutlich) 16 MHz, ergäbe 
15.6 kHz, doch weit weg von 10 kHz.

Beitrag #6536646 wurde vom Autor gelöscht.
von Herrmann (Gast)


Lesenswert?

Okay Entschuldigung die genaue Frequenz ist nicht so wichtig PB1, PB2, 
PB3 sollten nur alle die gleiche Frequenz haben so um die 10kHz es muss 
nicht genau 10 KHz sein +-3kHz sind egal.

von S. Landolt (Gast)


Lesenswert?

Dann würde ich, als ersten Ansatz, für Timer1 & Timer2 den Vorteiler 
1024 versuchen.

von Herrmann (Gast)


Lesenswert?

Habs hin bekommen danke :)

von Arno (Gast)


Lesenswert?

Herrmann schrieb:
> im Mode 3 kann ich keinen Dutycycle
> einstellen.

Das stimmt so nicht.

MfG, Arno

von Herrmann (Gast)


Lesenswert?

Jup hab ich auch gemerkt den dutycycle kann man sehr wohl einstellen, 
hier noch mein fertiger code:
1
//Dutycycle
2
uint8_t dtc = 0;
3
4
void setup(){ 
5
 
6
  setPwmPin9_10();
7
  setPwmPin11();
8
 
9
  }
10
  
11
  void loop() {
12
 
13
  //Loop wird hier stark verlangsamt
14
  dtc = map(analogRead(A0),0,1023,0,255);
15
  OCR1A = dtc;
16
  OCR1B = dtc;
17
  OCR2A = dtc;
18
  
19
   
20
  }
21
22
23
24
  void setPwmPin9_10(){
25
  // Reset Timer Register
26
  TCCR1A = 0;
27
  TCCR1B = 0;
28
  //Fast PWM Mode 
29
  TCCR1A |= (1<<WGM10);
30
  TCCR1B |= (1<<WGM12);
31
  //Setze Compare Modi non inverting Mode!
32
  TCCR1A |= (1<<COM1B1);
33
  TCCR1A |= (1<<COM1A1);
34
35
  //Setze Prescaler 8
36
  TCCR1B &= ~(1<<CS10);
37
  TCCR1B |=  (1<<CS11);
38
  TCCR1B &= ~(1<<CS12);
39
  //Setze Compare Values
40
  OCR1B = 0;
41
  OCR1A = 0;
42
  //Setze Pin 9 und 10 für aktiven PWM ausgang
43
  DDRB |= (1<<PB1);
44
  DDRB |= (1<<PB2); 
45
 }
46
47
  void setPwmPin11(){
48
  // Reset Timer Register
49
  TCCR2A = 0;
50
  TCCR2B = 0;
51
  //Fast PWM Mode TOP 0xFF
52
  TCCR2A |=(1<<WGM21);
53
  TCCR2A |=(1<<WGM20); 
54
  //Setze Compare Modi non inverting Mode!
55
  TCCR2A |= (1<<COM2A1);
56
  // prescaler = 8
57
  TCCR2B &= ~(1<<CS22);
58
  TCCR2B |= (1<<CS21);
59
  TCCR2B &= ~(1<<CS20);
60
  //Setze Compare Value
61
  OCR2A = 0;
62
  //Setze Pin11 afür aktiven PWM ausgang
63
  DDRB |= (1<<PB3);
64
    
65
    
66
  }

von S. Landolt (Gast)


Lesenswert?

> Habs hin bekommen danke :)

Prima!
Ich hatte nämlich übersehen, dass beim Timer2 ja auch noch durch 2^8 = 
256 geteilt wird, damit sieht es dann deutlich besser aus, z.B. 16 MHz 
/256 /8 = 7.8 kHz.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

auch wenn der Timer scheinbar das macht was er soll, sollte man in der 
Arduino IDE alle Timerregister (TCCRnx und TIMSKn) vorher löschen. Die 
werden mittels setup() im Hintergrund für analogWrite voreingestellt. 
Das schützt vor unliebsamen Überraschungen wenn der Timer plötzlich 
nicht das macht was er eigentlich sollte. Ich selbst beginne mit TCCRnB, 
damit der Timer erstmal gestoppt ist.

Für die Prescalereinstellerei noch 2 Funktionen die einem das Leben 
leichter machen. Kannste auf jeden Timer anpassen.
1
void runTimer1 (const unsigned int prescaler)
2
{
3
  switch (prescaler) {  
4
    case    1 : TCCR1B |= _BV(CS10);              break;
5
    case    8 : TCCR1B |= _BV(CS11);              break;
6
    case   64 : TCCR1B |= _BV(CS11) | _BV(CS10);  break;
7
    case  256 : TCCR1B |= _BV(CS12);              break;
8
    case 1024 : TCCR1B |= _BV(CS12) | _BV(CS10);  break;
9
    default :   break;
10
  }  
11
}
12
13
14
void stopTimer1 (void)
15
{
16
  TCCR1B &= ~( _BV(CS12) | _BV(CS11) | _BV(CS10) );
17
}

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