Forum: Compiler & IDEs ATmega164P Fast PWM keine funktion


von Sebastian S. (sebastian_s25)


Lesenswert?

Hi Leute

und wieder eine PWM Frage. Ich hab leider nix passendes in der Suche 
gefunden, also muss ich jetzt einen neuen Beitrag erstellen...

Folgendes, ich will mit meinem ATmega164P 4 Relais ansteuern. Um energie 
zu sparen, will ich die PWMs der Ports PD4,5 (OC1B/OC1A) und PD6,7 
(OC2B/OC2A) verwenden.

Jetzt hab ich alles schoen ausm Datenblatt rausgelesen und programmiert. 
Leider bekomm ich aber nur am PD6 (OC2B) ein Signal!!

Die anderen Bleiben tot...

Hier ist mal die Definition der Pins
1
#define OC1A_PWM     PD5
2
#define OC1A_PWM_PORT   PORTD
3
#define OC1A_PWM_DDR  DDRD
4
5
#define OC1B_PWM     PD4
6
#define OC1B_PWM_PORT   PORTD
7
#define OC1B_PWM_DDR  DDRD
8
9
#define OC2A_PWM     PD7
10
#define OC2A_PWM_PORT   PORTD
11
#define OC2A_PWM_DDR  DDRD
12
13
#define OC2B_PWM     PD6
14
#define OC2B_PWM_PORT   PORTD
15
#define OC2B_PWM_DDR  DDRD

Dann ist hier mein .c in dem ich die Funktionen und die 
Initialisierungen habe
1
/**** OC1A/B ****************************/
2
3
void OC1A_B_PWM_Init(void)
4
{
5
  OC1B_PWM_DDR = (1<< OC1B_PWM);
6
  OC1A_PWM_DDR = (1<< OC1A_PWM);
7
8
  TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM10) | (1<<WGM11);
9
  TCCR1B = (1<<CS10);
10
}
11
12
void OC1A_PWM_OFF(void)
13
{
14
  OCR1AH = 0x00;
15
  OCR1AL = 0x00;
16
}
17
18
void OC1A_PWM_Static(void)
19
{
20
  OCR1AH = 0x00;
21
  OCR1AL = 0xFF;
22
}
23
24
void OC1A_PWM_ON_8bit(uint8_t OCRValue)
25
{
26
  OCR1AH = 0x00;
27
  OCR1AL = OCRValue;
28
}
29
30
void OC1B_PWM_OFF(void)
31
{
32
  OCR1BH = 0x00;
33
  OCR1BL = 0x00;
34
}
35
36
void OC1B_PWM_Static(void)
37
{
38
  OCR1BH = 0x00;
39
  OCR1BL = 0xFF;
40
}
41
42
void OC1B_PWM_ON_8bit(uint8_t OCRValue)
43
{
44
  OCR1BH = 0x00;
45
  OCR1BL = OCRValue;
46
}
47
48
/**** OC2 ****************************/
49
50
void OC2A_B_PWM_Init(void)
51
{
52
  OC2A_PWM_DDR = (1<< OC2A_PWM);
53
  OC2B_PWM_DDR = (1<< OC2B_PWM);
54
55
  TCCR2A = (1<<COM2A1) | (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);
56
  TCCR2B = (1<<CS20);
57
}
58
59
void OC2A_PWM_OFF(void)
60
{
61
  OCR2A = 0x00;
62
}
63
64
void OC2A_PWM_Static(void)
65
{
66
  OCR2A = 0xFF;
67
}
68
69
void OC2A_PWM_ON(uint8_t OCRValue)
70
{
71
  OCR2A = OCRValue;
72
}
73
74
void OC2B_PWM_OFF(void)
75
{
76
  OCR2B = 0x00;
77
}
78
79
void OC2B_PWM_Static(void)
80
{
81
  OCR2B = 0xFF;
82
}
83
84
void OC2B_PWM_ON(uint8_t OCRValue)
85
{
86
  OCR2B = OCRValue;
87
}

