1 | /* Programm zur Ansteuerung eines Phasenabschnitts-Dimmers.
|
2 | Der Dimmer ist somit auch für elektronische Halogentrafos geeignet; für Glühlampen und dergleichen ebenfalls
|
3 |
|
4 | Der Dimmer selbst wird in SERIE zur Phase und dem mit der Last verbundenen Nullleiter geschlossen. Es efolgt keine galvanische Trennung, daher kann
|
5 | eine Berührung des Dimmers während des Betriebes zum Tod führen!
|
6 | Ist der MOSFET durchgeschlaten, so liegt der volle SINUS am Verbraucher an. In der jetzigen Version wird die Versorgungsspannung in der AUS-Zeit der
|
7 | Sinus-Periode in einem Kondensator zwischengespeichert. Folgedessen liegt bei voller Aussteuerung am Dimmer keine Spannung an!
|
8 |
|
9 | Der Nulldurchgang wird mit Hilfe einer Diodenschaltung detektiert. Es ist dabei aber zu beachten, dass nur EIN Nulldurchgang pro periode detektiert wird.
|
10 | Der Durchgang tritt bei einer Sinus-Spannung mit 50Hz ja zeitlich um 10ms versetzt auf, wonach die kein großes Problem darstellt.
|
11 | Dieser Durchgang wird dem µC durch seinen Int0-Eingang zugeführt. Der µCmuss für fallende Ints konfiguriert sein
|
12 |
|
13 | Programmablauf:
|
14 | - Int0 detektiert Nulldurchgang -> ISR
|
15 | - Der MOSFET schaltet durch zuweisen von LOW auf den Ausgangspin durch
|
16 | - Ein Timer beginnt zu zählen
|
17 | - Nach Erreichen des Ansteuerwinkels (EIN-Zeit) wird der Ausgang auf HIGH gesetzt
|
18 | - Nach Erreichen von 10msec wir der Ausgang für die zweite Halbwelle wieder auf LOW gesetzt
|
19 | - Es wird wieder mit dem Timer die EIN-Zeit abgewarten und der Ausgang auf HIGH gesetzt
|
20 | - Reti, warte auf nächste fallende Flanke...
|
21 |
|
22 | Prozessor: ATMEGA8
|
23 | Takt: 3,2768MHz
|
24 |
|
25 | Tasten: PB0 -> UP
|
26 | * PB1 -> DOWN
|
27 |
|
28 | !!!!!!!!!!!Beschreibung nicht aktuell!!!!!!!!!!!
|
29 |
|
30 | Interner Quarz, 8MHz, Timer 1 mit Vorgabe 4000
|
31 |
|
32 |
|
33 | */
|
34 |
|
35 | #include <avr/io.h>
|
36 | #include <avr/interrupt.h>
|
37 |
|
38 | #define T_UP PINB0
|
39 | #define T_DOWN PINB1
|
40 | #define T_PIN PINB
|
41 | #define MOSFET_DDR DDRD
|
42 | #define MOSFET_PORT PORTD
|
43 | #define MOSFET_PX PD3
|
44 |
|
45 | #define SET_MOSFET_OUT MOSFET_DDR|=(1<<MOSFET_PX)
|
46 | #define MOSFET_EIN MOSFET_PORT&=~(1<<MOSFET_PX) //LOW -> Mosfet einschalten!
|
47 | #define MOSFET_AUS MOSFET_PORT|=(1<<MOSFET_PX)
|
48 |
|
49 | #define TEILER -4000
|
50 | #define RETURN 100
|
51 |
|
52 | void entprellen(void);
|
53 |
|
54 | volatile unsigned char winkel=0; //Anstellwinkel, EIN-Zeit, max 64
|
55 | volatile unsigned char takt;
|
56 | volatile unsigned char flanke; //Flankenart, 0->steigend; 1->fallend
|
57 |
|
58 | int main(void)
|
59 | {
|
60 | DDRD|=(1<<DDD3);
|
61 |
|
62 | MCUCR|=(1<<ISC01)|(1<<ISC00); //Int0 bei steigender Flanke
|
63 | GICR|=(1<<INT0); //Int0 ein
|
64 | flanke=0;
|
65 |
|
66 | TCCR1B|=(1<<CS10); //Teiler 1
|
67 | TCNT1 = TEILER;
|
68 |
|
69 | SET_MOSFET_OUT;
|
70 | MOSFET_AUS; //Erstmals gar nichts machen, Lampe aus
|
71 |
|
72 | winkel=5;
|
73 | takt=0;
|
74 |
|
75 | sei();
|
76 |
|
77 | for(;;)
|
78 | { if(T_PIN&(1<<T_UP))
|
79 | { entprellen();
|
80 | winkel+=1;
|
81 | if(winkel>10) winkel=10; //Für PLC mit FCPU=3,6864: winkel=74 Begrenz erstmals auf 62*2
|
82 | }
|
83 |
|
84 | if(T_PIN&(1<<T_DOWN))
|
85 | { entprellen();
|
86 | winkel-=1;
|
87 | if(winkel<1) winkel=1;
|
88 | }
|
89 |
|
90 | /*if(takt>=winkel)
|
91 | { MOSFET_AUS;
|
92 | }
|
93 | if(takt>=20) //20*0,5ms=10ms
|
94 | { MOSFET_EIN;
|
95 | if(takt>=winkel+20)
|
96 | { MOSFET_AUS;
|
97 | TCNT0=0;
|
98 | takt=0;
|
99 | TIMSK&=~(1<<TOIE1);
|
100 | }
|
101 | }*/
|
102 | }
|
103 |
|
104 | }
|
105 |
|
106 | void entprellen(void)
|
107 | { unsigned char t=0xFF;
|
108 | //while( (T_PIN&(1<<T_UP)) || (T_PIN&(1<<T_DOWN)));
|
109 | while(t--);
|
110 | }
|
111 |
|
112 | ISR(INT0_vect)
|
113 | { char temp, sreg_temp, i;
|
114 |
|
115 | sei();
|
116 |
|
117 | if(flanke) //Für fallende Flanke
|
118 | { /*Filter it to makes sure it was not only noise*/
|
119 | for (i=0; i<5; i++) //Five samples noise filter for LOW
|
120 | { if(!(PIND & (1<<PD2))) temp++; //PD2 muss 5 Ticks LOW sein, dass gültig
|
121 | else temp = RETURN;
|
122 | }
|
123 |
|
124 | if(temp != RETURN)
|
125 | {
|
126 | /*Place your zero cross action here*/
|
127 |
|
128 | MCUCR|=(1<<ISC01)|(1<<ISC00); //Int0 auf steigende Flanke umschalten
|
129 | flanke = 0;
|
130 |
|
131 | MOSFET_EIN;
|
132 | TIMSK|=(1<<TOIE1);
|
133 |
|
134 | for(;;)
|
135 | { if(takt>=winkel)
|
136 | { MOSFET_AUS;
|
137 | takt=0;
|
138 | TCNT1=TEILER;
|
139 | TIMSK&=~(1<<TOIE1);
|
140 | break;
|
141 | }
|
142 | }
|
143 |
|
144 | }
|
145 | }
|
146 |
|
147 | if(flanke==0) //Für steigende Flanke
|
148 | { /*Filter it to makes sure it was not only noise*/
|
149 | for (i=0; i<5; i++) //Five samples noise filter for LOW
|
150 | { if(PIND&(1<<PD2)) temp++; //PD2 muss 5 Ticks HIGH sein, dass gültig
|
151 | else temp = RETURN;
|
152 | }
|
153 |
|
154 | if(temp != RETURN)
|
155 | {
|
156 | /*Place your zero cross action here*/
|
157 |
|
158 | MCUCR|=(1<<ISC01); //Int0 auf fallende Flanke umschalten
|
159 | flanke = 1;
|
160 |
|
161 | MOSFET_EIN;
|
162 | TIMSK|=(1<<TOIE1);
|
163 |
|
164 | for(;;)
|
165 | { if(takt>=winkel)
|
166 | { MOSFET_AUS;
|
167 | takt=0;
|
168 | TCNT1=TEILER;
|
169 | TIMSK&=~(1<<TOIE1);
|
170 | break;
|
171 | }
|
172 | }
|
173 |
|
174 | }
|
175 | }
|
176 |
|
177 | }
|
178 |
|
179 | ISR(TIMER1_OVF_vect) //alle 0,5msec
|
180 | { takt++;
|
181 | TCNT1=TEILER;
|
182 | }
|