[codenoInterrupts(); //Interrupts abschalten, damit bei der Zuweisung zum Register nicht unterbrochen werden kann.
OCR1A = OCR1A_Wert
interrupts();]
Dies hat soweit ertmal geklappt, die Lampe flackert nicht mehr.
Ich habe jetzt einige Tage versucht, wie beim Spannungsmesser zuvor, das ganze präzise zu kriegen.
Beim Phasenanschnittregler habe ich die Verzögerung mit dem Oszilloskop ermittelt.(380µs). Was mich immernoch wundert wieso der Triac zu früh zündet.
Aber ich habe diese Verzögerung in der Exeltabelle miteinberechnet.
Den Spannungsmesser bekomme ich nicht so präzise hin wie zuvor. Ich habe den zuvor verwendeten Trafo wieder eingesetzt und R3 etwas größer gemacht. Nun habe ich bei 224V im Netz 3,62V am Ausgang.
Ich habe bei verschiedenen Netzwerten die Zahl am analogen Ausgang notiert. Denn bei jedem paar Netzwert/Analog gerechnet und aus diesen Werten den durchschnitt gebildet. Anschließend multipliziere ich diesen Wert im Programm mit dem Analogwert um die Netzspannung zu ermitteln.
Teilweise funktioniert es präzise(in bezug auf mein Messgerät) teilweise weicht der Wert aber auch um 0,5V ab.
Mir ist aufgefallen das der analoge Wert bei gleicher Netztpannung manchmal 1digit weniger ist. Deswegen weicht es denke ich mal ab.
War vorher aber glaube ich nicht so. (Den Filter verwende ich)
Im gesamten Porgramm stelle ich nun die gewünschte Voltzahl ein. Wenn ich 100V einstelle habe ich aber eine Abweichung teilweise von +4V. Beim ganzen zuvor hatte ich eine Abweichung von vllt 0.5V.
Nun weiß ich nicht wie ich das ganze weiter präziser machen soll. Wie zuvor halt. Den Phasenanschnittregler kann man schonmal ausschließen der ist Präzise. Es kann nur an der Umrechnungen oder am Spannungsmesser liegen.
Was kann ich machen?
Hier nochmal der jetztige sketch:
#include <avr/io.h>
#include <avr/interrupt.h>
#define GATE 9 //Triac Pin
#define PULSE 20 //trigger pulse width (counts) 10µs
#define DETECT 2 //zero cross detect
int U_NetzPin = A7; // Netzspannungsmesser
int U_ref = 220; // bei 220V 3000W Leistung
long previousMillis = 0;
long interval = 13;
int Neuwert;
const int FF = 99;
float U_NetzAD;
void setup() {
pinMode(DETECT, INPUT); //zero cross detect
digitalWrite(DETECT, HIGH); //enable pull-up resistor
pinMode(GATE, OUTPUT); //triac gate control
pinMode(U_NetzPin, INPUT);
// set up Timer1
OCR1A = 0; //initialize the comparator
TIMSK1 |= (1 << OCIE1A); // Comperator A Interrupt aktivieren
TIMSK1 |= (1 << TOIE1); //Overflow Interrupt aktivieren
TCCR1A = 0x00; //timer control registers set for
TCCR1B = 0x00; //normal operation, timer disabled
// bei zerocross Interrupt
attachInterrupt(0,zeroCrossingInterrupt, RISING);
//IRQ0 is pin 2. Call zeroCrossingInterrupt
//on rising signal
Serial.begin(57600);
}
void loop() {
Sollwert(100.00); // 100V
} //end loop
//d) eine Funktion, die den Phasenanschnitt ausführt.
//the interrupt function must take no parameters and return nothing
void zeroCrossingInterrupt(){ //zero cross detect
TCCR1B=0x02; //start timer prescaler 8
TCNT1 = 0; //reset timer - count from zero
}
ISR(TIMER1_COMPA_vect){ //comparator match
digitalWrite(GATE,HIGH); //Triac an machen
TCNT1 = 65536-PULSE; //trigger pulse width
}
ISR(TIMER1_OVF_vect){ //timer1 overflow
digitalWrite(GATE,LOW); //Triac ausmachen
TCCR1B = 0x00; //disable timer stopd unintended triggers
}
//c) eine Funktion, die dir aus Sollwert und Netzspannung die Phasenanschnittszeit errechnet
void Sollwert(float Volt){ //Voltzahl
float U_Netz = U_NetzLesen();
float Faktor_U = U_ref / U_Netz; // das ist der Korrekturfaktor, den du aus der abweichenden Spannung hast.
float Faktor_G = Faktor_U * (Volt/U_Netz*100.00); // das ist dein Gesamtfaktor, um den du mittels Phasenanschnitt deine Spannung
//Serial.print("U_Netz: ");Serial.print(U_Netz);
//Serial.print(" Faktor_U: ");Serial.print(Faktor_U);
//Serial.print(" Prozent: ");Serial.print(Prozent);
//Serial.print(" Faktor_G: ");Serial.print(Faktor_G);Serial.println();
const int Tabpunkte = 50;
const float WerteTab[Tabpunkte][2]={ // 1.Spalte V in Prozent 1= 220V , 2.Spalte Zeit in Microsekunden
{ 0.725233373128343,20360},
{ 2.04884152815099,19960},
{ 3.75653798961305,19560},
{ 5.76760037973328,19160},
{ 8.03185633657378,18760},
{ 10.5123471747264,18360},
{ 13.1791534987902,17960},
{ 16.0065727330459,17560},
{ 18.9716372400389,17160},
{ 22.0532660329187,16760},
{ 25.2317515266739,16360},
{ 28.4884385028046,15960},
{ 31.8055204064967,15560},
{ 35.1659108385353,15160},
{ 38.5531651452729,14760},
{ 41.951436442244, 14360},
{ 45.3454558986707,13960},
{ 48.7205304460519,13560},
{ 52.0625531752139,13160},
{ 55.3580230518699,12760},
{ 58.5940714931153,12360},
{ 61.7584939718206,11960},
{ 64.8397852526323,11560},
{ 67.8271771743856,11160},
{ 70.7106781186548,10760},
{ 73.4811134683906,10360},
{ 76.1301664807882,9960},
{ 78.6504190855496,9560},
{ 81.0353921805756,9160},
{ 83.2795850361218,8760},
{ 85.3785134379723,8360},
{ 87.3287462010954,7960},
{ 89.1279396673216,7560},
{ 90.7748697626847,7160},
{ 92.2694611303291,6760},
{ 93.6128127709887,6360},
{ 94.8072195123975,5960},
{ 95.8561884891733,5560},
{ 96.7644496439482,5160},
{ 97.5379590584164,4760},
{ 98.1838936915438,4360},
{ 98.7106358471148,3960},
{ 99.1277454250591,3560},
{ 99.445917748684,33160},
{ 99.6769245301471,2760},
{ 99.8335353769449,2360},
{ 99.9294172020061,1960},
{ 99.9790090388604,1560},
{ 99.9973701481919,1160},
{ 100.00, 760}};
int i = 0;
while (i < Tabpunkte && Faktor_G > WerteTab[i][0]){i++;} // passenden Eintrag in der Tabelle suchen
// richtigen Wert interpolileren
int OCR1A_Wert = int (((WerteTab[i][1] - WerteTab[i-1][1]) * ( Faktor_G - WerteTab[i-1][0] ))/ (WerteTab[i][0] - WerteTab[i-1][0] )) + WerteTab[i-1][1];
noInterrupts(); //Interrupts abschalten, damit bei der Zuweisung zum Register nicht unterbrochen werden kann.
OCR1A = OCR1A_Wert;
interrupts();
}
//b) eine Funktion um die Netzspannung aus dem AD-Eingang zu ermitteln.
/*************************************************************************************************
** Liest den AD-WErt an Pin "U_NetzPin" **
** und interpoliert aus der Tabelle den korrekten pysikalischen Wert. **
** **
** Input: nix **
** Output: Netzspannung in Volt **
** genutzte Globale Variablen: SensorPin **
**************************************************************************************************/
float U_NetzLesen() {
/* Wertetabelle SpannungsWerte */
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) { // alle 13ms Neuwert
previousMillis = currentMillis;
Neuwert = analogRead(U_NetzPin);
}
U_NetzAD = (Neuwert + FF * U_NetzAD)/(FF+1);
Serial.println(U_NetzAD*0.291902974);
//***************** Interpolation des Wertes aus der Tabelle *****************************************
// richtigen Wert interpolileren
float Wert = U_NetzAD*0.291902974;
return Wert;
} // End of U_NetzLesen