ATmega164P Fast PWM keine funktion

OP #2470334
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
OP #2470349
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
Gast #2470364
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
Gast #2470367
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.
OP #2470415
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
OP #2470423
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren