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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Herrmann (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von Arno (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
korrigiere OCR2A = 200;

von S. Landolt (Gast)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
S. Landolt schrieb:
> PB3 ist OC2A

Richtig.

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

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von Herrmann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Habs hin bekommen danke :)

von Arno (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Herrmann schrieb:
> im Mode 3 kann ich keinen Dutycycle
> einstellen.

Das stimmt so nicht.

MfG, Arno

von Herrmann (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.