Dimmer flackert trotz Timer Interrupt

OP #2458923
Hallo,
ich habe einen Dimmer/Phasenanschnitt mit Hilfe der bekannten 
Triacansteuerung realisiert. Jetzt merke ich das ich trotz 
Timerintterrupt, in der ich den Triac/Ausgang lösche, undefeniert, immer 
wenn der yC gerade etwas arbeiten muss, (UART, Schleifenaufruf...) ein 
Flackern der Lampe wahrnehme. Laut Oszi löscht er im Nulldurchgang den 
Ausgang nicht und hat somit nach dem Nulldurchang die komplette 
Halbwelle.
Ich benutze diese Interrupt/Timer Initialisierungen:
1
/////////////////////////////////////////////////
2
//Interrupt steigende Flanke Nulldurchgang konfigurieren
3
///////////////////////////////////////////////// 
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 Dimmwert für Triac Ansteuerung erhöhen (8-bit) konfigurieren
11
/////////////////////////////////////////////////
12

13

14
    TCCR0A  = (1<<WGM01);                 // CTC Modus
15
    TCCR0B |= (1<<CS00) | (1<<CS02);      // Prescaler 1024
16
  TCNT0   = 0;
17

18
  
19
 ////////////////////////////////////////////////////
20
 // Timer 1 Timer für den Dimmwertvergleich (16-bit)
21
 ////////////////////////////////////////////////////
22
 
23
    TCCR1B |= (1<<CS10) | (1<<WGM12);     // CTC uns Prescaler 1 (16.000.000/256)= 0,016ms TimerInterrupt auslösen) 
24
  TCNT1   = 0;                          // Timer Startwert
25
    OCR1A   = 256;                        // Load register      
26
    TIMSK1 |= (1<<OCIE1A);                // Interrupt nach Overflow

und hier sind die Timer / Interrupts:
1
//==================================================================================
2
// Timer 1 Dimmwertvergleich
3
//==================================================================================
4
ISR (TIMER1_COMPA_vect)
5
{
6
      
7
TriacZuenden(50,16); // Das Bit 16 welches den Triac ansteuert wird nach erreichen von TCNT0 >= 50 gesetzt.
8

9
// Timer zurücksetzen  
10
if (TCNT0 >= 135) 
11
  {
12

13
  TCNT0   = 0;
14
  TCCR0B  = 0b00000000;   // Timer stoppen
15
  }    
16
}
17
//==================================================================================
18
//Interrupt 0 Nulldurchgangerkennung steigende Flanke
19
// Im Nulldurchang wird der "TriacAusgang" gelöscht und der Timer wieder gestartet
20
//==================================================================================
21

22
ISR(INT0_vect)
23
{    
24
//  TRIAC Zündung löschen
25
AusgangUnsetBit(16);
26
AusgangOut();  
27
  
28
  
29

30
  
31
    // gestoppten Timer mit  Prescaler 1024 wieder starten
32
    TCCR0B |= (1<<CS00) | (1<<CS02);   // Prescaler 1024
33
  TCNT0   = 0;  
34

35
  
36
}
Hat evtl. jemand ein Tip warum da was schief geht?
Danke.
OP
Marvin M. schrieb:
> Hallo,
>
> nutzen die Routinen, die die Störungen verursachen, ebenfalls einen
> Interrupt oder sperren ihn?

Hi, dieses "oder sperren ihn?" verstehe ich vom Sinn nicht...
Die Routinen die die Störungen verursachen haben keine Interrupts mehr,
diese Routine z.B hat "nur" Schleifen und Stört:
1
void Eingaenge_abfragen (void)
2
{
3
    PORTC |= (1<<PC4);
4

5
    // Mit PL alle Eingänge in das Register schieben.
6

7
    // PL auf High
8
    PORTC |= (1<<PC5);
9
    // PL auf Low
10
    PORTC &= ~(1<<PC5);
11
    // PL auf High
12
    PORTC |= (1<<PC5);
13

14
      
15
      //Abfragen welches Registerbit gesetzt -> mit clock weiter schieben
16
    for(m=(Eingangskarten * 16)-1;m>=0;m--)
17
    {
18
          
19
      if (PINA & (1<<PINA0)) 
20
      { // Logisch 1 wenn Schalter nicht gedrückt da Pullup an
21
      Eingang[m] = false;     
22
      
23
            if      (m<= 8) StatusEingangByte1 &= ~(1 << m);
24
      else if (m<=16) StatusEingangByte2 &= ~(1 << m);
25
      else if (m<=24) StatusEingangByte3 &= ~(1 << m);
26
      else if (m<=32) StatusEingangByte4 &= ~(1 << m);
27

28
      } 
29
      else 
30
      {
31
      Eingang[m] = true;  
32
      
33
      if      (m<= 8)  StatusEingangByte1 |= ( 1 << m );
34
      else if (m<= 16) StatusEingangByte2 |= ( 1 << m );
35
      else if (m<= 24) StatusEingangByte3 |= ( 1 << m );
36
      else if (m<= 32) StatusEingangByte4 |= ( 1 << m );      
37
      }        
38
          
39
      // Mit Clock weiterschieben
40

41
      // Clock auf High
42
      PORTC |= (1<<PC4);
43
      // Clock auf Low
44
      PORTC &= ~(1<<PC4);
45
      // Clock auf High
46
      PORTC |= (1<<PC4);    
47
    }      
48
}
OP
Wenn ich in der Timer Interrupt einen Ausgang toggle passt das auch, 
also er wird alle 0,016ms aufgerufen

