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

[c][atmega8] Sterownik silnika krokowego pod EMC2

17 Wrz 2010 19:08 3845 7
  • Poziom 12  
    Witam,
    Cały dzień męczę się z programem do uc na przerwaniach. Ponieważ jestem początkujący, narobiłem masę błędów. No ale...
    Na pinach 0,1,2,4 portu D są tranzystory w układzie darlingtona
    na int1 jest wejście step z EMC2
    a na pinc1 jest sygnał lewo , prawo.
    Niby wszystko się świeci, ale silnik się nie kręci. Steruję halfstepem.
    Code:

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

    volatile unsigned int flaga = 0;

    void Inicjalizacja(void)
    {
        sei();                            //Włączenie obsługi przewań   
       
    // INT1 - zbocze opadające, INT0 - brak
    MCUCR = _BV(ISC11);
    // załączenie przerwania od INT1
    GICR = _BV(INT1);
    }

    SIGNAL (SIG_INTERRUPT1)
    {
       flaga++;
    }

    int step(int i)
    {int krok[8]={0x01,0x05,0x04,0x06,0x02,0x12,0x10,0x11};
    if(i<0){i=7;}
    if(i>7){i=0;}
    PORTD=krok[i];

    return i;
    }



    int main( void )
    {
       Inicjalizacja();
       
    int i=0;
    /* Wszystkie linie portu D sa wyjsciami */
       DDRD = 0x17; 
    /* Wszystkie linie portu C sa wejściami */
       DDRC= 0x00;
       PORTC=0x00;

       while(1)
       {
    if(flaga==1)
    {if(!(PINC&0x02)){i--;step(i);}else{i++;step(i);}
    i=step(i);flaga=0;
    }
    PORTD=0;
    }

    }

    Prosiłbym o pomoc!
  • Poziom 30  
    Skoro ustawiasz cały port D jako wyjścia to nie dziwię się że nie działa int1 - pin D.3 .

    Sorki, nie zauważyłem że ddrd masz ustawiony właściwie, zasugerowałem się opisem.
  • Poziom 38  
    Chyba w C to się każdą bzdurę da skompilować.
    Uporządkuj ten kod i dodaj komentarze- co chcesz w danej linii dostać.
    I nawiasy.
    I schemat.
  • Poziom 28  
    syntetyczn dran napisał:

    Code:

    ...
       while(1)
       {
    if(flaga==1)
    {if(!(PINC&0x02)){i--;step(i);}else{i++;step(i);}
    i=step(i);flaga=0;
    }
    PORTD=0; // proponuję usunąć
    }
    ...


    Najpierw wewnątrz funkcji 'step()' ustawiasz PORTD, po czym zerujesz go w pętli 'while' w funkcji 'main'. Jak go ustawisz, to chyba tak powinien zostać do następnego impulsu (kroku).

    Poza tym niepotrzebne kombinacje z tym ograniczaniem wartości zmiennej 'i'.
    syntetyczn dran napisał:

    Code:

    int step(int i)
    {int krok[8]={0x01,0x05,0x04,0x06,0x02,0x12,0x10,0x11};
    if(i<0){i=7;} // proponuję usunąć
    if(i>7){i=0;} // proponuję usunąć
    PORTD=krok[i];

    return i; // proponuję usunąć i zmienić deklarację funkcji na 'void step(int i)'
    }


    Usuń zaznaczone linie z funkcji step(), a zamiast tego zrób np. tak w funkcji 'main':
    Code:

       while(1)
       {
          if(flaga==1)
          {
             if( !(PINC & 0x02) ) i--;
             else i++;
             i &= 0x07;
             step(i);
             flaga=0;
          }
       }


    No i zwróć uwagę na różnicę w formatowaniu kodu, o czym już napisał janbernat :), bo Twój kod jest mało czytelny.
  • Poziom 12  
    Dzięki za odzew. Z tym zerowaniem portu D to może być główna przyczyna błędu. Jutro z rana zajmę się schematem i uporządkowaniem wszystkiego(jakoś w winavr to wszystko wydawało się czytelniejsze).
  • Poziom 38  
    Sekwencja przy pracy półkrokowej powinna być chyba taka:
    100x0 0x10
    110x0 0x18
    010x0 0x8
    011x0 0xC
    001x0 0x4
    001x1 0x5
    000x1 0x1
    100x1 0x11
    gdzie x jest pinem przerwania- więc powinno być 0.
  • Poziom 28  
    janbernat napisał:

    Sekwencja przy pracy półkrokowej powinna być chyba taka:
    100x0 0x10
    110x0 0x18
    010x0 0x8
    011x0 0xC
    001x0 0x4
    001x1 0x5
    000x1 0x1
    100x1 0x11
    gdzie x jest pinem przerwania- więc powinno być 0.

    Pinem przerwania INT1 w ATmega8 jest PD3, a nie PD1.

    Autor użył kombinacji:
    Code:

    0bxxx0x001 = 0x01
    0bxxx0x101 = 0x05
    0bxxx0x100 = 0x04
    0bxxx0x110 = 0x06
    0bxxx0x010 = 0x02
    0bxxx1x010 = 0x12
    0bxxx1x000 = 0x10
    0bxxx1x001 = 0x11

    więc wydaje się, że wszystko OK, tylko jakby PD2 jest zamienione z PD1. Wszystko zależy od schematu. Zakładając, że schemat połączeń silnika jest odpowiedni do tego sterowania (tego nie wiemy), imho - powinno działać.
  • Poziom 12  
    Po usunięciu PORTD=0; wszystko zaczęło działać jak należy.

    Oto działający kod:
    Code:
    #include <avr/io.h>
    
    #include <avr/interrupt.h>

    volatile unsigned int flaga = 0;

    void Inicjalizacja(void)//inicjalizacha przerwań na porcie int1
    {
        sei();  //Włączenie obsługi przewań   
       
        // INT1 - zbocze opadające
        MCUCR = _BV(ISC11);
        // załączenie przerwania od INT1
        GICR = _BV(INT1);
    }

    SIGNAL (SIG_INTERRUPT1)//zwiększenie flagi o 1 przy wystąpieniu przerwania
    {
       flaga++;
    }

    //funkcja z zabezpieczeniami dla kroku, podająca wartości załączanych cewek
    int step(int i)
    {int krok[8]={0x01,0x05,0x04,0x06,0x02,0x12,0x10,0x11};
    if(i<0){i=7;}
    if(i>7){i=0;}
    PORTD=krok[i];

    return i;
    }



    int main( void )
    {
       Inicjalizacja();
       
    int i=0;
    /* Linie 0,1,2,4 portu D sa wyjsciami */
       DDRD = 0x17; 
    /* Wszystkie linie portu C sa wejściami */
       DDRC= 0x00;
       PORTC=0x00;

       while(1)
       {
    if(flaga==1)
    {
        if(!(PINC&0x02))
        {
            i--;step(i);
        }else{
            i++;step(i);
            }
    i=step(i);flaga=0;
    }
    }

    }