


	#include <avr/io.h>						//AVR Headerdatei 
	#include <avr/interrupt.h>				//AVR Headerdatei 
	#include <util/delay.h>					//Warte ms und us Funktion
	#include <math.h>						//sin, cos, asin - Funktionen
	#include "ButtonPress.h"				//Taster Entprellung 
	#include "TrigonometrischeFunktionen.h"	//Sinus- und Arcsin Funktionen
	#include "Initialisierung.h"			//Gesamte Initialisierung
	#include "PI_Regler.h"
	#include "Strombeobachter.h"
	#include "VZ1_Filter.h"
	/*
	|--------------------------------------------------------------------------
	| Variablen-Deklaration
	|--------------------------------------------------------------------------
	*/
	float u = 0;
	float u_gefiltert = 0;
	float u_test;
									
	int ALPHA = 17900, ALPHA1 = 17900, ALPHA2=17900;						//Startwert für Zündwinkel: 161°     //17900
	volatile int ALPHAnutz = 17900, ALPHAnutz1 = 17900, ALPHAnutz2 = 17900;			//Startwert für Hilfsvariable: 161°
	
	
	const int ALPHAmax = 17900;				//Maximaler Zündwinkel 161°
	const int ALPHAmin = 11000;				//Minimaler Zündwinkel 81° == 9000    //11000==1.727875959

	volatile int LAMBDA = 4000;				//Initialisierungswert für Leitdauer 36°
	int freigabe = 0;						//0 = Steuerung Aus, 1 = Steuerung An
	int ausschaltsicherung = 0;				//Hilfvariable um nicht bei gezündeten Triacs auszuschalten
	int linearisierung = 0;					//0 = Linearisierung Aus, 1 = Linearisierung An
	int steigendeFlanke = 0;				//Hilfsvariable für die Leitdauererfassung
	int zweiteHalbwelle = 0;				//Hilfsvariable für Netzsynchronisation
	int weiterZuenden = 0;					//Hilfsvariable für Netzsynchronisation
	int Startvorgang = 1;
	
	float Imax = 0, Imax_eingelesen=0;      //alle float
	float Id_neu=0 , Id_alt=0, Id_berechnet=0;
	float ALPHA_ohneL=17900;
	float ALPHA_mitL=17900;
	float ALPHA_radiant = 2.81172542;  //17900=2.81172542 
	float ALPHA1_radiant;
	float ALPHA2_radiant;
	int ErgebnisLin;
	
	int Potistellung = 0;
	int ersterLinDurchlauf = 1; 
	int ALPHAgrenzemax = 17900;
	
	float Delta_Alpha, Delta_Alpha_gefiltert, Delta_u;  
	int Delta_Alpha_integer;
	int Imax_integer;
	int Id_integer;
	int Id_neu_integer, Id_alt_integer;

	int x=0,y=0,z=0, pq = 0;
	
	int ADC_Wert;

	int Nulldurchgangsfreigabe;

	int stromdauer;
	int PIdurchlauf = 1;
	int Stromregelung = 0;
	
	float  TermI, TermII, TermIII, TermIV, TermV, TermVI, TermVII, TermVIII, TermIX, TermX, TermXI, TermVI_radiant, TermVII_radiant, TermVII_normal;
	

	/*
	|--------------------------------------------------------------------------
	| Funktionen-Deklaration
	|--------------------------------------------------------------------------
	*/
	int ADC_Lesen(void);					
	int Linearisierung(void);

	
	/*
	|--------------------------------------------------------------------------
	| Main-Funktion
	|--------------------------------------------------------------------------
	*/
	int main(void)
	{
		cli();													//Interrupts deaktivieren
		Init();													//Initialisierung
		sei();													//Interrupts aktivieren
		Startvorgang = 1;
		while(1)
		{	
//************ if Linearisierung AUS ***********************************************************************		

		
		if(Stromregelung == 1)
			if(linearisierung == 0)							
			{
			    Imax = 0.00292969 * ADC_Lesen();  //3A = 

				if (x==1)
				{
					Id_alt = Id_neu;
					x = 0;
				}
								
				
				
				if (y==1) 
				{	
					Id_neu = Strombeobachtung1(ALPHAnutz1, LAMBDA);
					y = 0;  //Änderung2mal zünden
				}
					
				
				if (z==1)
				{	

				Delta_Alpha = PI_ohneL(Id_neu, Id_alt, Imax, PIdurchlauf);
				ALPHA_radiant = ALPHA_radiant - Delta_Alpha;
				ALPHA_ohneL = ALPHA_radiant * 6366.197717;
				
				if ((ALPHA_ohneL <= (ALPHAmax)) && (ALPHA_ohneL >= ALPHAmin)) ALPHA1 = ALPHA_ohneL;
				else
				   {
						if (ALPHA_ohneL > ALPHAmax)
						{
							ALPHA1 = ALPHAmax;
							ALPHA_ohneL=ALPHAmax;
							ALPHA_radiant = 2.9045; 
						}
						
						if (ALPHA_ohneL < ALPHAmin)
						{
							ALPHA1 = ALPHAmin;
							ALPHA_ohneL= ALPHAmin;
							ALPHA_radiant = 1.72787595; 
						}					
				    } 
				z = 0;	
				}	
				
				if (x==2)
				{
					Id_alt = Id_neu;
					x=0;
	
				}
				
				
				
				if (y==2)
				{
					Id_neu = Strombeobachtung2(ALPHAnutz2, LAMBDA);
					y=0;
				}
				
				
				if (z==2)
				{					
					Delta_Alpha = PI_ohneL(Id_neu, Id_alt, Imax, PIdurchlauf);
					ALPHA_radiant = ALPHA_radiant - Delta_Alpha;
					ALPHA_ohneL = ALPHA_radiant * 6366.197717;
					
					if ((ALPHA_ohneL <= (ALPHAmax)) && (ALPHA_ohneL >= ALPHAmin)) ALPHA2 = ALPHA_ohneL;
					else
					{
						if (ALPHA_ohneL > ALPHAmax)
						{
							ALPHA2 = ALPHAmax;
							ALPHA_ohneL=ALPHAmax;
							ALPHA_radiant = 2.9045;
						}
						
						if (ALPHA_ohneL < ALPHAmin)
						{
							ALPHA2 = ALPHAmin;
							ALPHA_ohneL= ALPHAmin;
							ALPHA_radiant = 1.72787595;
						}
					}
					z=0;
				} //z==2
				}
						

		if(linearisierung == 1)								//Poti gibt u vor
			{
				Imax = 0.001972 * ADC_Lesen(); 

				if (x==1)
				{
					Id_alt = Id_neu;
					x=0;
				}
				
				if (y==1) 
				{	
					Id_neu = Strombeobachtung1(ALPHAnutz1, LAMBDA);
					y=0;			
				}
							

				if (z==1)
				{
					u = PI_mitL(Id_neu, Id_alt, Imax, u_test, PIdurchlauf);	
					ALPHA1 = Linearisierung() ;      			//Aufruf der Linearisierungsfunktion, 480us; //960
					z = 0;
				}	

				
				if (x==2)
				{
					Id_alt = Id_neu;
					x=0;
				}
				
				if (y==2)
				{
					Id_neu = Strombeobachtung2(ALPHAnutz2, LAMBDA);
					y=0;
				}
				

				if (z==2)
				{
					u = PI_mitL(Id_neu, Id_alt, Imax, u_test, PIdurchlauf);
					ALPHA2 = Linearisierung() ; // - 960; 			//Aufruf der Linearisierungsfunktion, 480us; //960
					z = 0;
				}

				
			}
}//if Stromregelung 1

else { }

//************ if Button AN/AUS gedrückt ***********************************************************************

			if(ButtonPressed(0, PINA, 2, 500))					//Wenn Taster Steuerung An/Aus
			{
				
				if(linearisierung==0) {
				
				
				ALPHAgrenzemax = 17900;	
				ALPHA = 17900;
				ALPHA1 = 17900;
				ALPHA2 = 17900;
				ALPHAnutz1 = 17900;
				ALPHAnutz2 = 17900;
				ALPHA_ohneL = 17900;
				ALPHAnutz = 17900;
				ALPHA_radiant = 2.8103; //2.81172542
				Stromregelung = 0;
				PIdurchlauf = 0;
				n = 0;
				avgsum = 0;
				
				x,y,z =0;
				pq = 0;


				
				if(freigabe)									//Wenn Steuerung An
				{
					if(ausschaltsicherung)						//Hilfvariable um nicht bei gezündeten Triacs auszuschalten
					{
						freigabe = 0;							//Steuerung Aus
						PORTB |= (1<<PINB2);					//LED rechts aus#

					Stromregelung = 0;
											
					}
					else
					{
						_delay_us(2500);	
														
					}	
				}
				else											
				{
					Stromregelung = 1;
					
					freigabe = 1;								//Steuerung An
					//PORTB |= (1<<PINB3);						//rote LED aus
					
					if(linearisierung)							//Wenn Linearisierung An
					{
						//PORTB &= ~(1<<PINB4);					//LED links an
					}
					else
					{
						PORTB &= ~(1<<PINB2);					//LED rechts an
					}
				}
			}

			if(freigabe)										//Wenn Steuerung AN
			{
				
				if(ausschaltsicherung)							//Auschaltsicherung um nicht während Zündung auszuschalten
				{
					if(ButtonPressed(1, PINA, 1, 500))			//Wenn Taster Linearisierung AN/AUS
					{

						if(linearisierung)						//Wenn Linearisierung An
						{
							linearisierung = 0;					//Linearisierung Aus
						}
						else									//Linearisierung An
						{
							linearisierung = 1;				
							
						}
					}
				}
				else
				{
					_delay_us(2500);
				}
			}
		}
	}
	
	
	
