mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 3 Triacs gleichzeitig ansteuern mit dem Mega168


Autor: Robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es wird nur ein Interrupt beim Nulldurchgang ausgelöst, es sei denn, Du 
hast mehrere Phasen. In diesem Interrupt setzt Du Zählvariablen zurück. 
In einem Timerinterrupt zählst Du wiederum diese Variablen hoch und beim 
Erreichen der Sollwerte zündest Du den jeweiligen Triac. Kein Problem 
also.

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: robert (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Hochladen des Schaltplans hat wohl nicht geklappt.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist auf jeden Fall mal ein guter Tipp.
Die Optimierung ist ausgeschalten.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

  }
      }

    }
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  if(b>a & b>c)

  if(b>a && b>c)

Autor: robert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stimmt, aber ich habe diese Abfrage mal mit dem Debugger getestet und es 
funktioniert so.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.