Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Atmega8][C]Sterowanie silnikiem krokowym bipolarnym

25 Gru 2009 17:21 3428 1
  • Poziom 14  
    Witam , jestem początkującym elektronikiem jak i programistą dlatego proszę o wyrozumiałość.
    Schemat elektroniczny już mi ktoś sprawdził i powinien być dobrze ale w skrócie to chcę sterować za pomocą Atmegi8 poprzez układ L293 silnikiem krokowym dwufazowym bipolarnym.
    Wiem że ten listing nie jest poprawny, ale tyle udało mi się napisać i nie wiem co zrobić dalej (proszę o rady,wskazanie błędów), co teraz zrobić aby to zadziałało i proszę o wyrozumiałość (pisząc program wzorowałem się na jednym z kursów ale nie wszystko tam było)
    Pisane w języku C


    Code:
    /* sterowanie silnikiem bipolarnym "krokowy.c" */
    
    /* 2 przyciski przyłączone do portu D(PD0,PD1); 4 zaciski silnika do portu C(PC5,PC4,PC3,PC2); 4 diody led do portu B (PB0,PB1,PB2,PB3) */
    /* ATmega 1MHz */

    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>

    int main(void)
    {   
       /* 4 linie portu C będą wyjściami na L293NE (PC2,PC3,PC4,PC5) */
       DDRC = 0x3C;  /* 0x3C binarnie 000111100 */
       
        /* 2 linie portu D będą wejściami z podciągnięciem do VCC (PD0,PD1) */
        DDRD  = 0xFC;   /*11111100*/
       PORTD = 0x03;  /*00000011*/
       /* 4 linie portu B będą wyjściami na diody led (PB0,PB1,PB2,PB3)*/
       DDRB = 0x0F;  /*00001111*/
       PORTB = 0x0F; /*00001111*/
       
        /* Początek nieskończonej pętli */
        for(;;)
        {
            /* Przepisanie zawartości PIND do PORTC */
            PORTC = PIND;
          /* Przepisanie zawartości PIND do PORTB */
          PORTB = PIND;

     /* Początek nieskończonej pętli */
      while(1)
      {
        /* Jeśli pierwszy przycisk wciśnięty */
        if(!(PIND & 0x01)) PORTC = 0x14; /*00010100;(PC4,PC2);  I krok*/
       if(!(PIND & 0x01)) PORTB = 0x01; /*00000001;(PB0) pierwsza dioda led świeci*/
       _delay_ms(200);
       if(!(PIND & 0x01)) PORTC = 0x18; /*00011000;(PC4,PC3); II krok*/
       if(!(PIND & 0x01)) PORTB = 0x04; /*00000100;(PB2) trzecia dioda led świeci*/
       _delay_ms(200);
       if(!(PIND & 0x01)) PORTC = 0x28; /*00101000;(PC5,PC3);III krok*/
       if(!(PIND & 0x01)) PORTB = 0x04; /*00000100;(PB2) trzecia dioda led świeci*/
       _delay_ms(200);
       if(!(PIND & 0x01)) PORTC = 0x24; /*00100100;(PC5,PC2); IV krok*/
       if(!(PIND & 0x01)) PORTB = 0x08; /*00001000;(PB3) czwarta dioda led świeci*/
       _delay_ms(200);
     
        /* Jeśli drugi przycisk wciśnięty */
        if(!(PIND & 0x02)) PORTC = 0x24; /*IV krok*/
       if(!(PIND & 0x02)) PORTB = 0x08; /*00001000;(PB3) czwarta dioda led świeci*/
       _delay_ms(200);
       if(!(PIND & 0x02)) PORTC = 0x28; /*III krok*/
       if(!(PIND & 0x02)) PORTB = 0x04; /*00000100;(PB2) trzecia dioda led świeci*/
       _delay_ms(200);
       if(!(PIND & 0x02)) PORTC = 0x18; /*II krok*/
       if(!(PIND & 0x02)) PORTB = 0x04; /*00000100;(PB2) trzecia dioda led świeci*/
       _delay_ms(200);
       if(!(PIND & 0x02)) PORTC = 0x14; /*I krok*/
       if(!(PIND & 0x02)) PORTB = 0x01; /*00000001;(PB0) pierwsza dioda led świeci*/
       _delay_ms(200);

      }
    }
    }

    Program się kompiluje ale czy ma prawo działać ? Nie jestem pewny czy dobrze zrobiłem te pentle ?
    Wyskakuje mi jedynie : warning: "F_CPU" redefined
  • Poziom 17  
    Co do ostrzeżenia kompilatora, to stała F_CPU często ustalana jest w pliku makefile (a następnie przekazywana do kompilatora opcją -D). Korzystając z takiego rozwiązania proponuję ustawić jej wartość jedynie w pliku makefile i usunąć definicję z programu.

    Jeśli chodzi o program, to na pierwszy rzut oka widzę nieskończoną pętlę w nieskończonej pętli.

    Code:

    for(;;) {

      te_instrukcje;
      wykonają_się;
      tylko_raz;

      while(1) {

        z_tej_pętli;
        nigdy_nie_wyjdzie;   

      }
    }


    Domyślam się, że to wynik szukania problemów w kodzie.

    Drugi problem wygląda następująco:
    Czas wykonania pętli while wynosi 1,6s. W najgorszym przypadku od naciśnięcia przycisku do wystąpienia reakcji minie właśnie taki czas. Ponadto struktura pętli
    powoduje, że jeśli wszystko by zadziałało, to przez "połowę pętli" program powodował by obrót silnika a przez drugą "połowę pętli" hamował go.

    Sugeruję przepisać program w taki sposób
    Code:

    int main() {
      char licznik = 0;
      przygotuj_porty;
      while(1) {
        if(naciśnięto_przycisk_1) {
          //licz ... 1 2 3 0 1 2 3 0 1 2 ...
          if(licznik < 3) {
            licznik++;
          } else {
            licznik = 0;
          }
        }
        if(naciśnięto_przycisk_2) {
          //licz ... 2 1 0 3 2 1 0 3 2 1 ...
          if(licznik > 0) {
            licznik--;
          } else {
            licznik = 3;
          }
        }
       
        switch(licznik) {
          case 0: wykonaj_krok_0; break;
          case 1: wykonaj_krok_1; break;
          case 2: wykonaj_krok_2; break;
          case 3: wykonaj_krok_3; break;
        }
        _delay_ms(200);
      }
    }


    Jest też zapewne niezamierzone dwukrotne wysterowanie diody trzeciej (zamiast drugiej) w obu połowach pętli.


    Nie zauważyłem jednak żadnego problemu, który uniemożliwił by działanie układu o ile przycisk jest dostatecznie długo naciśnięty.

    Przydało by się więcej informacji.
    - Jak wygląda proces programowania, może układ nie programuje się poprawnie?
    - Czy po zaprogramowaniu układ cokolwiek robi (diody zapala na przykład)?
    - Jeśli układ się programuje ale nic się nie dzieje, proponuję zacząć od programu, który tylko zamiga diodą.