und aufrufen tu ich sie so
1
void Relay1_ON(uint8_t PWM)
2
{
3
  OC1B_PWM_Static();
4
  _delay_ms(10);
5
  OC1B_PWM_ON_8bit(PWM);
6
}
7
8
void Relay1_OFF()
9
{
10
  OC1B_PWM_OFF();
11
}
12
13
void Relay2_ON(uint8_t PWM)
14
{
15
  OC1A_PWM_Static();
16
  _delay_ms(10);
17
  OC1A_PWM_ON_8bit(PWM);
18
}
19
20
void Relay2_OFF()
21
{
22
  OC1A_PWM_OFF();
23
}
24
25
void Relay3_ON(uint8_t PWM)
26
{
27
  OC2B_PWM_Static();
28
  _delay_ms(10);
29
  OC2B_PWM_ON(PWM);
30
}
31
32
void Relay3_OFF()
33
{
34
  OC2B_PWM_OFF();
35
}
36
37
void Relay4_ON(uint8_t PWM)
38
{
39
  OC2A_PWM_Static();
40
  _delay_ms(10);
41
  OC2A_PWM_ON(PWM);
42
}
43
44
void Relay4_OFF()
45
{
46
  OC2A_PWM_OFF();
47
}
Alle 4 PWM-Ports sollten ohne Prescaler, auf Fast PWM (TOP 0xFF) 
eingestellt sein....

Hab ich da irgendwo was uebersehen?

mfg
Bastian

von Chris (Gast)


Lesenswert?

Relais steuert man nicht über eine PWM an, damit veringert sich die 
Haltekraft des E-Magneten. Was dann dazu führt dass du nicht mehr den 
angegebenen Strom darüber fließen lassen kannst.

von Sebastian S. (sebastian_s25)


Lesenswert?

Doch man kann es Relais ueber PWM ansteuern.

Das Relais braucht eine Mindestspannung zum sicheren Schalten (bei 
meinen 12V Relais min. 8,4V). Die Abfallspannung liegt aber viel weiter 
unten, bei ungefaehr 3V (laut DB 1,2V).

Ich nutze diese Toleranzen und die Traegheit der Spule jetzt aus und 
verringere durch meine PWM die Spannung von besagten 12 V auf die 8,4 V.

Somit ist immer noch sicher geschaltet...

Mein Problem ist aber das PWM und nicht ob es sinnvoll ist...

mfg
Bastian

von Chris (Gast)


Lesenswert?

Lass mich raten du initializierst Port PD6 als letztes. So wie du das 
machst überschreibst du immer deine letze zuweisung.

Damit
OC1A_PWM_DDR = (1<< OC1A_PWM); setzt du genau das eine Bit uns löscht 
alle anderen.
 machst du das aber so
OC1A_PWM_DDR |= (1<< OC1A_PWM);
setzt du das  eine Bit und übernimmst die anderen so wie sie stehen.

Daher ist nur der letzte Port den du  initializierst als Ausgang 
geschaltet.

Grüße

von Anton (Gast)


Lesenswert?

1. Relais lassen sich sehr wohl per PWM nach dem
   Einschalten in der Leistungsaufnahme drosseln,
   Mache ich gelegentlich auch.

2. Denke bitte daran daß bei den Atmegas die Pins
   mit den Sonderfunktionen wie z.B. PWM aolange als
   "normaler" Pin arbeiten, bis die "Sonderfunktion"
   z.B. PWM aktiviert wird, dann wird der Pin automatisch
   auf die Sonderfunktion umgeschaltet. Die im
   "Normalbetrieb" definierten Bedingungen (Richtung, Low/High)
   bleiben aber erhalten. Wird die Sonderfunktion beendet
   gelten wieder die Normal-Betriebs-Bedingungen.

von Sebastian S. (sebastian_s25)


Lesenswert?

Chris schrieb:
> Lass mich raten du initializierst Port PD6 als letztes. So wie du das
> machst überschreibst du immer deine letze zuweisung.
>
> Damit
> OC1A_PWM_DDR = (1<< OC1A_PWM); setzt du genau das eine Bit uns löscht
> alle anderen.
>  machst du das aber so
> OC1A_PWM_DDR |= (1<< OC1A_PWM);
> setzt du das  eine Bit und übernimmst die anderen so wie sie stehen.
>
> Daher ist nur der letzte Port den du  initializierst als Ausgang
> geschaltet.
>
> Grüße

Danke Chris!!

Genau das hab ich ueber Stunden gesucht!! Dass mir immer wieder solche 
dummen Fehler unterlaufen!! Und dann selber nicht finden...

Danke nochmal

mfg

Bastian

von Sebastian S. (sebastian_s25)


Lesenswert?

Einen "Fehler" hab ich aber noch...

bei meinem OC2 PWMs hab ich wenn ich in das OCR Register 0x00 
reinschreib immer wieder Peaks drin. Ist das normal?

Bei den OC1 PWMs kommts nicht.

Und ich hab 2 unterschiedliche frequenzen, obwohl ich den Teiler auf 1 
gestellt hab!!

Ausgebesserte Fehler:
1
void OC1A_B_PWM_Init(void)
2
{
3
  OC1B_PWM_DDR |= (1<< OC1B_PWM);
4
  OC1A_PWM_DDR |= (1<< OC1A_PWM);
5
6
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM10) | (1<<WGM12);
7
  TCCR1B |= (1<<CS10);
8
}

hier hatte ich aus versehen noch auf den 10Bit phasecorrect PWM 
gestellt, jetzt is der 8Bit Fast PWM.
1
void OC2A_B_PWM_Init(void)
2
{
3
  OC2A_PWM_DDR |= (1<< OC2A_PWM);
4
  OC2B_PWM_DDR |= (1<< OC2B_PWM);
5
6
  TCCR2A |= (1<<COM2A1) | (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);
7
  TCCR2B |= (1<<CS20);
8
}

mfg
Bastian

von Chris (Gast)


Lesenswert?

Das ist normal, kannst auch hier 
http://www.mikrocontroller.net/articles/LED-Fading nachlesen. Ist zwar 
für LED-Fading aber das prinzip ist ja das Gleiche. Da steht auch drin 
was man machen kann, dass der PWM-Channel richtig low wird.

von Stefan E. (sternst)


Lesenswert?

Sebastian S. schrieb:
> Und ich hab 2 unterschiedliche frequenzen, obwohl ich den Teiler auf 1
> gestellt hab!!

Weil du Timer 1 nicht auf Fast-PWM eingestellt hast, sondern auf 
Phase-Correct-PWM. Deshalb hast du die Peaks dort auch nicht.

von Sebastian S. (sebastian_s25)


Lesenswert?

Ja das hab ich auch bemerkt, deswegen hab ich es ja nochmal 
reingestellt!

Beim zweiten mal ist der Fehler behoben. Aber trotzdem hab ich den 
Unterschied...

mfg
Bastian

von Stefan E. (sternst)


Lesenswert?

Sebastian S. schrieb:
> Beim zweiten mal ist der Fehler behoben. Aber trotzdem hab ich den
> Unterschied...

Nein, ist er nicht.
Du musst schon auch die Bits in den richtigen Registern setzen.

von Sebastian S. (sebastian_s25)


Lesenswert?

Kannst mir dann auch bitte sagen wo der Fehler ist?

Ich dachte, es würde so passen...

mfg
Bastian

von Stefan E. (sternst)


Lesenswert?

Sebastian S. schrieb:
> Kannst mir dann auch bitte sagen wo der Fehler ist?

Du versuchst ein Bit in einem Register zu setzen, das dort gar nicht 
existiert.

von Sebastian S. (sebastian_s25)


Lesenswert?

Kannst du auch bitte so nett sein und mir sagen welches Bit in welchem 
Register?

Ich komm nicht drauf...

von Karl H. (kbuchegg)


Lesenswert?

Check noch mal die Einstellung vom Timer 1
Alles noch mal mit dem Datenblatt vergleichen, dann ist es eindeutig.

von Sebastian S. (sebastian_s25)


Lesenswert?

Ah...

ok hat lang gedauert aber jetzt hab ichs...

Danke nochmal!!

mfg

Bastian

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.