Hallo Zusammen,
also, wir möchten einen Phasenanschnittsteuerung über eine W4
Sparschaltung Realisieren, die es ermöglichen soll eine DAM im 1+4
Quadranten Sanft Hochlaufen zu lassen bzw. zu Reversieren. Gesteuert
wird das ganze über einen Poti mit 1024 Werten/Bits. Abhängig von den
Stellung des Ptotis wird eine Rampenfunktion für Alpha generiert und
zwar so,
dass wenn der Poti in der Mittesteht (Potiwert 400-600) der Maschine
steht.
Potiwert 400->0 Linkslauf
Potiwert 400->600 Stillstand
Potiwert 600->1023 Rechtslauf.
Für sich genommen Funktionieren Linkslauf und Rechtslauf auch wunderbar,
das Problem entsteht erst wenn alle Programmteile zusammengefügt werden.
Hier kommt es zu einem Rütteln was auf Fehlzündungen hindeutet, bzw.
auch schon zur Zerstörung Triacs geführt hat.
Im Stillstand werden alle Zündimpulse ausgeschaltet, zusätzlich alle
Timer und Comparewerte zurückgesetzt und zu guter letz die
Initialisierung wiederholt und auf Nummer sicherzugehen, da eine
Falsches Zünden der Triacs diese ja zerstören würde.
Der µC ist eine Atmega16.
Vielen Dank schonmahl für Anregungen und Tipps.
Quellcode.
/************************************PHASENANSCHNITTSTEUERUNG***********
***************************************
Microcontroller: ATMEGA2561
Clock: 16.0000MHz
AVR Hardware: Timer1, Timer3,
externe Hardware: W4-Reversiersparschaltung
//------------------------------------------------------------------
//
// PowerModul
//
#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define DDRT1 DDRG //Datenrichtung für das W2 Stellglied
#define DDRT2 DDRF
#define DDRT3 DDRA
#define DDRT4 DDRF
#define PORTT1 PORTG
#define PORTT2 PORTF
#define PORTT3 PORTA
#define PORTT4 PORTF
#define T1 PG5 //rechts L1 Ausgangsbits für das W4 Stellglied
#define T2 PF3 //rechts L3
#define T3 PA2 //Links L3
#define T4 PF1 // Links L1 Ausgangsbits für das W4 Stellglied
//**********************************************************************
**********//POTI
uint16_t ADC_Wert;
//int ADC_Wert_min_R = 600;
//int ADC_Wert_max_R = 1023;
float alpha1=0;
float alpha2=0;
int alpha1_min=12777;
int alpha1_max=18888;
int alpha2_min=32777;
int alpha2_max=38888;
float alpha1_Aus =0;
float alpha2_Aus =0;
int alpha1_min_Aus =18888;
int alpha1_max_Aus =18888;
int alpha2_min_Aus =38888;
int alpha2_max_Aus =38888;
//**********************************************************************
**********
//*************************************ADC******************************
**********
void AdcInit (void)
{
ADMUX |= (0<<MUX0) | (0<<MUX1) | (1<<MUX2); //ADC4
ADMUX |= (1<<REFS0); //externe Referenzspannung nutzen 5 V
ADCSRA |=(1<<ADEN); //ADC überhaupt zu aktivieren.
ADMUX |= (0<< ADLAR); // Die 8 bit kommen in das Low-Register
ADCSRA |=(1<<ADSC); //Messvorgang startet.
ADCSRA |=(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);//Vorteiler 128
}
uint16_t ADC_Lesen(void)
{
uint16_t result = 0;
ADCSRA |=(1<<ADEN); //ADC aktivieren.
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung
warten
ADCSRA &= ~(1<<ADEN); // ADC wieder deaktivieren
result = ADCW;
return result; // ADC auslesen und zurückgeben
}
//**********************************************************************
**********
// Funktionen
//**********************************************************************
**********
// Initialisierung W2 Stellglied
// diese funktionen in main 1x aufrufen
/*****************************PORT-Initialisierung*****************/
void w4Init(void)
{
DDRD=0x00; //Eingang Nulldurchgang
// Initialisierung Datenrichtung für das W2 Stellglied(als Äusgange
festgelegt)
DDRT1 |= (1<<T1); //DDRTn sind per (#define) definiert worden
DDRT2 |= (1<<T2);
DDRT3 |= (1<<T3);
DDRT4 |= (1<<T4);
PORTT1= 0x00; // PORTG high aktiv
PORTT2= 0x00; // PORTF high aktiv
PORTT3= 0x00; // PORTA high aktiv
PORTT4= 0x00; // PORTF high aktiv
//Ausgänge für LED initialisieren
DDRB |= (1<<PB1);//(1<<PB1) | (1<<PB2) | (1<<PB3); // Ausprobieren ob
alle Led noch leuchten?????
}
/*****************************Initialisierung
Timer/Counter1*********************************/
void Timer1Init(void) {
//Timer Clock = CPU Clock / 8
//Mode = 0 (Normal)
//TCCR1B= 0x02;//TCCR1B |= (0<<CS10) | (1<<CS11)| (0<<CS12);// CPU Takt
/ 8
TCCR1B=0x00; //stop Timer // Damit Timer bei 0 anfängt
TCCR1A= 0x00; //normal Mode // Inkrementale Aufzählung
// Interrupts TimerCounter1 aktivieren
TIMSK1 |=(1<<OCIE1C) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1); //
TIMSK1=0b00001111; //compare Register A B C
// Initialisierung Externe Interrupts / Nulldurchgangserkennung
// ND L12 //INT1 Ein = PORTD Pin 1
EIMSK |= (1<<INT1); // EIMSK |= 0b00000010; //enable INT1 // 0x01//
Damit wird INT1 aktiviert
EICRA |= (1<<ISC11) | (1<<ISC10); /*EICRA |= 0b00001100//0x0c;
//00000011
rising; 0x04 anyEdge // INT1 reagiert
auf steigende Flanke*/
TCNT1 = 0; // Timer1 auf Null setzen
OCR1C=7222;
TCCR1B= 0x02; //Vorteiler 8 //start Timer
}
/*****************************Initialisierung
Timer/Counter4*********************************/
void Timer4Init(void) {
TCCR4B=0x00; //stop Timer // Damit Timer bei 0 anfängt
TCCR4A= 0x00; //normal Mode // Inkrementale Aufzählung
// Interrupts TimerCounter1 aktivieren
TIMSK4 |= (1<<OCIE4B) | (1<<OCIE4A) | (1<<TOIE4); // TIMSK1=0b00001111;
//compare Register A B
// Initialisierung Externe Interrupts / Nulldurchgangserkennung
// ND L12 //INT1 Ein = PORTD Pin 1
EIMSK |= (1<<INT1); // EIMSK |= 0b00000010; //enable INT1 // 0x01//
Damit wird INT1 aktiviert
EICRA |= (1<<ISC11) | (1<<ISC10); /*EICRA |= 0b00001100//0x0c;
//00000011
rising; 0x04 anyEdge // INT1 reagiert
auf steigende Flanke*/
TCNT4 = 0; // Timer1 auf Null setzen
TCCR4B= 0x02; //Vorteiler 8 //start Timer
}
/*****************************Initialisierung
Timer/Counter3*********************************/
void Timer3Init(void) {
TCCR3B=0x00; //stop Timer // Damit Timer bei 0 anfängt
TCCR3A= 0x00; //normal Mode // Inkrementale Aufzählung
// Interrupts TimerCounter1 aktivieren
TIMSK3 |= (1<<OCIE3B) | (1<<OCIE3A) | (1<<TOIE3); // TIMSK1=0b00001111;
//compare Register A B
TCNT3 = 0; // Timer3 auf Null setzen//
TCCR3B= 0x02; //Vorteiler 8 //start Timer
}
/*****************************Initialisierung
Timer/Counter5*********************************/
void Timer5Init(void) {
TCCR5B=0x00; //stop Timer // Damit Timer bei 0 anfängt
TCCR5A= 0x00; //normal Mode // Inkrementale Aufzählung
// Interrupts TimerCounter1 aktivieren
TIMSK5 |= (1<<OCIE5B) | (1<<OCIE5A) | (1<<TOIE5); // TIMSK1=0b00001111;
//compare Register A B
TCNT5 = 0; // Timer1 auf Null setzen
TCCR5B= 0x02; //Vorteiler 8 //start Timer
}
/******************************EXTERNER Interrupt*****************/
ISR (INT1_vect) //INT1 hinter RESET höchste Priorität
//Netzsynchronisation
{ // wird jedesmal aufgerufen wenn der Netznullgang
kommt
alphawerteInterrupt1();
}//ISR(INT1_vect)
/***************************ZÜNDMUSTER_RECHSTSLAUF ********************/
ISR (TIMER1_COMPA_vect)
{
zuendmustereinL1(); //positive Halbwelle //zuendEinL1();
}
ISR (TIMER1_COMPB_vect)
{
zuendmustereinL1(); //Negative Halbwelle //zuendEinL1();
}
ISR (TIMER1_COMPC_vect)
{
alphawertetimer1compC();
}//ISR_timer1_compC
ISR (TIMER4_COMPA_vect)
{
zuendmusterausL1(); //positive Halbwelle //zuendAusL1();
}
ISR (TIMER4_COMPB_vect)
{
zuendmusterausL1(); //Negative Halbwelle //zuendAusL1();
}
ISR (TIMER3_COMPA_vect)
{
zuendmustereinL3(); //positive Halbwelle //zuendEinL3();
}
ISR (TIMER3_COMPB_vect)
{
zuendmustereinL3(); //Negative Halbwelle //zuendEinL3();
}
ISR (TIMER5_COMPA_vect)
{
zuendmusterausL3(); //Positive Halbwelle //zuendAusL3();
}
ISR (TIMER5_COMPB_vect)
{
zuendmusterausL3(); //Negative Halbwelle //zuendAusL3();
}
//********************************INITIALISIERUNG*******************
void Init()
{
w4Init();
Timer1Init();
Timer4Init();
Timer3Init();
Timer5Init();
AdcInit();
}
//*****************************HAUPT-PROGRAMM********************/
int main() {
cli(); //disable Interrupts
Init();
sei(); //alles initialisiert
while(1) {
ADC_Wert= ADC_Lesen();
}
}
/****************************************************Funktionen*********
****************************************************/
void zuendungaus(void)
{
Init();
PORTT1 &= ~ (1<<T1); //triac für rechtslauf auf low setzten
//zuendAusL1();
PORTT2 &= ~ (1<<T2); //triac für rechtslauf auf low setzten
//zuendAusL3();
PORTT3 &= ~ (1<<T3); //triac für Linkslauf auf low setzten
//zuendAusL3();
PORTT4 &= ~ (1<<T4); //triac für Linkslauf auf low setzten
//zuendAusL1();
TCNT1= 0;
OCR1A= 0;
OCR1B= 0;
TCNT4= 0;
OCR4A= 0;
OCR4B= 0;
//-----------------------------------------------------------------
TCNT3= 0;
OCR3A= 0;
OCR3B= 0;
TCNT5= 0;
OCR5A= 0;
OCR5B= 0;
}//Zuendungaus
void alphawerteInterrupt1(void)
{
if ((ADC_Wert >= 600) && (ADC_Wert <= 1023))
{
if ((ADC_Wert >= 1013) && (ADC_Wert <= 1023))
{
vollsteuerungL1 ();
}//if//vollsteuerung//rechtslauf
if ((ADC_Wert >= 600) && (ADC_Wert < 1013))
{
alpha1=(((alpha1_min - alpha1_max)/(1013-600))* (ADC_Wert-600))+
alpha1_max; //rechtslauf();
alpha2=(((alpha2_min - alpha2_max)/(1013-600))* (ADC_Wert-600))+
alpha2_max;
TCNT1= 0; // Timer1 wird bei Nulldurchgang auf null gesetzt
OCR1A=alpha1 ;
OCR1B=alpha2;
//-----------------------------------------
alpha1_Aus=(((alpha1_min_Aus - alpha1_max_Aus)/(1013 - 600))*
(ADC_Wert - 600))+ alpha1_max_Aus;
alpha2_Aus=(((alpha2_min_Aus - alpha2_max_Aus)/(1013 - 600))*
(ADC_Wert - 600))+ alpha2_max_Aus;
TCNT4= 0; // Timer4 wird bei Nulldurchgang auf null gesetzt
OCR4A= alpha1_Aus; //18888;
OCR4B= alpha2_Aus; //38888;
}
}//if//rechtslauf
if ((ADC_Wert >= 0) && (ADC_Wert <= 400))
{
if ((ADC_Wert >=0) && (ADC_Wert <= 10))
{
vollsteuerungL1 ();
}//if//vollsteuerung//linkslauf
if ((ADC_Wert > 10) && (ADC_Wert <= 400))
{
alpha1=(((alpha1_max - alpha1_min)/(400-10))* ADC_Wert)+
alpha1_min; //linkslauf();
alpha2=(((alpha2_max - alpha2_min)/(400-10))* ADC_Wert)+
alpha2_min;
TCNT1= 0; // Timer1 wird bei Nulldurchgang auf null gesetzt
OCR1A=alpha1 ;
OCR1B=alpha2;
//---------------------------------------
alpha1_Aus=(((alpha1_max_Aus - alpha1_min_Aus)/(400 - 10))*
(ADC_Wert - 10))+ alpha1_min_Aus;
alpha2_Aus=(((alpha2_max_Aus - alpha2_min_Aus)/(400 - 10))*
(ADC_Wert - 10))+ alpha2_min_Aus;
TCNT4= 0; // Timer4 wird bei Nulldurchgang auf null gesetzt
OCR4A= alpha1_Aus; //18888;
OCR4B= alpha2_Aus; //38888;
}
}//if//Linkslauf
if ((ADC_Wert > 400) && (ADC_Wert < 600))
{
zuendungaus();
}//if//Zuendungaus
}//alphawerteInterrupt1
void alphawertetimer1compC(void)
{
if ((ADC_Wert >= 600) && (ADC_Wert <= 1023))
{
if ((ADC_Wert >= 1013) && (ADC_Wert <= 1023))
{
vollsteuerungL3 ();
}//if//vollsteuerung//rechtslauf
if ((ADC_Wert >= 600) && (ADC_Wert < 1013))
{
alpha1=(((alpha1_min - alpha1_max)/(1013-600))* (ADC_Wert-600))+
alpha1_max; //rechtslauf();
alpha2=(((alpha2_min - alpha2_max)/(1013-600))* (ADC_Wert-600))+
alpha2_max;
OCR3A=alpha1;
OCR3B=alpha2;
//----------------------------------------------------------
alpha1_Aus=(((alpha1_min_Aus - alpha1_max_Aus)/(1013 - 600))*
(ADC_Wert - 600))+ alpha1_max_Aus;
alpha2_Aus=(((alpha2_min_Aus - alpha2_max_Aus)/(1013 - 600))*
(ADC_Wert - 600))+ alpha2_max_Aus;
OCR5A= alpha1_Aus; //18888;
OCR5B= alpha2_Aus; //38888;
}
}//if//rechtslauf
if ((ADC_Wert >= 0) && (ADC_Wert <= 400))
{
if ((ADC_Wert >=0) && (ADC_Wert <= 10))
{
vollsteuerungL3 ();
}//if//vollsteuerung//linkslauf
if ((ADC_Wert > 10) && (ADC_Wert <= 400))
{
alpha1=(((alpha1_max - alpha1_min)/(400-10))* ADC_Wert)+
alpha1_min; //linkslauf();
alpha2=(((alpha2_max - alpha2_min)/(400-10))* ADC_Wert)+
alpha2_min;
TCNT3= 0; // Timer3 wird nach 3,33ms (60°) auf null gesetzt
OCR3A=alpha1;
OCR3B=alpha2;
//------------------------------------------------------------------
alpha1_Aus=(((alpha1_max_Aus - alpha1_min_Aus)/(400 - 10))*
(ADC_Wert - 10))+ alpha1_min_Aus;
alpha2_Aus=(((alpha2_max_Aus - alpha2_min_Aus)/(400 - 10))*
(ADC_Wert - 10))+ alpha2_min_Aus;
TCNT5= 0; // Timer5 wird nach 3,33ms (60°) auf null
gesetzt
OCR5A= alpha1_Aus; //18888;
OCR5B= alpha2_Aus; //38888;
}
}//if//Linkslauf
if ((ADC_Wert > 400) && (ADC_Wert < 600))
{
zuendungaus();
}//if//Zuendungaus
}//alphawertetimer1compC
void zuendmustereinL3(void)
{
if ((ADC_Wert >= 0) && (ADC_Wert <= 400))
{
PORTT2 &= ~ (1<<T2);
//?????????????????????????????????
PORTT3 |= (1<<T3); //triac für Linkslauf
zünden //zuendEinL3();
PORTB &= ~(1<<PB1); // Grüne Led geht an
//linkslauf();
}
if ((ADC_Wert > 400) && (ADC_Wert < 600))
{
zuendungaus();
}
if ((ADC_Wert >= 600) && (ADC_Wert <= 1023))
{
PORTT3 &= ~
(1<<T3);//???????????????????????????????
PORTT2 |= (1<<T2); //triac für rechtslauf zünden
//zuendEinL3();
PORTB &= ~(1<<PB1); // Grüne Led geht
an//rechtslauf();
}
}
void zuendmusterausL3(void)
{
if ((ADC_Wert >= 0) && (ADC_Wert <= 400))
{
PORTT3 &= ~ (1<<T3); //triac für Linkslauf auf low
setzten //zuendAusL3();//linkslauf();
}
if ((ADC_Wert > 400) && (ADC_Wert < 600))
{
zuendungaus();
}
if ((ADC_Wert >= 600) && (ADC_Wert <= 1023))
{
PORTT2 &= ~ (1<<T2); //triac für rechtslauf auf low
setzten //zuendAusL3();//rechtslauf();
}
}
void zuendmustereinL1(void)
{
if ((ADC_Wert >= 0) && (ADC_Wert <= 400))
{
PORTT1 &= ~ (1<<T1);//???????????????????????????????
PORTT4 |= (1<<T4); //triac für Linkslauf zünden
//zuendEinL1();
PORTB &= ~(1<<PB1); // Grüne Led geht an
//linkslauf();
}
if ((ADC_Wert > 400) && (ADC_Wert < 600))
{
zuendungaus();
}
if ((ADC_Wert >= 600) && (ADC_Wert <= 1023))
{
PORTT4 &= ~ (1<<T4);
//????????????????????????????????????????ß
PORTT1 |= (1<<T1); //triac für rechtslauf zünden
//zuendEinL1();
PORTB &= ~(1<<PB1); // Grüne Led geht an
//rechtslauf();
}
}
void zuendmusterausL1(void)
{
if ((ADC_Wert >= 0) && (ADC_Wert <= 400))
{
PORTT4 &= ~ (1<<T4); //triac für Linkslauf auf
low setzten //zuendAusL1();//linkslauf();
}
if ((ADC_Wert > 400) && (ADC_Wert < 600))
{
zuendungaus();
}
if ((ADC_Wert >= 600) && (ADC_Wert <= 1023))
{
PORTT1 &= ~ (1<<T1); //triac für rechtslauf auf low
setzten //zuendAusL1();//rechtslauf();
}
}
void vollsteuerungL1 (void){
TCNT1= 0;
OCR1A= 2777;
OCR1B= 22777;
TCNT4= 0;
OCR4A= 0;
OCR4B= 0;
}
void vollsteuerungL3 (void){
TCNT3= 0;
OCR3A= 2777;
OCR3B= 22777;
TCNT5= 0;
OCR5A= 0;
OCR5B= 0;
}