3 Triacs gleichzeitig ansteuern mit dem Mega168

Gast #748460
Lesenswert?

Hallo,

ich habe mir eine Schaltung aufgebaut, bei der ich 12V Wechselspannung 
mit Triacs anschneiden will.
Insgesamt habe ich 3 Ausgänge, welche über Ports vom Mega168 angesteuert 
werden.
Ich gehe hierbei folgendermaßen vor:

Der Nulldurchgang der Wechselspannung wird detektiert und je ein 
Interrupt ausgelöst. Ab diesem Zeitpunkt wir der Triac entweder sofort, 
oder verzögert gezündet. (0...10ms)
Das funktioniert auch wunderbar bei einem Triac. Wenn ich nun jedoch die 
3 Triacs zu verschiedenen Zeitpunkten zünden will, also z.B. den ersten 
bei t=0ms, den 2. bei t=2ms und den 3. bei t=7ms bekomme ich da wohl 
Probleme, da dieses ja nicht parallel abgearbeitet werden kann.

Wäre über Tipps sehr dankbar.

Code habe ich noch keine, aber die Schaltung stelle ich demnächst mal 
rein.

Grüße
Robert
Gast #760305
Lesenswert?

Das problem ist allerdings, wenn die Triacs fast zum gleichen Zeitpunkt 
zünden sollen, ist die Rechenleistung nicht hoch genug und es zündet nur 
der erste.

Ich takte den MC mit 8MHz. Eine Halbwelle der Netzphase ist 10ms lang. 
Wenn nun der erste Triac bei 2ms zünden soll und der zweite bei 2,1ms, 
dann wird dieser ausgelassen. Nachfolgend habe ich mal den Code nur für 
das Zünden der Triacs bei festen Werten aufgeführt. Das Resultat ist, 
dass die zuerst gezündete Lampe gedimmt leuchtet, die anderen aber wild 
blinken.
Es sollen später auch noch die ADCs ausgelesen, sowie ein LCD 
angesteuert werden. Das wünde dann noch mehr rechenleistung kosten.

Der INT0, bei welchem phase auf 1 gesetzt wird, wird immer beim 
Phasennullduchgang ausgelöst.

Der Schaltplan befindet sich im Anhang.

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <lcd.h>
#include <lcd.c>

volatile uint8_t phase;

ISR (INT0_vect)
{
  TCNT1=0;
  phase=1;
}


int main(void)
{

  DDRC=0xff;
  PORTC=0xff;
  DDRB=0xff;

  EICRA|=(1<<ISC00);
  EIMSK|=(1<<INT0);

    TCCR1B|=(1<<CS11)|(1<<CS10);TIMSK1|=(1<<TOIE1);  //Timer1

    sei();


    while(1)
  {

  while(phase==1)
  {

  if(TCNT1==900)  //TCNT1=1200 entspticht 10ms
  {
  PORTC &= ~(1<<PC3);
  _delay_us(100);
  PORTC |= (1<<PC3);

         if(a>b & a>c)
  phase=0;

  }

  if(TCNT1==910)
  {
  PORTC &= ~(1<<PC4);
  _delay_us(100);
  PORTC |= (1<<PC4);

  if(b>a & b>c)
  phase=0;
  }

  if(TCNT1==920)
  {

  PORTC &= ~(1<<PC5);
  _delay_us(100);
  PORTC |= (1<<PC5);

  if(c>a & c>b)
  phase=0;

  }
     }

  }
}


MFG
Gast #760327
Lesenswert?

>Das problem ist allerdings, wenn die Triacs fast zum gleichen Zeitpunkt
>zünden sollen, ist die Rechenleistung nicht hoch genug und es zündet nur
>der erste.

Quatsch. Du verwendest  _delay_us(100);
 _delay_us(); ist mit Vorsicht zu geniessen.


6.22.2.2 void _delay_us (double __us)
Perform a delay of __us microseconds, using _delay_loop_1().
The macro F_CPU is supposed to be defined to a constant defining the CPU 
clock
frequency (in Hertz).
The maximal possible delay is 768 us / F_CPU in MHz.

