logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega8][c]brak regulacji prędkości silnika DC przez PWM

Papillon11 04 Cze 2011 22:39 2657 10
REKLAMA
  • #1 9577309
    Papillon11
    Poziom 10  
    Witam, może Wy mi pomożecie. Mam mały problem odnośnie sterowania prędkością silnika DC przez PWM.

    Mikrokontroler to atmega8 podłączony przez mostek H do silnika DC.
    Chcę w prosty sposób zmienić mu prędkość przez wpisanie mu do rejestru OCR2 odpowiednich wartości co się równa z odpowiednim wypełnieniem sygnału. Silnik po podłączeniu zasilania i nadania mu kierunku obrotów rusza i się obraca z najprawdopodobniej maksymalną prędkością a na jej zmiany nie reaguje. PWM działa bo jak podepnę pod tego pina diodę to miga. Podobny program napisałem w asemblerze i wszystko chodziło więc podejrzewam że jakiś błąd w programie robię a program przecież banalny.

    Proszę o pomoc:|
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    ISR (TIMER2_COMP_vect)						
    {
    	PORTB ^=_BV(0);
    }
    ISR (BADISR_vect){}
    
    
    int main()
    { 
    	DDRB |= 0xff;		//11111111		
    	PORTB |=_BV(0);		//00000000	Pin dla sygnału PWM
    
    	DDRD = 0x06;		//00000110	Ustawienia dla przycisków do sterowania
    	PORTD = 0xf9;		//11111001
    	
    	int p1,p2;
    	p1=0x32;	//50	impuls o czasie 3.2ms
    	p2=0x7d;	//125	impuls o czasie   8ms
    	
    	/*Licznik 2*/
    	
    	TCCR2 |= (1<<WGM21) |(1<<WGM21) |(1<<CS22) |(1<<CS20);	//Fast PWM, preskaler 128//
    																//Zegar 2MHz, czętotliwość 61Hz
    	TCNT2 = 0x00;		//00000000
    	
    	TIMSK |= (1<<OCIE2);
    	
    	
    	
    	sei();
    	
    	
    	for(;;)
    	{
    		
    		if(bit_is_clear(PIND,5))	//Zmiana prędkości
    		{
    			
    			OCR2 = p1;		
    		}
    		if(bit_is_clear(PIND,6))
    		{
    			OCR2 = p2;		
    		}
    		
    		if(bit_is_clear(PIND,0))	//Zmiana kierunków
    		{
    		PORTD |= _BV(1);
    		PORTD &= ~_BV(2);
    		}
    		if(bit_is_clear(PIND,3))
    		{
    		PORTD |= _BV(2);
    		PORTD &= ~_BV(1);
    		}
    			
    	
    	}
    	
    	return 0;
    	
    	}
  • REKLAMA
  • #2 9577398
    zumek
    Poziom 39  
    
    	/*Licznik 2*/
    	
    	TCCR2 |= (1<<WGM21) |(1<<WGM21) |(1<<CS22) |(1<<CS20);	//Fast PWM, preskaler 128//

    To jest CTC, a nie Fast PWM.

    Poza tym, na pinie PB0 Twój program będzie generował fale prostokątną o wypełnieniu 50/50, a zmiana wartości rejestru OCR2 i tak tego nie zmieni.
    Jeżeli możesz, wykorzystaj sprzętowy PWM na PB3/OC2.
  • REKLAMA
  • #3 9578627
    Papillon11
    Poziom 10  
    Witam
    Ustawiłem już poprawnie, na Fast PWM i wykorzystałem PB3/OC2 ustawiając w TCCR2 COM21 na logiczną jedynkę oraz pin jako wyjściowy i nic się nie działo. Podłączyłem do diody to się ledwie co paliła a po ustawieniu dodatkowo COM20 na 1, silnik się obracał i miałem na pinie stan wysoki no i według mnie prawidłowo, według tego co datasheetcie napisano ale tylko to że niema przebiegu PWM.
    O co tu chodzi?
  • REKLAMA
  • #5 9578679
    zumek
    Poziom 39  
    Papillon11 napisał:
    ... Podłączyłem do diody to się ledwie co paliła...

    To właśnie dlatego, że na OC2 jest generowany przebieg PWM.
    ...
    Pokaż kod po modyfikacjach.
  • #6 9578878
    Papillon11
    Poziom 10  
    Oscyloskopu nie mam ale to co dondu podesłał to pewnie fajna rzecz, poczytam o tym.
    A zmieniony kod to:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    
    int main()
    { 
    	DDRB |= _BV(3);					
    
    	DDRD = 0x06;		//00000110	Ustawienia dla przycisków do sterowania
    	PORTD = 0xf9;		//11111001
    	
    	int p1,p2;
    	p1=0x32;			//50	impuls o czasie 3.2ms
    	p2=0x7d;			//125	impuls o czasie   8ms
    	
    						/*Licznik 2*/
    	
    	TCCR2 |= (1<<WGM20) |(1<<COM21) |(1<<WGM21) |(1<<CS22) |(1<<CS20);	//Fast PWM, preskaler 128//
    																			//Zegar 2MHz, czętotliwość 61Hz
    	TCNT2 = 0x00;		//00000000
    	
    	TIMSK |= (1<<OCIE2);
    	
    	
    	
    	sei();
    	
    	
    	for(;;)
    	{
    		
    		if(bit_is_clear(PIND,5))	//Zmiana prędkości
    		{
    			
    			OCR2 = p1;		
    		}
    		if(bit_is_clear(PIND,6))	
    		{
    			OCR2 = p2;		
    		}
    		
    		if(bit_is_clear(PIND,0))	//Zmiana kierunków
    		{
    		PORTD |= _BV(1);
    		PORTD &= ~_BV(2);
    		}
    		if(bit_is_clear(PIND,3))
    		{
    		PORTD |= _BV(2);
    		PORTD &= ~_BV(1);
    		}
    			
    	
    	}
    	
    	return 0;
    	
    	}
  • REKLAMA
  • #7 9578979
    GSM
    Poziom 25  
    Witam,

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Uruchamiasz obsługę przerwania, a brak jest wektora do którego mikrokontroler ma skoczyć, więc się zresetuje :roll:

    Pozdrawiam,
    GSM
  • #8 9579020
    Papillon11
    Poziom 10  
    Rozumiem że chodzi Ci o to?

    ISR (TIMER2_COMP_vect)
    {
    	..........
    }
    
    ISR (BADISR_vect){}


    Czyli ma to być również umieszczone w programie mimo że korzystam z OC2? Wcześniej to wykorzystałem gdy korzystałem ze zwykłego pinu i jak pisałem działało ale bez zmiany prędkości.
    Czyli umieścić to w programie ale czy wpisywać tam jakiś kod?
  • #9 9579030
    GSM
    Poziom 25  
    ... :roll:
    Nie, po prostu usuń linię kodu, którą cytowałem...

    Pozdrawiam,
    GSM
  • #10 9579193
    janbernat
    Poziom 38  
    Możesz też zostawić "pustą" obsługę przerwania.
    Prolog i epilog zostaną zrobione, flagi pokasowane i wszystko będzie działać.
    Tak robię gdy wiem że przerwanie będzie użyte ale jeszcze nie mam kodu do obsługi.
  • #11 9579676
    Papillon11
    Poziom 10  
    Panowie temat zamknięty.
    Wykasowałem linie kodu którą polecał GSM i usunąwszy wektory do których się odwoływał uC jest możliwa zmiana prędkości.
    Dziękuję wszystkim.
REKLAMA