- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 3 von 3

Thema: PWM mit AVR: Rätselhafte Pulssprünge

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    44
    Beiträge
    269

    PWM mit AVR: Rätselhafte Pulssprünge

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Moin moin!

    Ich erzeuge mit einem ATmega48 vier PWM-Signale, mit denen ich jeweils einen Brushless-Regler mit entsprechendem Motor ansteuere. Im Prinzip funktioniert das auch super. Bloß, wenn ich die Drehzahl der Motoren ändere, zum Beispiel mit einer steigenden Rampe für die PWM-Pulse von 1 ms bis 2 ms, dann ändert sie sich nicht gleichmäßig, sondern springt gelegentlich zurück und läuft von dem kleineren Wert weiter.

    Mit dem Testprogramm unten wollte ich der Sache auf den Grund gehen. Die Werte im Testarray werden der Reihe nach an den Regler gegeben. Den ersten Wert (2000, entspricht 1 ms) braucht der Regler zum Anspringen; der Motor läuft erst beim zweiten Wert los. Dann werden die weiteren Werte für jeweils etwa 5 sec gehalten. Von 2350 auf 2360 springt die Drehzahl aber nicht hoch, sondern deutlich hörbar auf einen viel kleineren Wert. Von diesem kleineren Wert geht es dann in 5-sec-Schritten weiter aufwärts, bis nach dem letzten Wert im Array wieder die 2000 kommen und der Motor stehenbleibt.

    Während einer 20-sec-Rampe von 1 ms bis 2 ms (mit einem anderen Programm) kommen mehrere solcher Sprünge vor und es scheint auch so zu sein, daß die Drehzahl zwischendurch manchmal wieder auf die ursprünglichen Rampenverlauf hochspringt. Sorry, weiß nicht, wie ich das besser ausdrücken soll... Genau messen kann ich die Drehzahl leider nicht, habe keinen Drehzahlmesser (abgesehen vom Gehör ).

    Kann sich irgendjemand erklären, woher diese Sprünge in der Drehzahl kommen??

    Alle vier BL-Regler/Motoren verhalten sich gleich, also vermute ich den Fehler eher in der Pulslänge. Die läßt sich leider nicht genau messen. Ich habe zwar ein Oszi, aber das triggert die Pulse nicht richtig. Wenn ich die Auflösung so stelle, daß ich einen Puls genau messen kann, erscheinen nur noch sporadisch Pulse auf dem Bildschirm. Zoome ich soweit raus, daß z.B. 5 Pulse auf dem Schirm sind, kann ich erkennen, daß die Pulse zwischen 1 ms und 2 ms lang sind und sich alle 20 ms wiederholen, aber dann läßt sich die Pulslänge schlecht genauer messen... Das Oszi-Bild springt immer etwas hin und her, also hat entweder der Trigger ne Macke, oder meine Funktion zur PWM-Erzeugung. Vermutlich eher letzteres, aber ich find den Fehler einfach nicht.

    Ach so: der Motor pfeift immer ein bißchen. Das macht er nicht, wenn ich statt meines AVRs einen RC-Empfänger benutze. Ich denke, das spricht auch für einen Fehler in meinem Programm.

    Hier ist der Code:

    Code:
    // Code for ATmega48/16MHz
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #define MIN 2000				// Clock cycles for a PWM pulse of 1 ms (Timer0, prescaler=8)
    #define MAX 4000				// Clock cycles for a PWM pulse of 2 ms (Timer0, prescaler=8)
    #define PERIOD 40000			// Clock cycles for whole PWM period of 20 ms (Timer 0, prescaler=8)
    
    volatile long	sig_3,sig_4,sig_5,sig_6,sigcount_3,sigcount_4,sigcount_5,sigcount_6,percounter=PERIOD;
    volatile long	auxcounter=0;
    volatile int	i=0;
    volatile long	testarray[]={2000,2330,2340,2350,2360,2370,2380,2390,2400,2410,2420,2430,2440,2450,2460};
    
    long min(long a, long b, long c, long d, long e, long f) {
    	long h=a;
    	if((b<h)&&(b>0)) h=b;
    	if((c<h)&&(c>0)) h=c;
    	if((d<h)&&(d>0)) h=d;
    	if((e<h)&&(e>0)) h=e;
    	if((f<h)&&(f>0)) h=f;
    	return h;
    }
    
    ISR(SIG_OUTPUT_COMPARE0A) {
    	if(sigcount_3>0) sigcount_3-=OCR0A;
    	if(sigcount_4>0) sigcount_4-=OCR0A;
    	if(sigcount_5>0) sigcount_5-=OCR0A;
    	if(sigcount_6>0) sigcount_6-=OCR0A;
    	if(percounter>0) percounter-=OCR0A;
    	
    	if(sigcount_3==0) { PORTB&=~(0x02); }			//Reset Pin OC1A (=PB1)
    	if(sigcount_4==0) { PORTB&=~(0x04); }			//Reset Pin OC2B (=PB2)
    	if(sigcount_5==0) { PORTB&=~(0x08); }			//Reset Pin OC2A (=PB3)
    	if(sigcount_6==0) { PORTD&=~(0x08); }			//Reset Pin OC2B (=PD3)
    	
    	if(percounter==0) {
    		/*Block TWI Interrupt*/
    		percounter=PERIOD;							//New period starts
    		sigcount_3=sig_3; PORTB|=(0x02);				//Set Pin OC1A (=PB1)
    		sigcount_4=sig_4; PORTB|=(0x04);				//Set Pin OC1B (=PB2)
    		sigcount_5=sig_5; PORTB|=(0x08);				//Set Pin OC2A (=PB3)
    		sigcount_6=sig_6; PORTD|=(0x08);				//Set Pin OC2B (=PD3)
    		OCR0A=255;
    	}
    	
    	OCR0A=min(255,percounter,sigcount_3,sigcount_4,sigcount_5,sigcount_6);	//smallest value that is GREATER THAN ZERO (see min() )
    	if((sigcount_3==0) && (sigcount_4==0) && (sigcount_5==0) && (sigcount_6==0)) /*release TWI Interrupt*/;
    }
    
    ISR(SIG_OVERFLOW0) {
    	if(auxcounter<39000) auxcounter++;
    	else {
    		auxcounter=0;
    		i++;
    		if(i>14) i=0;
    		sig_3=testarray[i];
    		sig_4=testarray[i];
    		sig_5=testarray[i];
    		sig_6=testarray[i];
    	}
    }
    
    int main(void) {
    	
    	DDRB	= 0xFF;
    	DDRD	= 0xFF;
    
    	TIMSK0	= (1<<OCIE0A)|(1<<TOIE0);			// Activate Overflow- and OutputCompare interrupts
    	TCCR0B	= (1<<CS01);						// Prescaler=8 --> 16 MHz/8 = 2 MHz --> 1 click = 0.5 µs
    	OCR0A	= 255;
    
    	sig_3=testarray[i];
    	sig_4=testarray[i];
    	sig_5=testarray[i];
    	sig_6=testarray[i];
    	sigcount_3=sig_3;
    	sigcount_4=sig_4;
    	sigcount_5=sig_5;
    	sigcount_6=sig_6;
    	
    	sei();
    
    	while(1) {
    
    	}
    
    	return 0;
    }
    Kann jemand helfen?

    Vielen Dank,

    Nils

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    21.05.2008
    Ort
    Oststeinbek
    Alter
    34
    Beiträge
    607
    Hab mir den Code zwar nicht richtig angeguckt, aber das problem hört sich sehr nach einem Variablenüberlauf an.
    Übrigens, wieso verwendest du keinen 16bit Timer? Vielleicht liegt das Problem dort.

    Gruß, Yaro

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Ganz sicher zu Problemen führt die Verwendung des volatile-Zeugs.

    Weiterlesen zB hier:

    http://www.rn-wissen.de/index.php/Fa...-atomarer_Code
    Disclaimer: none. Sue me.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress