Forum: Mikrocontroller und Digitale Elektronik Wie könnte ich die Ansteuerung vom TRIAC für Phasenanschnitt besser machen.


von Markus P. (sebastianwurst)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe wie im Anhang zu sehen eine Phasenanschnittsteurung nachgebaut. 
Hardwaremäßig funktioniert jetzt alles und daher bin ich jetzt an der 
Software dran.

Da die Sache über Timer und Interrupts gemacht werden müssen bin ich 
folgendermaßen angefangen indem ich eine Variable jede 0,016ms hochzähle 
nachdem sie bei der postiiven Flanke vom Nulldurchgang gelöscht wurde.
Hat diese Variable dann einen vorgegeben Wert erreicht schalte ich den 
TRIAC ein. So sieht der Code aus:
1
DimmWert_Lampe1 = 100;
2
3
//===============================================================
4
//Timerinterrupt bei Überlauf
5
//===============================================================
6
7
// Aufruf alle 0,016ms
8
9
ISR (TIMER0_COMPA_vect)
10
{
11
12
CountTimer++;
13
  
14
  if (CountTimer == DimmWert_Lampe1)
15
  {
16
  //Setzen
17
   PORTD |= (1<<PD3);    
18
  }
19
  
20
}
21
22
//============================================================
23
//Interrupt 0 Nulldurchgangerkennung steigende Flanke
24
//============================================================
25
26
ISR(INT0_vect)
27
{    
28
   // Löschen
29
    PORTD &= ~(1<<PD3);
30
    CountTimer =0;
31
  
32
}


Das Ganze gefällt mir aber nicht. Ich kannmir nicht vorstellen das 
dieses der eleganteste Weg ist, funktionieren tut es zwar. Wie würdet 
Ihr das lösen?


So sind die Interrupts/Timer gesetzt:
1
  
2
/////////////////////////////////////////////////
3
//INTerrupt konfigurieren
4
  
5
  EIMSK  |= (1<<INT0);   // External Interrupt 0 Enable PIN PD2  
6
  EICRA  |= (1<<ISC00) | (1<<ISC01);  // Int auslösen bei steigender Flanke
7
 
8
 
9
 //////////////
10
 // Timer 0 (8-bit) konfigurieren
11
12
    TCCR0B |= (1<<CS00);   // Prescaler 0
13
14
    TIMSK0 |= (1<<OCIE0A);
15
  
16
    //Globale Interrupts einschalten
17
    sei();

Benutzen tu ich einen Atmega644

von Markus (Gast)


Lesenswert?

Ich muss dazu noch beisagen  dass der " Dimmwert" natürlich variieren 
kann und insgesamt mehrer TRIACs gezündet werden müssen ! Je nachdem 
viele Verbraucher ich halt dummen will .
Vielen Dank schonmal...

von Michael R. (mexman) Benutzerseite


Lesenswert?

