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

Atmega328p i L293D w AtmelStudio - brak reakcji PWM, tylko prawy silnik działa

kacperstibi 30 Mar 2024 11:03 348 10
  • #1 21025519
    kacperstibi
    Poziom 2  
    Cześć,
    Napisałem prosty program LineFollowera w AtmelStudio. Atmega 328p polaczona jest ze sterownikiem silnikow l293d. Połączenia na płytce są okej, napisałem podobny program w arduino IDE i wszystko działa. W AtmelStudio też wszystko działa oprócz PWMa... Kręci się tylko prawy silnik i nie reaguje wogóle na zmiane wartości PWMa. Do atmegi nie jest podpięty kwarc, działa na swoim 1MHz.

    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdbool.h>
    #include <avr/interrupt.h>
    
    #define leftMotorR PIND7
    #define leftMotorF PIND6
    #define leftMotorEn PIND5
    #define rightMotorF PINB1
    #define rightMotorR PINB0
    #define rightotorEn PINB2
    #define leftSensor PINC5
    #define rightSensor PINC3
    bool leftAlarm;
    bool rightAlarm;
    int8_t speed = 50;
    
    void FORWARD();
    void BACKWARD();
    void RIGHT();
    void LEFT();
    void STOP();
    
    int main(void)
    {
        
    	DDRB |= 00000111; //PB0 PB1 PB2
    	DDRC |= 00101000; //PC3 PC5
    	DDRD |= 11100000; //PD5 PD6 PD7
    	//PORTD |= (1 << PIND5);
    	//PORTB |= (1 << PINB2);
    	//PWM D5
    	TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
    	TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
    	TCNT0=0x00;
    	OCR0A=0x00;
    	OCR0B=0x00;
    	//PWM B2
    	TCCR1A |= (0<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
    	TCCR1B |= (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
    	TCNT1=0x00;
    	OCR1A=0x00;
    	OCR1B=0x00;
    	
        while (1) 
        {
    	  OCR0B = speed;
    	  OCR1B = speed;
    	  leftAlarm = bit_is_clear(PINC, leftSensor);
    	  rightAlarm = bit_is_clear(PINC, rightSensor);
    	  
    	  if(leftAlarm == 1 && rightAlarm == 0){
    		  RIGHT();
    	  }
    	  else if(leftAlarm == 0 && rightAlarm == 1){
    		  LEFT();
    	  }
    	  else if(leftAlarm == 1 && rightAlarm == 1){
    		  FORWARD();
    	  }
    	  else if(leftAlarm == 0 && rightAlarm == 0){
    		  STOP();
    	  }
    	  _delay_ms(1);
        }
    }
    
    void FORWARD(){
    	PORTD |= (1 << leftMotorF); //digitalWrite(leftMotorF,1);
    	PORTD &= ~(1 << leftMotorR);//digitalWrite(leftMotorR,0);
    	PORTB |= (1 << rightMotorF);//digitalWrite(rightMotorF,1);
    	PORTB &= ~(1 << rightMotorR);//digitalWrite(rightotorR,0);
    	_delay_ms(1);
    }
    
    void BACKWARD(){
    	PORTD &= ~(1 << leftMotorF);//digitalWrite(leftMotorF,0);
    	PORTD |= (1 << leftMotorR);//digitalWrite(leftMotorR,1);
    	PORTB &= ~(1 << rightMotorF);//digitalWrite(rightMotorF,0);
    	PORTB |= (1 << rightMotorR);//digitalWrite(rightotorR,1);
    	_delay_ms(1);
    }
    
    void RIGHT(){
    	PORTD |= (1 << leftMotorF);//digitalWrite(leftMotorF,1);
    	PORTD &= ~(1 << leftMotorR);//digitalWrite(leftMotorR,0);
    	PORTB &= ~(1 << rightMotorF);//digitalWrite(rightMotorF,0);
    	PORTB |= (1 << rightMotorR);//digitalWrite(rightotorR,1);
    	_delay_ms(1);
    }
    
    void LEFT(){
    	PORTD &= ~(1 << leftMotorF);//digitalWrite(leftMotorF,0);
    	PORTD |= (1 << leftMotorR);//digitalWrite(leftMotorR,1);
    	PORTB |= (1 << rightMotorF);//digitalWrite(rightMotorF,1);
    	PORTB &= ~(1 << rightMotorR);//digitalWrite(rightotorR,0);
    	_delay_ms(1);
    }
    
    void STOP(){
    	PORTD &= ~(1 << leftMotorF);//digitalWrite(leftMotorR,0);
    	PORTD &= ~(1 << leftMotorR);//digitalWrite(leftMotorR,0);
    	PORTB &= ~(1 << rightMotorF);//digitalWrite(rightMotorF,0);
    	PORTB &= ~(1 << rightMotorR);//digitalWrite(rightotorR,0);
    	_delay_ms(1);
    }
    
  • #2 21025554
    gps79
    Poziom 35  
    Co się rzuca w oczy, to konieczne zmiany:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

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

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

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

    Kod warto wklejać w klamry SYNTAX, bo ten, który jest w poście #1 jest niepoprawny i nie wiadomo, czy to wina programu, czy formatowania posta.
  • #3 21025560
    kacperstibi
    Poziom 2  
    Oczywiscie male litery - wina formatowania.
    Dzięki, juz poprawilem posta.
  • #4 21025568
    tmf
    VIP Zasłużony dla elektroda
    Ponieważ program jest prosty, więc najłatwiej opalić symulator w Atmel Studio (nie potrzebujesz hardwarowego debugera) i sobie prześledzić ten program krok po kroku, w poszukiwaniu stanu IO, który jest niezgodny z oczekiwaniami. W ten sposób najłatwiej wykrywa się głupie błędy związane z nieprawidłową konfiguracją jakiegoś układu peryferyjnego.
    BTW, zamiast takich wielokrotnych if...else lepiej użyć switch - kod jest czytelniejszy, potencjalnie kompilator ma też łatwiej z optymalizacją.
  • #5 21025663
    kacperstibi
    Poziom 2  
    Dzięki.
    Po przeanalizowaniu w symulatorze pierwsze co rzuciło się w oczy to że 7 bit z portu D nie zapisywał sie jako OUTPUT (jednak jak puszczam silniki na max, bez pwma to działa dobrze). Zmieniłem tylko na DDRD |= (1<<5)|(1<<6)|(1<<7); i już pokazywało okej.
    Z timerów niestety muszę się jeszcze chyba troche podszkolić bo nie za bardzo wiem jak to zinterpretować.
    Atmega328p i L293D w AtmelStudio - brak reakcji PWM, tylko prawy silnik działa
  • #6 21025726
    mpier
    Poziom 29  
    Witam,
    11100000 to jest jedenaście milionów sto tysięcy. Rozumiem, że zapis ósemkowy można przegapić (np. DDRB |= 00000111), ale tego dziesiętnego raczej się nie da. Chyba, że zakładasz że 10 + 1 == 3.
    Kolega wyżej poprawił..
    Pozdrawiam.
  • #7 21025849
    kacperstibi
    Poziom 2  
    mpier napisał:
    Witam,
    11100000 to jest jedenaście milionów sto tysięcy. Rozumiem, że zapis ósemkowy można przegapić (np. DDRB |= 00000111), ale tego dziesiętnego raczej się nie da. Chyba, że zakładasz że 10 + 1 == 3.
    Kolega wyżej poprawił..
    Pozdrawiam.


    Sam siebie poprawiłem, właśnie.
    Ale to i tak nie jest źródło problemu niestety.
  • #8 21026022
    mpier
    Poziom 29  
    Właśnie to jest źródłem problemu, a kod dalej jest błędny na górze. Co to powinno zrobić: "DDRC |= 00101000; //PC3 PC5"? Przypadkiem, na szczęście, nie robi to nic.
    Timer0 ma dwa kanały PWM.
  • #9 21026046
    kacperstibi
    Poziom 2  
    mpier napisał:
    Właśnie to jest źródłem problemu, a kod dalej jest błędny na górze. Co to powinno zrobić: "DDRC |= 00101000; //PC3 PC5"? Przypadkiem, na szczęście, nie robi to nic.
    Timer0 ma dwa kanały PWM.

    Zdaje sobie sprawę ze kod ma swoje bledy, ale jak zamiast pwma podaje wypełnienie 100% to wszystko działa. Zakładam więc że istota problemu tkwi w timerach a nie w reszcie kodu i to głównie chciałem skonsultować.
    Sam sobie odpowiedziałem w komentarzu poza tym i zmieniłem to na DDRD |= (1<<5)|(1<<6)|(1<<7);
  • #10 21026649
    mpier
    Poziom 29  
    W takim razie to problem polityczny.
    Pokaż aktualny kod i napisz czego od niego oczekujesz.
  • #11 21026658
    kacperstibi
    Poziom 2  
    mpier napisał:
    W takim razie to problem polityczny.
    Pokaż aktualny kod i napisz czego od niego oczekujesz.

    Problem był chyba w za małym prescalerze. Zwiększyłem go zmienijąc kod w ten sposób
    TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
    	TCCR0B=(0<<WGM02) | (1<<CS02) | (0<<CS01) | (0<<CS00);
    	TCNT0=0x00;
    	OCR0A=0x00;
    	OCR0B=0x00;
    	//PWM B2
    	TCCR1A |= (0<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
    	TCCR1B |= (1<<WGM12) | (1<<CS12) | (0<<CS11) | (0<<CS10);
    	TCNT1=0x00;
    	OCR1A=0x00;
    	OCR1B=0x00;
    

    Mam wrażenie że troche chodzi nierówno, ale działa, da się kontrolować PWMem prędkość obrotów.
REKLAMA