//********** Timer Interrupts zum Aufruf des PI Reglers ******************************
	
	ISR (TIMER4_COMPA_vect) 					//In den Interrupt für NDG // 1x pro Halbwelle Strom an PinB1 (SCK) ausgeben  //keine steile Flanke --> PB4 grüne LED
	{
		PORTB &= ~(1<<PINB4);		//LED AN
	}

	ISR (TIMER5_COMPA_vect) 					// Berechnung Id_neu alle 1ms nach Übergabe von Id_alt=Id_neu
	{	

		if (pq == 1){						//pq für positive Halbwelle zuständig
		OCR5B = 28000;	//25500
		y = 2;
		}
		else{
		y=1;
		OCR5B = 8500;    // Durch Ändern dieser Werte wird Verschiebung der Linearisierungsaufrufs während negativer Netzhalbwelle variiert
		}
	}
	
	ISR (TIMER5_COMPB_vect) 					// Aufruf PI Regler alle 3,5 ms nach Netzspannungsnulldurchgang
	{
		
		if (pq ==1) {
			z = 2;
			pq = 0;
		}
		else {
		z=1;
		OCR5C = 21000;
		}
	}	
	
	ISR (TIMER5_COMPC_vect) 					// neue Halbwelle
	{
		x = 2;
		OCR5A = 23000;  
		pq = 1;
	}
	
	