Der Ausgang togglet im Sekundentakt:
1
ISR (TIMER1_COMPA_vect)
2
{
3
longCount++;
4

5
if (longCount>=62500 && !memm)        
6
{
7
     PORTC |= (1<<PC6);  
8
         longCount= 0;
9
         memm = true;
10
}
11
else if (longCount>=62500 && memm)      
12
{        
13
         PORTC &= ~(1<<PC6);
14
         longCount= 0;
15
         memm = false;
16
}
17
  
18
}
Gast
Ich hab mir deinen Code jetzt nicht genau angeguckt, aber du musst den 
Triac doch nur einmal "zünden", dann bleibt er doch "an". Also kurzen 
Puls aufs Gate und dann is gut. Damit ist sichergestellt dass er im 
Nulldurchgang definitiv aus ist.


Knut
OP
Einmal sei() direkt hinter der Timer/Interruptinitialisierung:
1
....
2

3
 ////////////////////////////////////////////////////
4
 // Timer 1 Timer für den Dimmwertvergleich (16-bit)
5
 ////////////////////////////////////////////////////
6
 
7
    TCCR1B |= (1<<CS10) | (1<<WGM12);     // CTC uns Prescaler 1 (16.000.000/256)= 0,016ms Interrupt auslösen) 
8
  TCNT1   = 0;                          // Timer Startwert
9
    OCR1A   = 256;                        // Load register      
10
    TIMSK1 |= (1<<OCIE1A);                // Interrupt nach Overflow  
11
  
12
  //Globale Interrupts einschalten
13
  sei();
OP
Knut schrieb:
> Ich hab mir deinen Code jetzt nicht genau angeguckt, aber du musst den
> Triac doch nur einmal "zünden", dann bleibt er doch "an". Also kurzen
> Puls aufs Gate und dann is gut. Damit ist sichergestellt dass er im
> Nulldurchgang definitiv aus ist.
>
>
> Knut

Ja das ist Richtig, ich lösche den Triac erst wieder mit steigender 
Flanke des Nulldurchgangs:
1
ISR(INT0_vect)
2
{    
3
//  TRIAC Zündung löschen
4
AusgangUnsetBit(16);
5
AusgangOut();  
6
  
7
  
8

9
  
10
    // gestoppten Timer mit  Prescaler 1024 wieder starten
11
    TCCR0B |= (1<<CS00) | (1<<CS02);   // Prescaler 1024
12
  TCNT0   = 0;  
13
 
14
}
Wenn ich jetzt Softwaremäßig den Nulldurchgang nicht mitbekomme (warum 
auch immer, ist wie im Anhang verdrahtet) dann würde er das Bit nicht 
löschen und wäre wieder/immer noch an. Das gehe ich mal noch genauer auf 
den Grund....
Gast
Markus P. schrieb:
>//===================================================================== 
=============
> //Interrupt 0 Nulldurchgangerkennung steigende Flanke
> // Im Nulldurchang wird der "TriacAusgang" gelöscht und der Timer wieder 
>gestartet
>//===================================================================== 
=============

Das ist zwar theoretisch möglich, würde ich aber schon früher machen, 
da:

Knut schrieb:
> Triac doch nur einmal "zünden", dann bleibt er doch "an"



Knut
Gast
Interessant wäre auch mal deine Nulldurchgangserkennung-Hardware. Nicht 
das die einfach zu spät den Nulldurchgang meldet und da dein Triac schon 
gezündet hat. Wenn du das dann mit der Netzspannung vergleichst:

Markus P. schrieb:
> Laut Oszi löscht er im Nulldurchgang den
> Ausgang nicht


Knut
OP
Knut schrieb:
> Interessant wäre auch mal deine Nulldurchgangserkennung-Hardware. Nicht
> das die einfach zu spät den Nulldurchgang meldet und da dein Triac schon
> gezündet hat. Wenn du das dann mit der Netzspannung vergleichst:
>
> Markus P. schrieb:
>> Laut Oszi löscht er im Nulldurchgang den
>> Ausgang nicht
>
>
> Knut

Optokoppler 4N25
Optokoppler MOC3020
Brückengleichrichter B250C1500
Schmitttriger  74HC14

TIC 246M  16 A /600V als Triac
Knut schrieb:
> Ok, nein, dass sieht ok aus. Versuch einfach mal den Ausgang vorm
> Nulldurchgang auszuschalten.

oder bei fallender Flanke an INT0 auslösen, dann wird der Nulldurchgang 
noch kurz vor dem eigentlichen Zeitpunkt erkannt.

Oder für die Triacansteuerung gleich eine Fast-PWM Betriebsart des 
Timers verwenden, und mit INT0 nur den Timer auf die Netzspannung 
syncronisieren.


Sascha
@Markus P.: Noch ein kleiner Tip, ich verwende AC Optokoppler, damit 
kann man sich den Gleichrichter sparen.

Wenn wir hier schon beim Thema Flackern sind, habe gerade auch meine 
Software fertig, im Moment zum testen noch per Poti, aber ich habe ein 
leichtes hin und hergehen der Zündimpulse, sieht man am Ende des Videos 
einigermaßen. Findet ihr das ist das schon zu unruhig, um Flackerfrei 
eine Helligkeitsstufe zu halten.

http://kosmos.bplaced.net/24032012005.mp4
Angehängte Dateien:

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.