Hallo Leute, ich habe zurzeit ein Problem mit meiner Phasenanschnitts-Steuerung. Und zwar passt die Ansteuerung des Triac nicht richtig. Es fallen immer wieder einzelne Impulse aus. Die Ansteuerung funktioniert momentan folgendermaßen: Ich habe einen Timerinterrupt, der alle 100us auslöst. In dem Timerinterrupt wird ein Counter hochgezählt. Außerdem habe ich eine Schaltung, die mir beim Nulldurchgang einen Impuls erzeugt (Zero Cross Detection). Durch den Impuls wird ein Interrupt beim Controller ausgelöst. In dem Interrupt wird dann der aktuelle Counterwert festgehalten. Nach einer bestimmten Wartezeit, die durch einen Poti definiert wird, wird der Triac eingeschalten. Der Einschaltimpuls für den Triac dauert 100us. Die ganze Berechnung ist in dem Timerinterrupt untergebracht.
:
Verschoben durch Moderator
Wie sieht der Nulldurchgangsdetektor aus? Schaltung Wenn der Steuerpuls fehlt ist die Triacstufe erst mal egal.
Was sollen die Bilder darstellen? Miss doch mal die Spannung Eingangsseitig am Optokoppler mit dem Oszi und dann Ausgangsseitig. Dann weißt du doch schon ob die Signale ankommen und kannst das Problem eingrenzen.
Einfach gefragt schrieb: > Was sollen die Bilder darstellen? Na, das ist doch eindeutig: Es ist eine Ansicht des Marktplatzes von Halle an der Saale -oder siehst Du etwas Anderes?
Die Bilder stellen das Signal am Optokoppler eingangs- und ausgangsseitig dar.
karadur schrieb: > der Steuerpuls fehlt Der Steuerimpuls der Nullduchgangserkennung fehlt... Tim K. schrieb: > Die Bilder stellen das Signal am Optokoppler eingangs- und > ausgangsseitig dar. Dort passt das tadellos: die LED wird nicht angesteuert und der Triac schaltet nicht. Der Fehler passiert davor. Tim K. schrieb: > Die ganze Berechnung
1 | /*Zeitpunkt Phasenanschnitt abhängig vom Poti einstellen*/
|
2 | uint16_t poti(uint16_t dma) |
3 | {
|
4 | if(dma < 250) time = 140; // ca. 20% -> 50V übrig |
5 | else if(dma >= 250 && dma < 500) time = 130; |
6 | else if(dma >= 500 && dma < 1000) time= 120; |
7 | else if(dma >= 1000 && dma < 1250) time = 110; |
8 | else if(dma >= 1250 && dma < 1500) time= 100; |
9 | else if(dma >= 1500 && dma < 1750) time = 90; |
10 | else if(dma >= 1750 && dma < 2000) time= 80; |
11 | else if(dma >= 2000 && dma < 2250) time = 70; |
12 | else if(dma >= 2250 && dma < 2500) time = 60; |
13 | else if(dma >= 2500 && dma < 2750) time= 50; |
14 | else if(dma >= 2750 && dma < 3000) time = 40; |
15 | else if(dma >= 3000 && dma < 3250) time= 30; |
16 | else if(dma >= 3250 && dma < 3500) time = 20; |
17 | else time = 0; |
18 | return time; |
19 | }
|
Ein Wort zum Code: wenn dma nicht kleiner 250 ist, dann ist dma automatisch größer oder gleich 250. Du kannst dir die Afrage auf >= also jewils sparen:
1 | :
|
2 | if (dma < 250) time = 140; // ca. 20% -> 50V übrig |
3 | else if(dma < 500) time = 130; |
4 | else if(dma < 1000) time = 120; |
5 | else if(dma < 1250) time = 110; |
6 | else if(dma < 1500) time = 100; |
7 | else if(dma < 1750) time = 90; |
8 | :
|
9 | else if(dma < 3000) time = 40; |
10 | else if(dma < 3250) time = 30; |
11 | else if(dma < 3500) time = 20; |
12 | else time = 0; |
Und wenn man das gemacht hat, dann fällt einem die Unregelmäßigkeit bei 250-500-1000-1250 direkt ins Auge: warum fehlt da 750? Und am anderen Ende ist bei 40-30-20-0 auch eine Stufe drin: die 10 fehlt. Und wenn dieser Fehler behoben ist, kann man auf die Idee kommen, dass time auch einfach berechnet und feiner aufgelöst werden könnte. So kommst du recht gut an deine handgestrickte gestufte inverse Regression:
1 | time = 160-(dma/25); |
Das gibt "kostenlos" auch noch die Einerschritte bei time. Und wenn du da noch ein wenig mit den "magic numbers" spielst, dann kommt da schon das raus, was du willst. Dann musst du halt noch einbauen, dass die Grenzwerte abgefragt und validiert werden.
:
Bearbeitet durch Moderator
Hallo, hast du berücksichtigt dass dein "Counter" (der alle 100usec erhöht wird) auch mal "überläuft" (8bit/16Bit) und dann der "Counterwert" (kurz vor Überlauf übernommen) eine exakte Berechnung der Wartezeit verhindert. Erst der nächste Nulldurchgang (mit Übernahme eines neuen Counterwerts) bereinigt die Situation wieder. Diese Überlaufproblematik tritt nicht jedesmal sondern nur ab und zu auf. Als erste Abhilfe rate ich dir deine Counter/Conterwert Variablen auf den nächst höheren Bitwert auszulegen (also von 8bit auf 16bit oder von 16Bit auf 32Bit) Tritt der Fehler dann mit erheblich geringerer Häufigkeit auf ist es genau dieses Problem! Gruss
Tim K. schrieb: > Ich habe einen Timerinterrupt, der alle 100us auslöst. In dem > Timerinterrupt wird ein Counter hochgezählt. Der Dir natürlich regelmäßig überläuft. > Außerdem habe ich eine Schaltung, die mir beim Nulldurchgang > einen Impuls erzeugt (Zero Cross Detection). Durch den Impuls > wird ein Interrupt beim Controller ausgelöst. In dem > Interrupt wird dann der aktuelle Counterwert festgehalten. Und wen das (zu) kurz vorm Counter-Überlauf passiert, dann kriegst Du ein Problem. Zwar sind counter, prevCounter und delay alle unsigned, aber dummerweise nur 16 Bit breit und integer am STM32 wohl 32 Bit, nehme ich zumindest an? Damit werden alle Deine uint16 vor der entscheidenden Berechnung zu integern promoted, weshalb die Subtraktion vorzeichenbehaftet ausgeführt wird und das negative Ergebnis mit delay verglichen wird. Jetzt gibts zwei Möglichkeiten: * Du änderst alle drei Variablen-Typen auf unit32 und verhinderst damit die Promotion nach integer, oder * Du castest das Ergebnis Subtraktion explizit zurück nach uint16 und erhältst dadurch das gewollte positive Ergebnis, das dann problemlos mit delay verglichen werden kann.
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.