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

atmega32 i serwomechanizmy

MasioRs 03 Wrz 2009 21:30 2384 12
REKLAMA
  • #1 6977301
    MasioRs
    Poziom 2  
    witam
    mam pytanko bardzo ogólne- mianowicie buduje prototyp w którym musze wysterowac 25 serw z atmegi32 kwarc 16Mhz, używam pwm, ogólnie same problemy, i teraz moje pytanie: czy ktoś wie jaka jest maksymalna możliwa liczba wysterowanych serwomechanizmów tak aby w jednym cyklu (przemiatania wszystkich) każde z serw ustawiło się na inną pozycję przy takim systemie? tzn. czy to wogóle jest możliwe bo podobno czas reakcji/zadziałania pwm to ok.2,5us a odstępy na serwa muszą przychodzić co 20ms...;/czyli lekka kicha, ale mam program ktory steruje 16 serwami co w sumie przeczy temu i teraz nie wiem;/. Czu ustawienie 25 serw na atmega 32 w rozna pozycje w jednym rzucie jest wogole możliwe?

    pozdrawiam
  • REKLAMA
  • Pomocny post
    #2 6977385
    _Robak_
    Poziom 33  
    Niestety atmega 32 w latwy sposob wysterujesz 16 serw z rozdzielczoscia 16 bit. Nie potrzeba az tak duzej rodzielczosci, ale niestety 8 bit to malo. Ale juz przez atmege128 wysterujesz 6*8, czyli 48 serw z rodzialka 16 bit ;]
  • #3 6977409
    MasioRs
    Poziom 2  
    a teraz pytanie czy w takim razie muszę wymienić procka na atmege128?? czy np. mogę wysterować te 25 ale z mniejszą rozdzielczością np 4bit - bo nie potrzebuję płynnej regulacji obrotu co najwyżej 5 pozycji na 1 serwo max min i posrednie??
  • REKLAMA
  • #4 6977436
    _Robak_
    Poziom 33  
    Spokojnie wysterujesz 32 serwa z rozdzielczoscia 8 bit. Masz 3 liczniki w tym timer1 ma 2 kanaly, tylko musisz uwazac zeby OCR1A odmierzal zawsze wiecej niz OCR1B (albo na odwrot musisz sprawdzic :) )
  • #5 6977445
    MasioRs
    Poziom 2  
    dzieki:) dodałeś mi troche otuchy i wiary bo kurde srednio by było cały projekt od początku robić;/:P a obrona sie zbliża wielkimi krokami..pozdro
  • #6 6978617
    MasioRs
    Poziom 2  
    to teraz troche inaczej: atm32 ma 2 timery 8bit i jeden16bit... i 4 kanały pwm... ja potrzebuję 25 wyjść z niezależnym pwm'em...więc technicznie teoretycznie:

    jeden timer odpowiada za 50hz dla serwomechanizmów czyli powinien przemiatać wszystkie wyjścia znaczy włączać je co 20ms czyli powinien włączać kolejne co 0,8ms bo 0,8 x 25 daje 20ms czyli po przeleceniu wszystkich pojawia się znów na 1 wyjściu.

    no i teraz potrzebuje 25 niezależnych sygnałów o róznym wypełnieniu - ma już tylko 2 timery czyli jednym wysterowuje 12 a drugim 13 wyjść...??w trybie pwm oczywiście?

    jak to widzicie?
  • #8 6987167
    CaMIkaZEe
    Poziom 20  
    Zmodyfikowaliśmy program:

    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    //Prescaller jest ustawiony na 256 przy 16MHz
    //2.5ms - 0x3E
    //polozenie poczatkowe - 0x20 - 0d32 - 0.528ms
    //polozenie koncowe - 0x94 - 0d148 - 2.38ms
    unsigned char volatile p1[8] = {0x90,0x90,0x90,0x90,0x30,0x30,0x30,0x30};
    unsigned char volatile p2[8] = {0x90,0x90,0x90,0x90,0x30,0x30,0x30,0x30};
    unsigned char volatile p3[9] = {0x90,0x30,0x90,0x30,0x90,0x30,0x50,0x50,0x50};
    unsigned char volatile pin[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    
    int numer,i,dana;
    
    
    
    ISR(TIMER2_COMP_vect)
    {
       
       if (numer==9) numer=0;
       
       OCR0 = p3[numer];
       
       if (numer < 8)
       {
            OCR1AL = p1[numer];
    		OCR1BL = p2[numer];
    		
    		
    		PORTA = pin[numer];
    		PORTB = pin[numer];
    		PORTC = pin[numer];
       }
       else
       {
    		PORTD = 0x80;
       }
    
       TCCR1B|=_BV(CS12);
       TCCR0|=_BV(CS02);
    
       numer++;
    }
    
    
    ISR(TIMER1_COMPA_vect)
    {
       PORTA=0;
       
       TCCR1B=(0<<CS12);
       TCNT1L=0x00;
    }
    
    ISR(TIMER1_COMPB_vect)
    {
       PORTB=0;
    }
    
    ISR(TIMER0_COMP_vect)
    {
       if (numer < 8)
       PORTC=0;
       else
       PORTD=0;
       
       TCCR0=(0<<CS02);
       TCNT0=0x00;
    }
    
    void main( void )
    {
    //   Ustawienie UART
       UBRRL=25;
       UCSRC=_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0)|_BV(UPM1)|_BV(USBS);
       UCSRB=_BV(TXEN)|_BV(RXEN);   
    
    //   Ustawienie licznika 2   
       TCCR2=_BV(WGM21)|_BV(CS22)|_BV(CS21);
       OCR2= 0x9B;
       
    //   Ustawienie licznika 1
       TCCR1B=_BV(WGM12);
       OCR1AL=0x00;
       
    //   Ustawienie licznika 0
       TCCR0=_BV(WGM01);
       OCR0=0x00;
       
    //   Przerwania   
       TIMSK=_BV(OCIE0)|_BV(OCIE1A)|_BV(OCIE1B)|_BV(OCIE2);
       TIFR =_BV(OCF0)|_BV(OCF1A)|_BV(OCF1A)|_BV(OCF2);
       sei();
       
       DDRA = 0xFF;
       DDRB = 0xFF;
       DDRC = 0xFF;
       DDRD = 0x80;
    
       while(1)
       {
          
          for (i=0;i<16;i++)
          {
             while((_SFR_BYTE(UCSRA) & _BV(RXC))==0); //odbieranie z RS232
             //polozenie[i]=UDR;
                
    
          }
    
       
          for (i=0;i<16;i++)
          {
             while((_SFR_BYTE(UCSRA) & _BV(UDRE))==0); //wysylanie
              //UDR=polozenie[i];
             
          }   
       
       
       }
    
    
    } 
     


    Działa 25 serwomechanizmów. Ustawiają się w pozycje takie jak w tablicy p1, p2, p3. Niestety pin PA2, PA3 oraz PC7 szaleją. Czyli te dwa pierwsze "kręcą się" ostatni wybija na maksa. Nie do końca wiadomo dlaczego. Jeszcze jedna sprawa, jak najlepiej obsłużyć teraz transmisje po RSie?
  • REKLAMA
  • #9 6987629
    _Robak_
    Poziom 33  
    Przypominam ze jak korzystasz z kilka kanalow to z tego co pamietam OcnA musi byc wartoscia najwyzsza. Widze ze te warunki pokasowales
  • #10 6989207
    CaMIkaZEe
    Poziom 20  
    OK poprawione, jednak 3 wyjścia nadal wariują :(
  • #11 7029994
    CaMIkaZEe
    Poziom 20  
    Bieżący program wygląda następująco:

    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    unsigned char volatile p1[8] = {0x50,0x90,0x90,0x90,0x30,0x30,0x30,0x30};
    unsigned char volatile p2[8] = {0x90,0x90,0x90,0x90,0x30,0x30,0x30,0x30};
    unsigned char volatile p3[9] = {0x90,0x30,0x90,0x30,0x90,0x30,0x50,0x50,0x50};
    unsigned char volatile pin[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    
    int numer,pierwszy,i,dana;
    
    
    ISR(TIMER2_COMP_vect)
    {
       
       if (numer==9) numer=0;
       
       OCR0 = p3[numer];
       
       if (numer < 8)
       {
            if (p1[numer] > p2[numer])
    	    {
    			OCR1AL = p1[numer];
    			OCR1BL = p2[numer];
    			pierwszy = 1;
    	    }
    	    else   
    	    {
    			OCR1BL = p1[numer];
    			OCR1AL = p2[numer];
    			pierwszy = 2;
    	    } 		
    		
    		PORTA = pin[numer];
    		PORTB = pin[numer];
    		PORTC = pin[numer];
       }
       else
       {
    		PORTD = 0x80;
       }
    
       TCCR1B|=_BV(CS12);
       TCCR0|=_BV(CS02);
    
       numer++;
    }
    
    
    ISR(TIMER1_COMPA_vect)
    {
       if (pierwszy == 1)
          PORTA=0;
       else
       PORTB=0; 
       
       TCCR1B=(0<<CS12);
       TCNT1L=0x00;
    }
    
    ISR(TIMER1_COMPB_vect)
    {
       if (pierwszy == 1)
          PORTB=0;
       else
       PORTA=0; 
    }
    
    ISR(TIMER0_COMP_vect)
    {
       if (numer < 8)
       PORTC=0;
       else
       PORTD=0;
       
       TCCR0=(0<<CS02);
       TCNT0=0x00;
    }
    
    void USARTInit(uint16_t ubrr_value)
    {
       UBRRL = ubrr_value;
       UBRRH = (ubrr_value>>8);
    
       UCSRC=(1<<URSEL)|(3<<UCSZ0);
    
       UCSRB=(1<<RXEN)|(1<<TXEN);
    }
    
    char USARTReadChar()
    {
       while(!(UCSRA & (1<<RXC)))
       {
          //Do nothing
       }
       return UDR;
    }
    
    void USARTWriteChar(char data)
    {
       while(!(UCSRA & (1<<UDRE)))
       {
          //Do nothing
       }
       UDR=data;
    }
    
    
    
    
    void main( void )
    {
    //   Ustawienie UART
       USARTInit(51);
    
    //   Ustawienie licznika 2   
       TCCR2=_BV(WGM21)|_BV(CS22)|_BV(CS21);
       OCR2= 0x9B;
    
       
    //   Ustawienie licznika 1
       TCCR1B=_BV(WGM12);
       OCR1AL=0x00;
       
    //   Ustawienie licznika 0
       TCCR0=_BV(WGM01);
       OCR0=0x00;
       
    //   Przerwania   
       TIMSK=_BV(OCIE0)|_BV(OCIE1A)|_BV(OCIE1B)|_BV(OCIE2);
       TIFR =_BV(OCF0)|_BV(OCF1A)|_BV(OCF1A)|_BV(OCF2);
       sei();
       
       DDRA = 0xFF;
       DDRB = 0xFF;
       DDRC = 0xFF;
       DDRD = 0x80;
       
       flaga = 0;
    
       while(1)
       {      
    	  for (i=0;i<8;i++)
          {
             while((_SFR_BYTE(UCSRA) & _BV(RXC))==0); //odbieranie z RS232
             p1[i]=UDR;
    		 //p1[i]=USARTReadChar();
          } 
       }
    
    
    } 
    


    Serwomechanizmy działają jednak mam dwa problemy. Pierwszy - serwa z portu A piny 2 i 3 "drgają", działają chaotycznie. Drugie, że po odebraniu transmisji serwo ustawia się w wartość skrajną. Obojętnie co wysyłam. Transmisja po USB z użyciem układu FT232R. Program sterujący napisany w builderze. Ramka danych taka sama, prędkość też, aczkolwiek dane zczytywane z UDRa ustawiają błędnie serwomechanizmy.
  • #12 7030355
    _Robak_
    Poziom 33  
    Przetestuj sobie w symulatorze bo tak to ciezko cos wykminic ;) Wszystkie sie wychylaja na maksa czy jakies konkretne ? Druga sprawa... jesli serwa ci drgaja mozesz miec na nich za dlugi kabelek, badz slabe zrodlo zasilania. Ja sie meczylem z tym kupe czasu i wlasnie okazalo sie ze to wina kabelka.
  • REKLAMA
  • #13 7030537
    CaMIkaZEe
    Poziom 20  
    Z tymi drgającymi jest tak, że ten sam serwomechanizm zachowuje się poprawnie na pozostałych portach. Gdy wgrywam Twój program niezmodyfikowany jest to samo. Prosty program z bascoma działa dobrze. Wniosek, że programowo coś jest nie tak. Co do serw ustawianych z USB, to każde, którego ustawienia w tablicy są zmieniane wychylają się maksymalnie. Chciałem sprawdzić co jest odebrane poprzez zwrotne odesłanie, ale builder nic nie dostaje. W niektórych konfiguracjach zdarzało się, że ustawiało się dobrze, czasem serwo wybijało w daną pozycje i momentalnie powracało do poprzedniej. Myślałem, że może przebiegi czasowe timerów są zakłócane, bo po wielokrotnym wciskaniu buttona z wysłaniem ustawień, serwo przyjmuje pozycje losowe.
REKLAMA