Aufpassen beim Auswerten des Nulldurchgangs!
Nicht einfach nur den Portstatus abfragen, sondern auch auf 
Plausibilitaet des Nulldurchgangs testen (in Europa alle 10mS ein 
Nulldurchgang...passiert was in der Zwischenzeit, ignorieren.

Gruss

Michael

von Markus (Gast)


Lesenswert?

Guter Tip. Danke!
Was meinst du denn von den anderen Sachen? Ich finde das viel zu 
"anstrengend" für den Mikro alle 0,016ms in die Timer Interrupt zu 
springen. Doch wenn ich langsamer mache sieht man es komisch flackern.

von Markus P. (sebastianwurst)


Lesenswert?

Kann einer dazu eine Aussage treffen ob meine Vorgehensweise mit dem 
Timer Interrupt alle 0,016ms gut ist. Oder eher gesagt das man das ohne 
Bedenken so lassen kann. Ich weiß nicht wie weit so ein ofter Aufruf 
einer Interrupt das andere Programm im Ablauf nicht doch irgendwie 
beeinflusst? Ich habe auch noch Schieberegister, UART etc. auf dem yC.

Vielen Dank für die Hilfe ....

von Matthias (Gast)


Lesenswert?

Warum machst du den IRQ-Takt so schnell? Keine Ahnung, wie schnell dein 
Prozessor ist, aber bei 16 µs IRQ-Folge habe ich da meine Bedenken, ob 
er da hinterher kommt.

625 Helligkeitsstufen sind IMHO arg übertrieben.

von Markus P. (sebastianwurst)


Lesenswert?

16 MHz taktet der.

Ich hatte weniger genommen da habe ich dann aber ein Flackern 
wahrgenommen. Ich schloss das jetzt da drauf das der Timer natürlich 
immer in der Runde läuft bis der Überlauf kommt. Also kann es sein das 
ich den TRIAC evtl. erst ein Zyklus später oder früher zünde jenachdem 
wie der Nulldurchgang kommt. Wenn ich jetzt aber die Zykluszeit so klein 
wie möglich setze, also Prescaler = 0 und somit alle 0,016ms sah es sehr 
gut aus.

Wie würdest Du es machen ?

Vielen Dank schonmal !

von Markus P. (sebastianwurst)


Lesenswert?

Ich habe es jetzt mal so ausprobiert:

Jetzt starte ich den Timer immer mit Nuldurchgangerkennung und stoppe 
Ihn wenn er nicht mehr gebraucht wird. Somit kann ich schonmal klar 
stellen das er immer synchron mit dem Nulldurchgang ist. Und ausserdem 
vermutlich wesentlich Resourcenschonender für den Controller. Da 
Prescaler 1024 also alle 10ms ein Timer Interrupt nur.
Vergleichen tu ich dann den Timer Wert.
1
// Wenn Timerwert erreicht Triac zünden, Timer stoppen
2
if (TCNT0 >= 100) 
3
  {
4
  
5
    //Triac zünden
6
  PORTD |= (1<<PD3); 
7
  
8
  TCNT0   =0;
9
  TCCR0B  =0b00000000;   // Timer stoppen
10
   
11
  }
12
  
13
14
15
16
17
//Interrupt 0 Nulldurchgangerkennung steigende Flanke
18
19
ISR(INT0_vect)
20
{    
21
    PORTD &= ~(1<<PD3);
22
23
    // gestoppten Timer mit  Prescaler 1024 wieder starten
24
    TCCR0B |= (1<<CS00) | (1<<CS02);   // Prescaler 1024
25
    TCNT0   =0;  
26
}

von Matthias (Gast)


Lesenswert?

Markus P. schrieb:
> Ich schloss das jetzt da drauf das der Timer natürlich
> immer in der Runde läuft bis der Überlauf kommt.

Beim Nulldurchgang muß der Timer synchronisiert werden, d.h. auf Null 
gesetzt werden, sonst läuft der irgendwie weiter und der erste IRQ 
kommt irgendwann danach. Das könnte bei niedriger IRQ-Frequenz eine 
Flackerursache sein.
Außerdem verwendest du den Compare-IRQ, setzt aber nirgends das Compare 
Register. Eigentlich willst du vermutlich volle Timerrunden zählem, 
wofür dann der Overflow-IRQ angesagt wäre.
MfG

von Markus P. (sebastianwurst)


Lesenswert?

Danke Matthias,
hast du meine neue Post schon gelesen ? Wir haben glaube ich 
gleichzeitig geschrieben ;-)
Was hälst Du davon ?

von Sascha W. (sascha-w)


Lesenswert?

@Markus P.

wenn du mit Prescaler arbeitest, solltest du auch den zurücksetzen, da 
sonst ein Jitter entsteht der sich bei bestimmten Helligkeiten mit 
flackern bemerkbar macht.
Du kannst auch die Outputcomparefunktion des Timers verwenden um den 
Ausgang für den Triac zu schalten. Der Timer muss dazu mit einer 
Overfowzeit von 10ms laufen, dann kannst du die Helligkeit mit dem 
OCRx-Register einstellen. Im Nulldurchgang setzt du TCRx auf null und 
machst einen Prscaler-Reset.

Sascha

von Markus P. (sebastianwurst)


Lesenswert?

Hi,
aber den Prescaler setzte ich doch zurück:

1
  TCCR0B  =0b00000000;   // Timer stoppen

Oder was meinst Du ?

von Sascha W. (sascha-w)


Lesenswert?

Damit koppelst du den Timer vom Takt ab, der Prescaler läuft trotzdem 
weiter.

Hab gerade noch mal im Datenblatt nachgeschlagen - beim 644 geht das nur 
beim Timer2 (GTCCR-Register PSRASY-Bit).

Sascha

von spess53 (Gast)


Lesenswert?

Hi

>Hab gerade noch mal im Datenblatt nachgeschlagen - beim 644 geht das nur
>beim Timer2 (GTCCR-Register PSRASY-Bit).

Mit PSRSYNC auch, allerdings gemeinsam, für Timer0 und 1.

MfG Spess

von Sascha W. (sascha-w)


Lesenswert?

hm.. in der Version des Datenblatt's vom 644 das ich gerade auf dem 
Rechner hab' steht das PSRSYNC zwar drin - ist aber nirgendwo 
beschrieben. Beim 644P stehts dann aber auch drin.

Sascha

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.