Hallo liebe Gemeinde. Bei meinen Phasenanschnitt habe ich das Problem das wie im Bild 1. zu sehen, der angeschnittene Bereich schwankt und dadurch auch ein optisches Flackern der Lampe verursacht wird. (PS.: Der Bereich ist kleiner als der Markierte, genau kann ich das nicht sagen, Oszi zu alt...) Den Anschnitt mache ich über die Platine in Bild 2. Also kurz gesagt über Schieberegister (74HC595)und Triacs etc. Der Nulldurchgang, der auch im Bild 1 zu sehen ist, steht wie eine Eins. Ich "Nulle" den Timer (s.main.c) immer beim Nulldurchgang und starte dann den Timer neu, zünde den Triac wenn ein gwünschter Wert erreicht ist. Diese Wertabfrage mache ich im Interrupt alle 0,016ms. Nach meiner Auffassung kann im schlechtesten Fall nur eine Verzögerung von 0,016ms entstehen, das würde man aber mit Sicherheit nicht als flackern wahrnemen, denke ich. Hat vielleicht noch einer ein Tip für mich was ich mal ausprobieren kann um der Sache auf die Spur zu kommen? (Ich habe hier Beitrag "Dimmer flackert trotz Timer Interrupt" auch schon mal was geschrieben,da war aber das Problem das komplette Wellen nicht geschaltet wurden, das konnte ich bisher beheben. Jetzt geht es wirklich nur um den "kleinen" Versatz beim Starten der Zündung/Triacs)
@ Markus P. (sebastianwurst) > 1.JPG > 1,6 MB, 6 Downloads Bitte mal über Bildformate informieren. >Diese Wertabfrage mache ich im Interrupt alle 0,016ms. Wo? Ich sehe nur einen INT0-Interrupt für den Nulldurchgang, einen TIMER0_COMPA für das verzögerte zünden und einen USART_RX für den Datenempfang per UART. Dort wird auch dein Jitter herkommen, denn während der USART_RX abgearbeitet wird, muss der TIMER0_COMPA warten. Schalt mal den UART testweise aus. Ausserdem ist deine main Hauptschleife RIESIG, da sieht keine Sau durch. Pack das in Funktionen, damit man maximal 1-2 Bildschirmseiten für die Hauptscheife braucht. Ausserdem habe ich das unbestimmte Gefühl, dass da noch nicht alles rund läuft mit den Dutzenden Aufgaben. MFG Falk
Du hast Recht, ich muss mal aufräumen da ich 80% auch garnicht mehr gebrauche, ich weiss nur noch nicht ob es für ewig so bleiben wird deswegen hab ich die noch drin gelassen.... Durch diese Initialisierung des Timers 0:
1 | TCCR0B |= (1<<CS00) | (1<<WGM02); // CTC uns Prescaler 1 (16.000.000/256)= 0,016ms Interrupt auslösen) |
2 | |
3 | TCNT0 = 0; // Timer Startwert |
4 | OCR0A = 255; // Load register |
5 | TIMSK0 |= (1<<OCIE0A); // Interrupt nach Overflow |
Das sind dann 0,016ms und hier wird die Aufgerufen: Dort wird dann alle 0,16ms der TriacZuenden()aufgerufen und wenn der TCNT1 die Vorgaben überschritten hat der Triac gezuendet...
1 | //==================================================================
|
2 | // Timer 0 Dimmwertvergleich
|
3 | //==================================================================
|
4 | ISR (TIMER0_COMPA_vect) |
5 | {
|
6 | |
7 | TriacZuenden(15000,16); |
8 | TriacZuenden(15000,18); |
9 | |
10 | |
11 | // Timer zurücksetzen
|
12 | if (TCNT1 >= 19000 ) |
13 | {
|
14 | |
15 | |
16 | |
17 | AusgangUnsetBit(16); |
18 | AusgangOut(); |
19 | |
20 | AusgangUnsetBit(17); |
21 | AusgangOut(); |
22 | |
23 | AusgangUnsetBit(18); |
24 | AusgangOut(); |
25 | |
26 | |
27 | |
28 | TCNT1 = 0; |
29 | TCCR1B = 0b00000000; // Timer stoppen |
30 | }
|
31 | }
|
Wenn ich aber nichts über USART sende/empfange dann brauch die USART_RX auch nichts machen oder?
Deine ISR (TIMER0_COMPA_vect) braucht wegen dem AusgangSetBit/UnsetBit/AusgangOut Verhau immer länger als 16us. Das braucht sie so zwar immer noch, aber nur gelegentlich: volatile int tick,dimm17=15000,dimm18=10000,dimm19=15000; ISR(TIMER0_COMPA_vect) { unsigned char changed=0; tick++; if(tick==dimm17) { AusgangSetPit(17); changed=1; } if(tick==dimm18) { AusgangSetPit(18); changed=1; } if(tick==dimm19) { AusgangSetPit(19); changed=1; } if(changed) AusgangOut(); } ISR(INT0_vect) { tick=0; AusgangUnsetBit(17); AusgangUnsetBit(18); AusgangUnsetBit(19); AusgangOut(); } Man muß übrigens sicher stellen, daß nur die eine oder andere Interrupt-Funktion ausgeführt werden kann, keine geschachtelten Interrupts sonst wird eventuell mitten im rücksetzen noch gesetzt oder umgekehrt. Glücklicherweise ist das default-mässig der Fall.
@ Markus P. (sebastianwurst) >Durch diese Initialisierung des Timers 0: >TCCR0B |= (1<<CS00) | (1<<WGM02); // CTC uns Prescaler 1 >(16.000.000/256)= 0,016ms Interrupt auslösen) >TCNT0 = 0; // Timer Startwert >OCR0A = 255; // Load register >TIMSK0 |= (1<<OCIE0A); // Interrupt nach Overflow Der Kommentar ist irreführend, weil falsch. Es ist der CTC Modus, da gibt es keinen Überlauf, sondern einen Compare Match. So heißt auch die ISR. >Das sind dann 0,016ms Oder wie der Fachmann sagt, 16us. Nicht viel, mach gerade mal 256 Takt bei 16MHz. Mit wieviel läift dein AVR? >Dort wird dann alle 0,16ms der TriacZuenden()aufgerufen und wenn der >TCNT1 die Vorgaben überschritten hat der Triac gezuendet... Sportlich, in einem 16us Interrupt noch Funktionen aufrufen, die sind bekanntermassen beim AVR nicht so schnell an der Stelle (Stichwort Register sichern etc.). WENN, dann macht man das direkt in der ISR, ohne Funktionsaufruf. Aber wozu braucht man für eine Phasenanschnittsteuerung einen 16us Timer? Es reicht doch, per Output Compare nach dem Nulldurchgang ein IO-Pin zu setzen. Das macht der Timer allein ohne jegliche CPU-Last. Und jitterfrei ;-) Wenn man nun noch so clever ist, und statt INT0 die Input Capture Funktion nutzt, clever combimiert mit der Output Compare Funktion, kann man nahezu beliebige Interrupts parallel nutzen, ohne den geringsten Jitter. >Wenn ich aber nichts über USART sende/empfange dann brauch die USART_RX >auch nichts machen oder? Ja. MFG Falk
> Oder wie der Fachmann sagt, 16us. Nicht viel, mach gerade mal 256 Takt > bei 16MHz. Mit wieviel läift dein AVR? 16Mhz >Es reicht doch, per Output Compare nach dem > Nulldurchgang ein IO-Pin zu setzen. Aber ich habe ja mehrere Phasenanschnitt, daher das Schieberegister. > Sportlich, in einem 16us Interrupt noch Funktionen aufrufen, die sind > bekanntermassen beim AVR nicht so schnell an der Stelle (Stichwort > Register sichern etc.). Ich wollte das auch erst nicht mit Funktionsaufrufe in der ISR machen, wollte eigentlich nur ein Flag setzen und diesen dan in der main abfragen, aber das klappt auch nicht besonders gut (Flackern). > Wenn man nun noch so clever ist, und statt INT0 die Input Capture > Funktion nutzt, clever combimiert mit der Output Compare Funktion, kann > man nahezu beliebige Interrupts parallel nutzen, ohne den geringsten > Jitter. Da bin ich zu doof für, glaub ich ;-( Aber ich versuche mein Bestes. Werde durch Eure Tips nochmal einbissel ausprobieren. Danke schonmaml. Bitte schaut nochmal rein....
@ Markus P. (sebastianwurst) >Aber ich habe ja mehrere Phasenanschnitt, daher das Schieberegister. Wieviele? Timer 1 hat zwei Output COmpares Register, kann man schon mal zwei erledigen. Es gibt AVRs mit vier und mehr Output Compares, kann man nutzen. Reicht das nicht, muss man es so wie du in Software machen, ist dann eine Art synchroner Soft-PWM. >Ich wollte das auch erst nicht mit Funktionsaufrufe in der ISR machen, >wollte eigentlich nur ein Flag setzen und diesen dan in der main >abfragen, Keine gute Idee, da ist das Timing noch mieser. > aber das klappt auch nicht besonders gut (Flackern). Logisch. MFg Falk
Falk Brunner schrieb: > Wieviele? Timer 1 hat zwei Output COmpares Register, kann man schon mal > zwei erledigen. Es gibt AVRs mit vier und mehr Output Compares, kann man > nutzen. Reicht das nicht, muss man es so wie du in Software machen, ist > dann eine Art synchroner Soft-PWM. Bis zu zehn sind das Ziel... >Keine gute Idee, da ist das Timing noch mieser. Das dachte ich mir dann auch...
Evtl. mal eine Gegenprobe mit Rechteckimpulsgenerator machen ob die gelieferten Impulse überhaupt AUSREICHEN um den Triac anzusteuern?
oszi40 schrieb: > Evtl. mal eine Gegenprobe mit Rechteckimpulsgenerator machen ob die > gelieferten Impulse überhaupt AUSREICHEN um den Triac anzusteuern? Ich habe auch direkt am Ausgang vom Schieberegister gemessen (74HC595) das spiegelt den sinusverlauf der angeschnittenen Wechselspannung komplett wieder.
Vielleicht stelle ich mich auch viel zu sehr an. Ich habe keinen Vergleichsdimmer bei mir im Hause, nur einen Dimmer der über Kondensatoren/Schieberegler den Phasenanschnitt macht. Da gibts kein flackern. Das flackern ist auch so klein, denke mir nur das eine so flackernde Leselampe zu Kopfschmerzen führen würde.
Kann dieser INT2 auch was damit zu tun haben, ich benutz das AVR Net IO Board da ist die NEtzwerkkarte auch drauf. Die brauch den Interrupt. Welcher Interrupt gewinnt?
1 | #define enc_select() ENC_PORT &= ~(1<<ENC_CS)
|
2 | #define enc_deselect() ENC_PORT |= (1<<ENC_CS)
|
3 | |
4 | #define ETH_INTERRUPT INT2_vect
|
5 | #define ETH_INT_ACTIVE (!(ENC_PIN & (1<<ENC_INT)))
|
6 | |
7 | #define ETH_INT_ENABLE EIMSK |= (1<<INT2)
|
8 | #define ETH_INT_DISABLE EIMSK &= ~(1<<INT2)
|
Auf der Platine kann man TIC206M lesen, zwei Lötpunkte für diesen Triac. Was ist mit dem mittleren Pin des Triacs? Das bitte mal erklären.
Der ist etwas nach vorne (oben) rausgebogen, damit die Abstände der Lötpunkt grösser werden.
> Wieviele? Timer 1 hat zwei Output COmpares Register, kann man schon mal > zwei erledigen. Es gibt AVRs mit vier und mehr Output Compares, kann man > nutzen. Reicht das nicht, muss man es so wie du in Software machen, ist > dann eine Art synchroner Soft-PWM. ich habe jetzt mal nur einen Ausgang getogglet und der sieht komplett identisch zu den Ausgängen der Schieberegister aus. Ich habe fast jeden weitern Code in der Main auskommentiert und trozdem wackelt der Ausgang. So wie im Bild vom ersten Eintrag... Auch ohne Schieberegister wackelt der (PD3) Der Nulldurchgang steht auf die 1000/Sekunde, laut Oszi. Müsste der getogglet Ausgang auch so stehen? Was ist denn Normal für so einen Atmega 644p mit 16Mhz Taktung? Hier ist nochmal der Code der Interrupts:
1 | /////////////////////////////////////////////////
|
2 | /////////////////////////////////////////////////
|
3 | //Interrupt 0 steigende Flanke Nulldurchgang
|
4 | /////////////////////////////////////////////////
|
5 | |
6 | EIMSK |= (1<<INT0); // External Interrupt 0 Enable PIN PD2 |
7 | EICRA |= (1<<ISC00) | (1<<ISC01); // Int auslösen bei steigender Flanke |
8 | |
9 | |
10 | ////////////////////////////////////////////////
|
11 | // Timer 1 Dimmwert für Triac Ansteuerung erhöhen (16-bit)
|
12 | /////////////////////////////////////////////////
|
13 | |
14 | |
15 | TCCR1A = (1<<WGM12); // CTC Modus |
16 | TCCR1B |= (1<<CS11); // Prescaler 8 = (16.000.000/20000/8)= 10,00ms würde Interrupt ausgelöst) |
17 | TCNT1 = 0; // |
18 | OCR1A = 20000; // Load register |
19 | // TIMSK1 |= (1<<OCIE1A); // Interrupt nach Overflow
|
20 | |
21 | ////////////////////////////////////////////////////
|
22 | // Timer 0 Timer für den Dimmwertvergleich (8-bit)
|
23 | ////////////////////////////////////////////////////
|
24 | |
25 | TCCR0B |= (1<<CS00) | (1<<WGM02); // CTC uns Prescaler 1 (16.000.000/256)= 0,016ms Interrupt auslösen) |
26 | // TCCR0B |= (1<<CS00) | (1<<CS01) | (1<<WGM02); // CTC uns Prescaler 64 (16.000.000/256/64)= 1,024ms Interrupt auslösen)
|
27 | // TCCR0B |= (1<<CS01) | (1<<WGM02); // CTC uns Prescaler 8 (16.000.000/256/8)= 0,128ms Interrupt auslösen)
|
28 | |
29 | TCNT0 = 0; // Timer Startwert |
30 | OCR0A = 255; // Load register 0,064 |
31 | TIMSK0 |= (1<<OCIE0A); // Interrupt nach Overflow |
32 | |
33 | //Globale Interrupts einschalten
|
34 | sei(); |
35 | /*
|
1 | //==================================================================================
|
2 | // Timer 0 Dimmwertvergleich
|
3 | //==================================================================================
|
4 | ISR (TIMER0_COMPA_vect) |
5 | {
|
6 | |
7 | //Triac setzen
|
8 | |
9 | if (u16Dimmwert[0] < 16000) |
10 | {
|
11 | if (TCNT1 >= u16Dimmwert[0]) |
12 | {
|
13 | PORTD |= (1<<PD3); |
14 | AusgangSetBit(0); |
15 | AusgangOut(); |
16 | }
|
17 | }
|
18 | |
19 | /*
|
20 | if (u16Dimmwert[1] < 16000)
|
21 | {if (TCNT1 >= u16Dimmwert[1]){AusgangSetBit(1);AusgangOut();}}
|
22 | |
23 | if (u16Dimmwert[2] < 16000)
|
24 | {if (TCNT1 >= u16Dimmwert[2]){AusgangSetBit(2);AusgangOut();}}
|
25 | |
26 | if (u16Dimmwert[3] < 16000)
|
27 | {if (TCNT1 >= u16Dimmwert[3]){AusgangSetBit(3);AusgangOut();}}
|
28 | */
|
29 | /*
|
30 | if ((u16Dimmwert[0] < 16000) && ausgaenge_status[4])
|
31 | {if (TCNT1 >= u16Dimmwert[0]){AusgangSetBit(PosDerLetzenRAS*8);AusgangOut();}}
|
32 |
|
33 | |
34 | if (u16Dimmwert[1] < 16000)
|
35 | {if (TCNT1 >= u16Dimmwert[1]){AusgangSetBit(PosDerLetzenRAS*8+1);AusgangOut();}}
|
36 | |
37 | if (u16Dimmwert[2] < 16000)
|
38 | {if (TCNT1 >= u16Dimmwert[2]){AusgangSetBit(PosDerLetzenRAS*8+2);AusgangOut();}}
|
39 | |
40 | if (u16Dimmwert[3] < 16000)
|
41 | {if (TCNT1 >= u16Dimmwert[3]){AusgangSetBit(PosDerLetzenRAS*8+3);AusgangOut();}}
|
42 | */
|
43 | |
44 | |
45 | |
46 | // Timer / Triac zurücksetzen
|
47 | if (TCNT1 >= 17000 ) |
48 | {
|
49 | volatile bool b_SetAusgangOut = false; |
50 | |
51 | if (u16Dimmwert[0] < 16000) |
52 | {
|
53 | PORTD &= ~(1<<PD3); |
54 | AusgangUnsetBit(0); |
55 | b_SetAusgangOut = true; |
56 | }
|
57 | |
58 | |
59 | |
60 | //if (u16Dimmwert[1] < 16000){AusgangUnsetBit(1);b_SetAusgangOut = true;}
|
61 | //if (u16Dimmwert[2] < 16000){AusgangUnsetBit(2);b_SetAusgangOut = true;}
|
62 | //if (u16Dimmwert[3] < 16000){AusgangUnsetBit(3);b_SetAusgangOut = true;}
|
63 | //if (b_SetAusgangOut) {AusgangOut();b_SetAusgangOut=false;}
|
64 | |
65 | /*if (u16Dimmwert[0] < 16000){ PORTD &= ~(1<<PD3);AusgangUnsetBit(PosDerLetzenRAS*8);b_SetAusgangOut = true;}
|
66 | if (u16Dimmwert[1] < 16000){AusgangUnsetBit(PosDerLetzenRAS*8+1);b_SetAusgangOut = true;}
|
67 | if (u16Dimmwert[2] < 16000){AusgangUnsetBit(PosDerLetzenRAS*8+2);b_SetAusgangOut = true;}
|
68 | if (u16Dimmwert[3] < 16000){AusgangUnsetBit(PosDerLetzenRAS*8+3);b_SetAusgangOut = true;}
|
69 | */
|
70 | |
71 | if (b_SetAusgangOut) {AusgangOut();b_SetAusgangOut=false;} |
72 | |
73 | TCNT1 = 0; |
74 | TCCR1B = 0b00000000; // Timer stoppen |
75 | }
|
76 | |
77 | }
|
78 | //==================================================================================
|
79 | //Interrupt 0 Nulldurchgangerkennung steigende Flanke
|
80 | //==================================================================================
|
81 | ISR(INT0_vect) |
82 | {
|
83 | |
84 | Nulldurchgang = true; |
85 | |
86 | // gestoppten Timer mit Prescaler 8 wieder starten
|
87 | TCCR1B |= (1<<CS11); // Prescaler 8 |
88 | TCNT1 = 0; |
89 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.