Forum: Mikrocontroller und Digitale Elektronik Geschickte Programmierung für Phasenanschnitt


von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

Hallo zusammen,

das Thema Phasenanschnitt (50Hz Netzspannung) wurde schon etliche male 
behandelt. Eine passende Software dafür konnte ich jedoch leider nicht 
finden.

Mein Problem: Ich habe einen Phasenanschnittsdimmer mit ATMega8 gebaut. 
An den OC1A-Pin ist ein TRIAC angeschlossen, über einen Jumper kann ich 
entweder am ICP-Pin oder am INT0-Pin ein Rechtecksignal einlesen, 
welches bei jedem Nulldurchgang seinen Zustand umkehrt.

Nun meine Frage: Wie kann einen möglichst effizienten Code generieren, 
der mir den TRIAC nach einer eingestellten "Dimm-Verzögerung" (z.B. 8ms) 
einschaltet und kurze Zeit später, jedoch auf jeden Fall bei t < 10ms, 
wieder ausschaltet? Das Ganze eben möglichst ohne 3 Interrupts dafür zu 
benutzen o.ä..

Leider blicke ich bei den ganzen "Phase Corrected Frequency Corrected 
PWM Modes" etc. im Datenblatt nicht ganz durch bzw. sehe noch nicht, wie 
ich diese Funktionen geschickt einsetzen kann...

Wäre für Tipps sehr dankbar!
Schöne Grüße,
Alex

von Purzel H. (hacky)


Lesenswert?

Als Trigger muss man erst mal ein gefiltertes Netz verwenden. Ohne 
rabiaten Filter, der die Harmonischen rigoros wegmacht ist nichts. Dann 
einen Timer laufenlassen. Immer jeweils vom Trigger her. Und 
gleichzeitig die Periode pruefen, ist sie nicht relativ genau 20ms, dann 
macht man zur Sicherheit nichts. Einen durchgehenden Timer wuerd ich 
nicht verwenden, der laeuft dem Netz ueber eine gewisse Zeit davon und 
es knallt.
Das Problem mit der Filterung ist, dass man das Netz selbst veraendert.

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

A...aha Soooo. schrieb:
> Dann
> einen Timer laufenlassen. Immer jeweils vom Trigger her.

Genau, ich wollte auch bei jedem Wechsel des Trigger-Signals (es 
wechselt, wie gesagt, bei jedem Nulldurchgang) den Timer "resetten".

>Und gleichzeitig die Periode pruefen, ist sie nicht relativ genau 20ms, dann
>macht man zur Sicherheit nichts.

Richtig, das hatte ich mir auch überlegt.

Nun dennoch die Frage, wie man dazu geschickt die Timer-Funktionen des 
AVRs nutzen kann ohne alles in Software und mit Interrupts zu erledigen. 
Kann man nicht vieles davon in Hardware realisieren (mit den ganzen 
Timer-Spezialmodi)?

Gruß,
Alex

P.S.:
>und es knallt.
Was denn und warum? Stimmt im schlimmsten Fall nicht einfach der 
"Dimm-Wert" nicht?

von Sven P. (Gast)


Lesenswert?

PWM ist hier nicht ganz angebracht. Es ist ja dein AC-Netz, das die 
Zeitvorgaben liefert, und nicht du, der du z.B. eine Grundfrequenz für 
PWM festlegst.

Eine Überlegung: Was macht dein Prozessor denn noch? Nur 
Phasenanschnitt? Rechne dann doch einmal aus, wie sehr der sich 
langweilen wird zwischen den Nulldurchgängen.
Ansonsten kann man sowas für zwei Kanäle prima mit den beiden 
Auffangregistern (Compare) eines Timers machen. ist zwar immer noch mit 
Spatzen auf Kanonen geschossen, macht aber nichts :-)

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Was soll den geschnitten werden?
Ohmsche oder Induktive Last?

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

Markus Müller schrieb:
> Was soll den geschnitten werden?
> Ohmsche oder Induktive Last?

In erster Linie Ohm'sche Last. Ich glaubte jedoch (bis zu deiner Frage), 
dass induktives Dimmen genauso funktioniert... :-)