//************ externe Interrups ***********************************************************************		

	/*********Netzsynchronisation*********/
	ISR (INT0_vect)				
	{	
		TCNT1 = 0;							//Timer starten
		ALPHAnutz1 = ALPHA1;
		OCR1A = ALPHAnutz1;					//Setze Vergleichswert A	
		x=1;
		TCNT5 = 0;
		OCR5A=3000;  //2000
		
		

	}
	/*********Leitdauererfassung*********/
	ISR (INT1_vect)				
	{
		int q=1;  //Test für eingelensenen Lamdawert
		
		static int LAMBDAmess = 2100;		//4000
		if(bit_is_clear(PIND, 1))			//bit_is_clear prüft, ob ein Bit gelöscht ist. Wenn das Bit gelöscht ist, also auf 0 ist, wird ein Wert ungleich 0 zurückgegeben.
		{									//Prüft den Pegel der Leitdauererfassung 
			steigendeFlanke = 1;			//Freigabe Zählerstand auslesen
			TCNT3 = 0;						//Timer zurücksetzen
	
			TCNT4 = 0;
			OCR4A = (Id_neu_integer * 2);					// Id*2 wegen 1Takt=0,5us --> 1A == 1ms
			PORTB |= (1<<PINB4); 
		}
		else if(steigendeFlanke)			//Freigabe für steigende Flanke nur wenn vorher fallende Flanke detektiert wurde
		{

			
			steigendeFlanke = 0;			//Freigabe zurücksetzen
			LAMBDAmess = TCNT3;				
			if(LAMBDAmess >= 2100)			//min. 18° um fehlerhaften Zündimpuls zu unterdrücken
			{ 
				LAMBDA = LAMBDAmess;		//Ergebnis in gloaber Variable LAMBDA schreiben
			
			}
	
		}
		
	}
	/*
	|--------------------------------------------------------------------------
	| Software Interrupts
	|--------------------------------------------------------------------------
	*/
	/*********Timer1: Zünden und Löschen der Thyristoren*********/
		
	ISR (TIMER1_COMPA_vect) 					//Zündung erste Halbwelle
	{
		if(freigabe)							//Wenn Steuerung an
		{
			zweiteHalbwelle = 1;				//Lässt das setzen des Vergleichswerts C nur ein Mal zu
			ausschaltsicherung = 0;				//Verhindert ein Ausschalten bei gezündeten Triacs
			weiterZuenden = 1;					//Freigabe für weiteres Zünden nur nachd
			PORTA |= (1<<PINA4);				//T1 an
			PORTA |= (1<<PINA5);				//T2 an
			OCR1B = ALPHAnutz1 + 400;			//Setze Vergleichswert B
		}
	}

	ISR (TIMER1_COMPB_vect)						//Löschen aller gezündeten Pins
	{
		if(freigabe)							//Wenn Steuerung An
		{
			if(weiterZuenden)
			{
				ausschaltsicherung = 1;			//Ausschalten bei gelöschten Triacs zulassen
				PORTA &= ~(1<<PINA4);			//T1 aus
				PORTA &= ~(1<<PINA5);			//T2 aus
				PORTA &= ~(1<<PINA7);			//T3 aus
				PORTA &= ~(1<<PINA6);			//T4 aus
				
					
				if(zweiteHalbwelle)				//Lässt das setzen des Vergleichswerts C nur einmal zu
				{
					zweiteHalbwelle = 0;		//Verhindert ein erneutes setzen des Vergleichswerts C in der zweiten Halbwelle
					ALPHAnutz2 = ALPHA2;
					OCR1C = ALPHAnutz2 + 20000;	//Zündung 10ms später mit gleichem Alpha
				}
				else
				{
					weiterZuenden = 0;			
				}
			}
		}
	}

	ISR (TIMER1_COMPC_vect)						//Zündung zweite Halbwelle
	{
		if(freigabe)							//Wenn Steuerung An
		{
			if(weiterZuenden)
			{
				ausschaltsicherung = 0;			//Verhindert ein Ausschalten bei gezündeten Triacs
				PORTA |= (1<<PINA7);			//T3 an
				PORTA |= (1<<PINA6);			//T4 an
				OCR1B = ALPHAnutz2 + 20400;		//Löschen der Triacs nach 200us
			}
		}
	}

	/*
	|--------------------------------------------------------------------------
	| Funktionen
	|--------------------------------------------------------------------------
	*/	
	/*********Linearisierung*********/
	int Linearisierung( )
	{
		
		
		if(LAMBDA < 15)				//0,135° Gleichung gilt nur für LAMBDA > 0!
		{
			LAMBDA = 15;
		}
		else if (LAMBDA > 20000)	//Lambda darf max. 180° werden -> Lückbetrieb
		{
			LAMBDA = 20000;
		}

		TermI = (LAMBDA * 0.000157)/2;
		TermII = sin(TermI);			
		TermIII = TermII * 3.1415; //3,1415 stand da
		TermIV = ((TermI*2)/TermIII);
		TermV = TermIV * u;
		TermVI = asin(TermV);
		TermVII = 3.1415 - TermI - TermVI;
		TermVIII = TermVII/0.000157;
				
		ErgebnisLin = TermVIII;
				

		if(ErgebnisLin > ALPHAgrenzemax)
			{
				ErgebnisLin = ALPHAgrenzemax;
				u_test = 0;
			}
			else if(ErgebnisLin < 11000)
			{
				ErgebnisLin = 11000;
				u_test = 1;
			} 
			       
		return ErgebnisLin;    //von 28,75us - 461,94us !!   //result = 12698 bei 10000  //14321 bei 7000
	}

	/*********Analog-Digital-Konvertierung*********/
	int ADC_Lesen(void)
	{
		ADCSRA |=(1<<ADEN); 			  	//ADC aktivieren
		ADCSRA |=(1<<ADSC);            		//nächste Umwandlung starten
		while (ADCSRA & (1<<ADSC));			//warten bis die Umwandlung abgeschlossen ist
		ADCSRA &= ~(1<<ADEN);				//ADC deaktivieren
		//rampe = ADCW;
		return ADCW;						//Ergebnis von 0 bis 1023 ausgeben
	}
