www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PWM Ein- und Ausschalten und Interrupts verursacht Probleme


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: nicht Gast (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo, ich habe ein kleines Problem:

Mein Atmega8 soll ein PWM-Signal erzeugen, welches zur Laufzeit ein- und 
ausschaltbar sein soll. Das PWM läuft mit dem Timer1 (Toggle on Compare 
Match)...

Gleichzeitig habe ich eine AD-Wandlung in der ISR laufen. Wenn ich die 
Interrupts (sei() ) nicht aktiviert habe, habe ich keine Probleme. 
Sobald jeadoch sei() gemacht wird, kommt beim BEENDEN des PWMs eine Art 
"Glitch", die Signalform sieht beim letzten Puls ungefähr so aus:

__|''|__|''|__|''|__|'''''''''|____________________


Beendet wird das PWM bei mir zunächst dadurch, dass das Register ICR1 = 
0 gesetzt wird. Dadurch stoppt es auch. Zusätzlich setze ich den Pin, 
über den das PWM ausgegeben wird als als Eingang. Das Problem tritt in 
beiden Fällen auf. Auch ein vorheriges cli() bringt keine Verbesserung, 
das Problem besteht weiterhin. Nur wenn ich die Interrupts gar nicht 
erst aktiviere, tritt der Fehler nicht auf.

Wie wird eigentlich das PWM korrekterweise beendet, habe ich es 
überhaupt richtig gemacht?

Ich hoffe dass es so halbwegs verständlich ist was ich sagen wollte ;)

Weiss einer, was ich falsch mache?... Würde mich über jeden Ratschlag 
freuen, thx!

Autor: Sascha Weber (sascha-w)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
zeig mal komplett wie du deinen Timer konfigurierst!
Um die PWM abzuschalten ist das einfachste den OCx-Pin vom Timer 
abzukoppeln, damit ist für den Pin wieder die Einstellung DDRx und PORTx 
wirksam.

Sascha

Autor: nicht Gast (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
hallo Sascha!

der Timer wird bei mir so konfiguriert:


TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0;
TCCR1B |= 1<<WGM12 | 1<<WGM13  | 1<<CS10;

das mit dem abkoppeln OCx habe ich noch nicht probiert, dafür das 
Abschalten von CSx, hat auch funktioniert jedoch brachte das keine 
Besserung..

Autor: STK500-Besitzer (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
nicht Gast schrieb:
> Hallo, ich habe ein kleines Problem:
>
> Mein Atmega8 soll ein PWM-Signal erzeugen, welches zur Laufzeit ein- und
> ausschaltbar sein soll. Das PWM läuft mit dem Timer1 (Toggle on Compare
> Match)...
>
> Gleichzeitig habe ich eine AD-Wandlung in der ISR laufen. Wenn ich die
> Interrupts (sei() ) nicht aktiviert habe, habe ich keine Probleme.

Sei() in der ISR? Son Quatsch!

> Beendet wird das PWM bei mir zunächst dadurch, dass das Register ICR1 =
> 0 gesetzt wird. Dadurch stoppt es auch. Zusätzlich setze ich den Pin,
> über den das PWM ausgegeben wird als als Eingang.

In welcher ISR verwendest du den ADC? Name?


Zeig einfach dein Programm! Das ist immer besser als rumzustochern.
Es liegt definitv am Programm!

Autor: nicht Gast (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
STK500-Besitzer schrieb:
> nicht Gast schrieb:
>> Hallo, ich habe ein kleines Problem:
>>
>> Mein Atmega8 soll ein PWM-Signal erzeugen, welches zur Laufzeit ein- und
>> ausschaltbar sein soll. Das PWM läuft mit dem Timer1 (Toggle on Compare
>> Match)...
>>
>> Gleichzeitig habe ich eine AD-Wandlung in der ISR laufen. Wenn ich die
>> Interrupts (sei() ) nicht aktiviert habe, habe ich keine Probleme.
>
> Sei() in der ISR? Son Quatsch!

sorry das war ein missverständnis, das sei() steht natürlich nicht in 
der ISR sondern in der main()

STK500-Besitzer schrieb:
>> Beendet wird das PWM bei mir zunächst dadurch, dass das Register ICR1 =
>> 0 gesetzt wird. Dadurch stoppt es auch. Zusätzlich setze ich den Pin,
>> über den das PWM ausgegeben wird als als Eingang.
>
> In welcher ISR verwendest du den ADC? Name?

Es war die ADC_Vect....
Leider habe ich den Stick mit dem Programm nicht bei mir :( Dass es am 
Programm liegt denke ich ja auch..

Autor: Sascha Weber (sascha-w)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
nicht Gast schrieb:
> hallo Sascha!
>
> der Timer wird bei mir so konfiguriert:
>
> TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0;
> TCCR1B |= 1<<WGM12 | 1<<WGM13  | 1<<CS10;

ok - Fast-PWM mit ICR als TOP-Wert

> das mit dem abkoppeln OCx habe ich noch nicht probiert, dafür das
> Abschalten von CSx, hat auch funktioniert jedoch brachte das keine
> Besserung..
du kannst den Ausgang abschalten indem du COM1A0 und COM1A1 auf Null 
setzt, dann läuft die PWM intern weiter am Controllerpin tut sich nix 
mehr.
Wenn du die CS-Bit's auf Null setzt dann bleit der Timer an der Stelle 
stehen und damit sollte sich auch am Ausgang nichts ändern. Eine 
Änderung von OC1x oder ICR könnte aber u.U. eine Änderung des 
Ausgangszustands hervorrufen.

Ohne dein Program kommen wir hier nicht weiter.

Sascha

Autor: nicht Gast (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo, ich habe mich heute noch ein wenig mit dem Programm beschäftigt, 
hab es euch auch angehängt.. (ist natürlich noch Work in Progress, also 
noch alles andere als Fertig..)..
#ifndef F_CPU
#define F_CPU 4000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

static volatile int analog, frequenz, strom = 0;
int pwm = 0;

int main(void)  {
  //Ausgang fuer die PWM
  DDRB |= 1<<PINB1;    
  //Timer initialisiern      
  TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0;
  TCCR1B |= 1<<WGM12 | 1<<WGM13  | 1<<CS10;  
  //AD-Wandler initialisieren
  ADCSRA |= 1<<ADPS2 | 1<<ADPS1; 
  ADMUX |= 1<<REFS0;  
  ADCSRA |= 1<<ADIE;  
  ADCSRA |= 1<<ADEN;  
  
  sei();  
  ADCSRA |= 1<<ADSC;  
  //2 Sekunden warten
  for(int i = 0; i < 2; i++)  {
    _delay_ms(1000);
  }
  //PWM starten...
  uint8_t zaehler = 40;
  OCR1A = zaehler/2;  //Wert für den Tastgrad, für 50 % eingestellt
  ICR1 = zaehler;  //Wert für die Periode
  //5 Sekunden Warten...
  for(int i = 0; i < 5; i++)  {
    _delay_ms(1000);
  }
  //PWM ausschalten mit unterschiedlichen Methoden...
  cli();
  TCCR1B &= ~(1<<CS10);
  ICR1 = 0;
  OCR1A = 0;
  DDRB &= ~(1<<PINB1);  

    while(1);  
  return 0;
}

ISR(ADC_vect)  {  
  //Auslesen des AD-Wandlers mit 10 bit
  uint8_t lowByte = ADCL;  
  analog = ADCH<<8 | lowByte;  
  //Umaschalten zwischen 2 Kanälen
  switch(ADMUX)  {
    case 0x40:  
      ADMUX = 0x41;
      strom = analog;
      break;
    
    case 0x41:  
      ADMUX = 0x40;
      frequenz = analog;
      break;
      
    default:
      break;  
  }
  ADCSRA |= 1<<ADSC;  // Nächste AD-Wandlung starten
}

Momentan soll das PWM über das _delay() eine Zeit lang am Leben gehalten 
werden, später wird das dann durch einen Analogwert ersetzt. Bei dem 
_delay() ist mir aufgefallen, dass es nicht bei allen Werten dieses 
Problem gibt.. Bei einem Delay von 5 Sekunden z.B. habe ich den Fehler, 
bei 4 Sekunden wiederum nicht.. Könnte es eventuell nur an der 
_delay()-Funkton liegen? eine andere Möglichkeit der zeitlichen 
Veränderung kann ich momentan leider schlecht testen...

thx!

Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
nicht Gast schrieb:

>   //PWM ausschalten mit unterschiedlichen Methoden...
>   cli();
>   TCCR1B &= ~(1<<CS10);
>   ICR1 = 0;
>   OCR1A = 0;


damit hast du erst mal nur den Timer angehalten.
Aber: Die Ausgabepins sind immer noch an den Timer gekoppelt, der sie 
unter seiner Fuchtel hat.
Und solange du das hier

  TCCR1A |=  ..... 1<<COM1A1 | 1<<COM1A0 .....

nicht rückgängig machst, bleibt das auch so.
Erst indem du die Pins durch Abschalten der COM... Bits wieder vom Timer 
entkoppelt hast, kriegst du wieder die Kontrolle darüber.

Autor: nicht Gast (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo, ich glaube das hat jetzt gewirkt. Wenn ich die COM pins 
abschalte, dann scheint das PWM bisher immer korrekt abzuschalten. Ist 
es dann eigentlich notwendig, den Timer noch zu stoppen bzw noch auf 
andere Weise sicherzustellen dass der Pin, an dem das PWM ausgegeben 
wird, nicht doch noch verrückt spielt?

Autor: Sascha Weber (sascha-w)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
nicht Gast schrieb:
> Hallo, ich glaube das hat jetzt gewirkt. Wenn ich die COM pins
> abschalte, dann scheint das PWM bisher immer korrekt abzuschalten. Ist
> es dann eigentlich notwendig, den Timer noch zu stoppen bzw noch auf
> andere Weise sicherzustellen dass der Pin, an dem das PWM ausgegeben
> wird, nicht doch noch verrückt spielt?
den Timer kannst du im Hintergrund ruhig weiterlaufen lassen, sind die 
COM-Bits auf 0 dann hat der Pin den durch DDRx,PORTx vorgegebenen 
Zustand.
Auch anhalten den Timers mit CSxy=0 sollte die PWM sicher stoppen, 
allerdings sollte man dann die ICR, OCR Register nicht mehr ändern.

Sascha

Autor: nicht Gast (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
ok das klingt schonmal gut. Dann würde ich den Pin anfangs auf 0 setzen, 
denn meine einzige Sorge ist, dass er irgendwann auf 1 geht und dort 
bleibt, das wäre für meine Anwendung nicht so gut!


danke schonmal!

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net