>Was macht dein Prozessor denn noch?
Es ist noch ein lokales User-Interface (1 LED, ein Drehencoder, ein 
Button) dran und eine ZigBee Schnittstelle (per UART) für "ein Bisschen" 
Kommunikation mit anderen Geräten. Ist aber nicht so "zeitkritisch".

>Ansonsten kann man sowas für zwei Kanäle prima mit den beiden
>Auffangregistern (Compare)
Es ist nur 1 Kanal. Aber erläutere mir bitte mal genauer, wie du das 
meinst...

von Sven P. (Gast)


Lesenswert?

Nun, parametrier einen Timer in der Art, sodass er innerhalb einer 
Halbwelle gerade nicht überläuft. Er soll am Ende der Halbwelle den 
Wert X erreichen.

Mit einem Auffangregister setzt du diesen Wert X TOP ein, das wäre dann 
einer von den CTC-Modi. Dadurch wird der Timer am Ende der Halbwelle 
wieder zurückgesetzt.

Dann leg eine Tabelle mit Vergleichswerten an. '0' wäre volle Leistung, 
X wäre gar keine Leistung, dazwischen dann z.B. noch linearisieren.

Legst du nun einen dieser Vergleichswerte in ein zweites Auffangregister 
(das erste sorgt ja bereits fürs Rücksetzen des Timers), so hast du 
deinen Zündzeitpunkt.

von Horst H. (horha)


Lesenswert?

Hallo,

Ich weiß ja nicht, was Du damit willst.
Dein Timer wird doch eine Rahmenzeit von 10 ms == 180° haben, um jede 
Halbwelle anzuschneiden.Damit schaltet der Timer immer bei 10 ms ab.
Der Trigger ist der Nulldurchgang der Netzspannung.

Alex Bürgel schrieb:
> "Phase Corrected Frequency Corrected PWM Modes"

Phase corrected PWM würde bei einem Phasenwinkel von 0,2° bei 89,9° eine 
Signal auf High setzen und bei 90,1° wieder zurück auf Low.
Also hättest Du als kleinsten Zündwinkel 90° == 50%.
Ergo könntest Du auch nur von 50..100% dimmen.
Das ist sicher nicht das gewünschte Verhalten.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Bei Induktiver Dimmung braucht man zwei Messungen:
- Spannung / Nulldurchgang
- Stromfluss durch den Verbraucher

Beides über Optokoppler mit dem Oszi betrachtet gibt eine interessante 
Erkenntniss.

von Anja (Gast)


Lesenswert?

Alex Bürgel schrieb:
> Nun meine Frage: Wie kann einen möglichst effizienten Code generieren,

Ich habe für eine Thyristorgleichrichtung von meinem Labornetzteil das 
ganze in einen Timer-Interrupt gelegt, der alle 51us aufgerufen wird. 
(Ich hatte keine anderen Ressourcen im PIC16F876 mehr frei). Dort wird 
dann die Entprellung des Eingangssignals, messen der 
Periodendauer-Hälften und die Ausgabe an die Thyristoren durchgeführt.
Die Berechnung der Anschnittwerte erfolgt separat im Hauptprogramm.
Das ganze braucht etwa 13% der Rechenzeit, 46 Assembler-Befehle und 
erlaubt einen Phasenanschnitt mit knapp 0,5% Auflösung und Jitter.

Gruß Anja

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

>Ich weiß ja nicht, was Du damit willst.

Es soll ein Dimmer für Glühlampen und 230V-Halogenlampen bis 500W sein 
(wobei mir zunächst 60W reichen). Ferner dachte ich eigentlich auch 
Niedervolthalogenlampen mit Ringkerntrafo damit dimmen zu können.

Bevor mir hier irgendetwas explodiert: Was sollte ich denn beim Dimmen 
eines Ringkerntrafos erwarten? Meiner Erwartung nach steigt der Strom 
beim Einschalten irgendwann innerhalb einer Halbwelle halt "langsam" an, 
die Spannung ist natürlich sofort die aktuelle Sinusspannung. 
Ausschalten tut sich der TRIAC doch von alleine wenn U ~ 0V und I ~ 0A 
ist. Es gibt im übrigen auch einen Snubber mit 100nF/33Ohm über dem 
TRIAC.


Das mit dem CTC kann ich mir noch nicht so recht vorstellen, muss mir 
das nochmal anhand des Datenblatts durch den Kopf gehen lassen...

Gruß,
Alex

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

>das ganze in einen Timer-Interrupt gelegt, der alle 51us aufgerufen wird.

Ja klar, so kann man es machen... ich hatte nur gehofft anstatt alle 
xxµs einen Interrupt zu generieren einfach diverse Hardware-Funktionen 
nutzen zu können. So verfügt der "Input-Capture" ja z.B. über einen 
"Noise Canceller" und der Output Compare hat 12 Betriebsmodi (oder so). 
Da sollte es doch eine Kombination geben, mit der man so was 
alltägliches mit nur 1 Interrupt lösen kann und dennoch 
Störungsresistent etc. ist...

von Ralph Fischer (Gast)


Lesenswert?

Hallo Alex,

ich hatte im Sommer mal angefangen, einen Dimmer in Bascom zu schreiben, 
der etwa so läuft, wie Du es Dir vorstellst. Gedacht ist das Ding für 
Glühlampenlast bis 3 kW und Einknopfbedienung (Taster).

Ist alles noch ziemlich provisorisch, geht aber im wesentlichen schon. 
Es läuft alles automatisch im Timer1 eines Attiny:
1
'*******************************************************************************
2
'  Dimmer for ohmic loads with Attiny24 for one button operation
3
'*******************************************************************************
4
'
5
'  Ralph Fischer 2010
6
7
8
$regfile = "ATtiny24.dat"
9
$crystal = 1000000                      '8 MHz with divider enabled
10
'$baud = 38400
11
12
$hwstack = 32
13
$swstack = 32
14
$framesize = 24
15
16
17
Config Porta.0 = Output
18
Triac Alias Porta.0
19
20
Config Pina.1 = Input
21
Porta.1 = 1
22
Key Alias Pina.1
23
24
Config Porta.2 = Output                 'just for debugging
25
Led Alias Porta.2
26
27
28
Config Int0 = Falling
29
On Int0 Int0_isr
30
Enable Int0
31
32
Dim Key As Bit
33
Dim Onoff_flag As Bit
34
Dim Dim_flag As Bit
35
Dim Dim_direction As Bit                '1 = incr. brightness, 0 = decr. brightness
36
Dim Key_count_flag As Bit
37
Dim Count_0 As Byte                     'for timing of the key
38
Dim Bright_min As Word
39
Dim Bright_max As Word
40
41
42
Declare Sub Key_count
43
Declare Sub Dimm
44
Declare Sub On_off
45
46
47
48
Ocr1b = 7000                            'start triac at x [µs] after zero cross; 0 = full power, 10,000 = off
49
Ocr1a = Ocr1b + 50                      'end of triac start pulse
50
Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Compare B = Disconnect , Clear Timer = 1
51
52
On Oc1b Set_triac
53
On Oc1a Reset_triac
54
Enable Oc1b
55
Enable Oc1a
56
57
Enable Pcint0
58
On Pcint0 Isr_pcint0
59
Pcmsk0 = &B00000010                     'PA.0 is key interrupt
60
61
Config Timer0 = Timer , Prescale = 1024
62
On Timer0 Timer0_isr
63
Enable Timer0
64
65
66
Enable Interrupts
67
68
Bright_min = 7000                       'note: this is the value for _minimum_ brighness
69
Bright_max = 2000                       'note: this is the value for _maximum_ brighness
70
                                        ' (values are the time gap between zero crossing and triac ignition)
71
72
73
74
75
76
77
78
'****Main****
79
Do
80
81
Led = onoff_flag
82
If Dim_flag = 1 Then
83
     Gosub Dimm
84
End If
85
86
If Key_count_flag = 1 Then
87
     Gosub Key_count
88
End If
89
90
Loop
91
'****/Main****
92
93
End
94
95
Isr_pcint0:
96
Waitms 20
97
If Key = 0 Then Set Key_count_flag
98
Return
99
100
Int0_isr:
101
Timer1 = 0
102
Start Timer1
103
Return
104
105
Timer0_isr:
106
     'Toggle Led
107
     Incr Count_0
108
Return
109
110
Set_triac:
111
Set Triac
112
Return
113
114
Reset_triac:
115
Reset Triac
116
Stop Timer1
117
Return
118
119
Sub On_off:
120
'Reset Triac
121
      Toggle onoff_flag
122
      If onoff_flag = 1 Then
123
         Enable Int0
124
         Else
125
         Disable Int0
126
         Gosub Reset_triac
127
      End If
128
End Sub
129
130
Sub Key_count:
131
     Reset Key_count_flag
132
     Count_0 = 0
133
     While Key = 0
134
     'Incr Count_0
135
     If Count_0 > 8 Then
136
          Set Dim_flag
137
          Count_0 = 0
138
          Exit Sub
139
     End If
140
     Wend
141
     If Count_0 < 5 Then Gosub On_off
142
End Sub
143
144
Sub Dimm:
145
Reset Dim_flag
146
Count_0 = 0
147
Toggle Dim_direction
148
     While Key = 0
149
          If Dim_direction = 0 Then
150
          Incr Ocr1b
151
               If Ocr1b > Bright_min Then
152
               Ocr1b = Bright_min
153
               End If
154
          Elseif Dim_direction = 1 Then
155
          Decr Ocr1b
156
               If Ocr1b < Bright_max Then
157
               Ocr1b = Bright_max
158
               End If
159
          End If
160
          Ocr1a = Ocr1b + 50
161
          Waitms 1
162
     Wend
163
End Sub

Vielleicht nutzt es.

Ralph

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

A...aha Soooo. schrieb:
> Als Trigger muss man erst mal ein gefiltertes Netz verwenden. Ohne
> rabiaten Filter, der die Harmonischen rigoros wegmacht ist nichts.

Hmm, komisch, mein 12-Kanal Dimmer funktioniert seit Jahren 
ausgezeichnet, auch ohne rabiaten Netzfilter. Die Kunst ist die 
Erkennung aller Nulldurchgänge, und zwar möglichst nahe an der Nullinie. 
Das habe ich mit einem Optokoppler mit Wechselspannungseingang gelöst. 
Dann gibt man dem Timer noch ein bisserl Reserve, so dass maximal 95% 
Leistung eingestellt werden können und dann ist alles super. Der 
Controller muss die Nulldurchgänge natürlich sauber erkennen, weshalb 
man hinter dem Optokoppler am besten einen Analog-Komparator-Eingang 
anstelle eines normalen Portpins nimmt. Diesen stellt man dann so ein, 
dass die Nullinie im Sinus einen schmalen Puls im Controller auslöst. Da 
der Analog-Komparator einen Interrupt auslösen kann, kann man die CPU 
zusätzlich entlasten. Als Leistungsstufe habe ich SSRs mit Snubbern 
hergenommen. Es hat sich herausgestellt, dass es sinnvoll ist, die SSRs 
den gesamten Leuchtzyklus nach dem Zünden eingeschaltet zu lassen, da es 
bei langen Lampenleitungen und zu kurzen Zündpulsen zu Flackern in 
kleinen Dimmstufen gekommen ist.

von Olaf (Gast)


Lesenswert?

Hey Knut !

Vielen Dank für Deinen hilfreichen Tipp mit dem Analog-Comparator !
( Ich quäle mich schon lange und das Gute lag so nah ;-))


Kannst Du mir bitte verraten, welches SSR Du benutzt ?

Danke + Gruß
Olaf

von Olaf (Gast)


Lesenswert?

Ach so, vergessen zu schreiben, wie ich es mache:

Ich nehme den Timer0 und teile ihn durch 1024.
Bei 16 MHz habe ich dann nach 10 ms einen Zählerstand von 157.

Das Capture Register muss dann also auf 157 minus irgendetwas gesetzt 
werden. In der Capture-Interrupt-Funktion dann EINSCHALTEN und in der
AnalogCompare/INTx Interrupt-Funktion dann AUSSCHALTEN
(benutze MOSFET´s)

Just my 2 cents

Olaf

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.