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
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 | }
|
> Ich bekomme einfach keinen Output auf PB3 was ist mein Fehler?
PB3 ist OC2A, offenbar soll die Pulsbreitenmodulation aber auf OC2B
erfolgen,.
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); |
Aber für OC2A ist das SFR OCR2A zuständig, und dieses ist im Modus 7 der TOP-Wert.
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
okay entschuldige ich bin etwas neu im programmieren mit Registern. Was muss ich jetzt schreiben um eine PWM an PB3 zu bekommen? :)
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
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.
> 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.
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.
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.
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.
Dann würde ich, als ersten Ansatz, für Timer1 & Timer2 den Vorteiler 1024 versuchen.
Herrmann schrieb: > im Mode 3 kann ich keinen Dutycycle > einstellen. Das stimmt so nicht. MfG, Arno
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 | }
|
> 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.