In deinem Fall 768 us / 8 = 96us. 100us ist zu viel !

Hast du auch Optimierung im makefile eingeschaltet ?
Gast #760350
Lesenswert?

Hallo Robert,

die Verzögerung ist auf jeden Fall die Quelle des Problems. Wenn Du den 
ersten Triac bei 2ms zündest und dann bei

 if(TCNT1==900)  //TCNT1=1200 entspticht 10ms
  {
  PORTC &= ~(1<<PC3);
  _delay_us(100);
  PORTC |= (1<<PC3);

         if(a>b & a>c)
  phase=0;
  }

eben 100us wartest, wird das Programm beim Zeitpunkt von 2ms+100us noch 
warten (= nicht wieder in der Hauptschleife sein!) und so den Zeitpunkt 
zum Zünden des 2. Triacs verpassen.

Gruß

Fred
Gast #760373
Lesenswert?

Ich habe einen Fehler im code gemacht:

den Timerwerten TCNT1 habe ich a,b und c zugeordnet. Mit den Abfragen

if(a>b & a>c)

findet man heraus, welcher Triac als letzter zündet. Und bei diesem wird 
phase auf 0 gesetzt und die whileschleife wird verlassen.
Gast #760386
Lesenswert?

Dieser Code macht dasselbe Problem:

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <lcd.h>
#include <lcd.c>


#define UART_BAUD_RATE      9600


volatile uint8_t phase;

volatile uint16_t a=200;
volatile uint16_t b=600;
volatile uint16_t c=900;

volatile char buffer[16];
volatile char s[16];

volatile uint8_t update=0;


ISR (INT0_vect)
{
  TCNT1=0;
  phase=1;
}


int main(void)
{


  DDRC=0xff;
  PORTC=0xff;
  DDRB=0xff;

  EICRA|=(1<<ISC00);
  EIMSK|=(1<<INT0);

    TCCR1B|=(1<<CS11)|(1<<CS10);TIMSK1|=(1<<TOIE1);        //Timer1

    TCCR0B|=(1<<CS02)|(1<<CS00);TIMSK0|=(1<<TOIE1);


  sei();


    while(1)
  {


         while(phase==1)
  {

  if(TCNT1==a)  //TCNT1=1200 entspticht 10ms
  {
  PORTC &= ~(1<<PC3);
  _delay_us(50);
  PORTC |= (1<<PC3);

  if(a>b & a>c)
  phase=0;
         }

         if(TCNT1==b)
  {

  PORTC &= ~(1<<PC4);
         _delay_us(50);
  PORTC |= (1<<PC4);

  if(b>a & b>c)
  phase=0;
  }

  if(TCNT1==c)
  {
         PORTC &= ~(1<<PC5);
  _delay_us(50);
  PORTC |= (1<<PC5);

  if(c>a & c>b)
  phase=0;

  }
      }

    }
}
Gast #760426
Lesenswert?

Vieleicht triffst du TCNT1 ja nicht immer GENAU auf den Punkt ;)

while(phase==1)
 {
  unsigned int tmrtmp;
  cli();
  tmrtmp = TCNT1;
  sei();

  if(tmrtmp>=a && tmrtmp<b)  //TCNT1=1200 entspticht 10ms
   {
    PORTC &= ~(1<<PC3);
    _delay_us(50);
    PORTC |= (1<<PC3);
    if(a>b && a>c)  phase=0;
   }

  if(tmrtmp>=b && tmrtmp<c)
  {
    PORTC &= ~(1<<PC4);
    _delay_us(50);
    PORTC |= (1<<PC4);
    if(b>a && b>c)  phase=0;
  }

  if(tmrtmp>=c)
  {
   PORTC &= ~(1<<PC5);
   _delay_us(50);
   PORTC |= (1<<PC5);
   if(c>a && c>b) phase=0;
  }

 }

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren