Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATTiny25/45/85][C] Modelarski regulator dwukierunkowy light

Smok79 18 Sie 2010 12:03 4905 29
  • #1 18 Sie 2010 12:03
    Smok79
    Poziom 9  

    Witam.

    Przymierzam się do budowy regulatora modelarskiego i mam problem ze zliczaniem długości trwania impulsu.

    Impuls trwa zazwyczaj od 1ms do 2ms w stanie wysokim (wyzwalany przerwaniem INT0)

    FCPU = 1 MHz (8MHz z preskalerem 8 (bit 7 ustawiony))

    Licząc, że jeden impuls trwa dokładnie 1 us i przy timerze zliczającym do 10 (startuje od 246 - Timer0) to po przekręceniu się timera uzyskujemy czas 10us. Przy długości impulsów w podanym zakresie timer powinien się przekręcić od 100 do 200 razy. Niestety program zlicza mi od 12 do 24 przekręceń tylko.

    Gdzie robię błąd ???

    Pozdrawiam. Smok.

    Code:


    #include <avr/io.h>
    #include <util/delay.h>   
    #include <avr/interrupt.h>

    #define    TSC   246      // stała czasowa timera

    volatile int x;
    volatile int czas;

    // funkcja opóźniająca
    void czekaj(int i){
       while(i>0){
          _delay_ms(10);
          i--;
       }
    }

    //funkcja wyświetlająca cyfrę na wyświetlaczu
    wypisz (int a){
       switch (a){
          case 0:
             LCD_WriteText("0");break;
          case 1:
             LCD_WriteText("1");break;
          case 2:
             LCD_WriteText("2");break;
          case 3:
             LCD_WriteText("3");break;
          case 4:
             LCD_WriteText("4");break;
          case 5:
             LCD_WriteText("5");break;
          case 6:
             LCD_WriteText("6");break;
          case 7:
             LCD_WriteText("7");break;
          case 8:
             LCD_WriteText("8");break;
          case 9:
             LCD_WriteText("9");break;

       }

    }

    // funkcja wyświetlająca integera (0-9999) na wyświetlaczu
    drukuj(int a){
       int t0,t1,t2,t3;

          t0=a/1000;
          wypisz(t0);
          t1=(a/100)-(t0*10);




          wypisz(t1);
          t2=(a%100)/10;
          wypisz(t2);
          t3=a%10;
          wypisz(t3);

    }

    // obsługa przewania timera0
    SIGNAL (SIG_OVERFLOW0){
          TCNT0=TSC;            // zerowanie timera
          czas++;
    }

    // obsługa przerwania zewn. INT0
    SIGNAL (SIG_INTERRUPT0){   
          SREG=1<<7;            // zezwolenie na przerwania
          czas=0;               // zerowanie licznika czasu
          while(bit_is_set(PIND,2)){};   // czekaj aż sygnał INT0 ustanie
          x=czas;
    }

    int main(void)
    {   

       TIMSK=1<<TOIE0;         // zezwolenie na przerwania z timera 0
       TCCR0B=1;               // preskaler
       TCNT0=TSC;               // zerowanie timer1

       LCD_Initalize();
       LCD_Clear();
       czekaj(1);
       LCD_WriteText("    Smok 2010");
       czekaj(1);
       LCD_GoTo(0,1);   
       czekaj(1);
       DDRD=0x00;               // PORTD jako wejście
       PORTD=0x00;               // Bez podciągnięcia do plusa

       GIMSK=(1<<6);            // włączenie przerwania od INT0
       MCUCR=(1<<0 | 1<<1);      // zbocze narastające dla INT0

       sei();               // włączenie przerwań
       while(1){
       
          cli();            // wyłączenie przerwań na czas obsługi wyświetlacza

          LCD_GoTo(0,1);   
          drukuj(x);         // wypisanie ilości zliczonego czasu (impulsów)

          sei();            // włączenie przerwań
          czekaj(1);
       }

       return 0;
    }

    0 29
  • Megger
  • Pomocny post
    #2 18 Sie 2010 13:33
    Andrzej__S
    Poziom 28  

    Smok79 napisał:

    Licząc, że jeden impuls trwa dokładnie 1 us i przy timerze zliczającym do 10 (startuje od 246 - Timer0) to po przekręceniu się timera uzyskujemy czas 10us. Przy długości impulsów w podanym zakresie timer powinien się przekręcić od 100 do 200 razy. Niestety program zlicza mi od 12 do 24 przekręceń tylko.

    Gdzie robię błąd ???


    Nieprawidłowe obliczenia czasu. Nie da się w ten sposób uzyskać 10us. Minimalna ilość taktów zliczanych przez Timer musi być większa od ilości taktów potrzebnych na obsługę jego przerwania.

    Code:

    // obsługa przewania timera0
    SIGNAL (SIG_OVERFLOW0){
          TCNT0=TSC;            // zerowanie timera
          czas++;
    }


    Z grubsza licząc samo wejście w procedurę obsługi przerwania (4 takty) i odłożenie na stos SREG i użytych w obsłudze przerwania rejestrów (po 2 takty na rejestr) zajmie więcej czasu. Nie będę już liczył, ile faktycznie potrwa obsługa przerwania timera 0, ale na pewno kilkakrotnie więcej, niż założyłeś.

    Jeżeli nie potrzebujesz 16-bitowego timera 1 do innych celów zrezygnuj z tych przerwań timera 0 i spróbuj raczej w ten sposób:
    Code:

    // obsługa przerwania zewn. INT0
    SIGNAL (SIG_INTERRUPT0){

    // do TCNT1 należy przypisać wartość początkową
    // równą ilości taktów potrzebnych na wejście w procedurę
    // obsługi przerwania + odłożenie na stos rejestrów + wprowadzenie
    // do TCNT1 nowej wartości
          TCNT1 = 12; // 12 to przykładowa wartość, należy obliczyć samodzielnie

          while(bit_is_set(PIND,2)){};   // czekaj aż sygnał INT0 ustanie

          x = TCNT1;
    }

    Otrzymasz w zmiennej 'x' ilość taktów zegara i jeśli znasz F_CPU to łatwo obliczysz czas.
    Można ewentualnie użyć timera 0 z preskalerem, co najwyżej zmniejszy to trochę dokładność.

    0
  • #3 18 Sie 2010 14:01
    tmf
    Moderator Mikrokontrolery Projektowanie

    Napisz lepiej co chcesz osiągnąć, bo mam wrażenie, że źle korzystasz z timera. No i zamiast tak kombinować z licznikiem timera masz przecież przerwanie compare match.

    0
  • #4 18 Sie 2010 16:28
    Andrzej__S
    Poziom 28  

    tmf napisał:

    No i zamiast tak kombinować z licznikiem timera masz przecież przerwanie compare match.

    Masz rację, że lepiej jest użyć przerwania "Compare Match", zamiast kombinować z wpisywaniem wartości początkowej licznika. Problem w tym, że kolega Smok79 planuje wywoływać przerwania co 10us taktując mikrokontroler zegarem 1MHz, czyli co 10 taktów zegara. Nie ma praktycznej możliwości, żeby jakakolwiek obsługa przerwania, która coś robi (np. inkrementuje jakąś zmienną), została wykonana w tak małej ilości taktów. Trzeba to rozwiązać inaczej lub zwiększyć częstotliwość taktowania.

    0
  • Megger
  • #5 18 Sie 2010 18:16
    tmf
    Moderator Mikrokontrolery Projektowanie

    ALe ja nie proponuje mu zostać przy absurdalnym pomyśle wywołania przerwania co 10us. Raczej, żeby wykorzystać compare match do wywołania zdarzenia wtedy kiedy potrzebuje jako alternatywę do liczenia czegoś przez inkrementację zmiennej. Albo zmianę całej filozofii sterowania, żeby wykorzystać hardware procesora, a nie robić programowo coś co procesor ma już wbudowane.

    0
  • #6 18 Sie 2010 18:42
    Andrzej__S
    Poziom 28  

    Sorry! Nie miałem zamiaru Cię urazić. Zresztą przecież napisałem, że masz rację. Ja tylko chciałem podkreślić fakt, że takie rozwiązanie nie zda egzaminu, niezależnie od tego, jakiego przerwania by nie użyć. Po prostu trzeba zmienić taktykę.

    0
  • Megger
  • #8 18 Sie 2010 19:16
    tmf
    Moderator Mikrokontrolery Projektowanie

    Andrzej__S - ale ja wcale nie czuję się urażony :) Tym bardziej, że z przerwaniami co 10us przy zegarze 1MHz masz całkowitą rację.

    0
  • #9 19 Sie 2010 11:35
    Smok79
    Poziom 9  

    janbernat - chcę uzyskać podobne urządzenie lecz oparte o ATTiny13. Stąd wykorzystanie tylko jednego timera, który będzie sterował modulacją PWM programowo a w wolnej chwili sprawdzał stan położenia (długości impulsu) serwa. Finalnie wszystko będzie chodzić na 9,6MHz lecz z uwagi na testy i podłączony wyświetlacz (i to bez linii RW) aktualnie jest 1MHz. Z tymi restrykcjami czasowymi to były moje przypuszczenia ale nawet gdy timer generuje przerwanie co 256 taktów to i tak liczba zliczonych impulsów jest o połowę mniejsza niż powinna być.

    Zrezygnuję również z generacji przerwania podczas przekręcenia timera i będę zliczał impulsy i zerował licznik Timera. Dzięki Andrzej __S :)

    Czasowo będzie:
    - 2-3ms na obsługę liczenia czasu impulsu
    - 10ms na pełen "takt" PWM co daje ~66Hz (przy założeniu 15ms na obsługę wszystkiego)

    W takim wypadku preskaler 64 (~ 6us) powinno mi dać wystarczającą dokładność.

    Pokierujcie mnie tylko czy mój tok myślenia i droga jest słuszna. Regulator ma być mały i bez wodotrysków do małych modeli pływających.

    PS: janbernat - podzielisz się schematem bo wydaje się być interesujący?

    1
  • #10 19 Sie 2010 12:12
    Andrzej__S
    Poziom 28  

    Trochę się pogubiłem. W temacie masz ATtiny2313, a w ostatnim poście piszesz o ATtiny13.:?:

    Smok79 napisał:

    - 10ms na pełen "takt" PWM co daje ~66Hz (przy założeniu 15ms na obsługę wszystkiego)


    Nie rozumiem trochę tego, że potrzebujesz czas na "takt" PWM. Przecież nawet ATtiny13 ma sprzętowy PWM. Potrzebujesz tylko kilkanaście taktów, żeby wpisywać odpowiednią wartość do OCR0A lub OCR0B, w zależności od tego, którego kanału będziesz używał. Resztę realizuje sprzęt.

    0
  • #11 19 Sie 2010 12:25
    Smok79
    Poziom 9  

    Cytat:

    Nie rozumiem trochę tego, że potrzebujesz czas na "takt" PWM. Przecież nawet ATtiny13 ma sprzętowy PWM. Potrzebujesz tylko kilkanaście taktów, żeby wpisywać odpowiednią wartość do OCR0A lub OCR0B, w zależności od tego, którego kanału będziesz używał. Resztę realizuje sprzęt.


    Finalnie będzie ATTiny13. Na ATTiny2313 przeprowadzam testy bo ATTiny13 mam SMD.

    Co do sprzętowego PWM to masz rację tylko, że ATTiny13 ma tylko jeden timer a nie mam pomysłu jak wykorzystać jeden timer do PWM i odliczania czasu trwania impulsu.

    W mikrokontrolerach jestem od bardzo niedawna. Jedyne poparcie to moje wykształcenie informatyczne (razem z ASM) i zaciętość w "budowaniu" sobie problemów :) [/quote]

    0
  • Pomocny post
    #12 19 Sie 2010 13:21
    Andrzej__S
    Poziom 28  

    Możesz spróbować mniej więcej tak:

    Code:

    // deklaracja zmiennych globalnych
    volatile uint8_t prev_tcnt, T;

    // w funkcji 'main'
    // skonfiguruj przerwanie INT0 tak, by reagowało na obydwa zbocza
       MCUCR |= (1<<ISC00);

    // używaj raczej makra ISR
    ISR(INT0_vect)
    {
    // sprawdzasz które zbocze wywołało przerwanie

        // jeżeli zbocze narastające, zapamiętaj stan licznika
       if(bit_is_set(PIND,2)) prev_tcnt = TCNT0;

        // jeżeli opadające - oblicz różnicę
       else T = TCNT0 - prev_tcnt;
    }


    W zmiennej 'T' otrzymasz ilość taktów timera odliczonych w czasie trwania stanu wysokiego, którą możesz wykorzystać w pętli głównej. Trzeba tylko zadbać, by impuls nie był na tyle długi, że timer odliczy w tym czasie więcej niż 256 taktów. Pomiar nie jest może zbyt dokładny, ale przy preskalerze 64 i tak nie będzie.

    W ten sposób nie manipulujesz zawartością timera, więc możesz spokojnie go użyć do generowania PWM.

    0
  • Pomocny post
    #13 19 Sie 2010 20:00
    janbernat
    Poziom 38  

    To i tak chyba się skończy obliczeniami możliwości sprzętu.
    Przy 9.6MHz wychodzi przy praskalerze=64 przerwanie od timera co 1.7 ms a skok timera co 6.7us.
    Silnik będzie napędzany przez PWM ok. 500Hz- będzie piszczał.
    Przy preskalerze=1 silnik pewnie wcale nie ruszy bo indukcyjność uzwojeń nie pozwoli na wystarczająco szybkie narastanie prądu.
    Przy 1024 silnik pewnie będzie chodził dobrze ale timer będzie miał skok co 0k. 0.1ms co zmniejszy nam rozdzielczość sprawdzania sygnału do 1/10- jak by nie kombinować.
    ATtiny25 ma dwa timery a kosztuje tyle samo co ATtiny13.
    ATtiny2313 jest niewiele większe w smd- ale to monstrum w porównaniu z tymi maluchami.
    No a tranzystory wykonawcze też coś zajmują- nawet półmostki smd.

    Cytat:

    PS: janbernat - podzielisz się schematem bo wydaje się być interesujący?

    Przepraszam- nie doczytałem do końca.
    Jak tylko znajdę płytkę i odtworzę.
    Schemat w zasadzie jest w moim temacie- jest tam podane skąd mostek ściągnąłem.

    0
  • #14 20 Sie 2010 10:48
    Smok79
    Poziom 9  

    Dzięki Panowie za odpowiedzi.

    Rzeczywiście po obliczeniach wychodzi kaszana z PWM lub z czasem do obliczania impulsu. Przejrzałem sobie notę większych ATTiny 25/45/85 i chyba któregoś z tych maluchów wykorzystam.

    Co do ATTiny2313 nie jest aż tak duży ale już mam projekt wykonany i maluchy ładnie się wpisały na płytce więc z nich skorzystam.

    Najważniejsze, że znów czegoś się nauczyłem :)

    PS: odnośnie obliczania Andrzej__S, dołożyłbym jeszcze sprawdzenie przekręcenia Timera:

    Code:

        // jeżeli opadające - oblicz różnicę
       else
         if (TCNT0>prev_tcnt) T = TCNT0 - prev_tcnt;
         else
         T = prev_tcnt - TCNT0;

    0
  • #15 20 Sie 2010 11:11
    Andrzej__S
    Poziom 28  

    Cytat:

    PS: odnośnie obliczania Andrzej__S, dołożyłbym jeszcze sprawdzenie przekręcenia Timera:
    Code:

        // jeżeli opadające - oblicz różnicę
       else
         if (TCNT0<prev_tcnt) T = TCNT0 - prev_tcnt;
         else
         T = prev_tcnt - TCNT0;


    Po pierwsze: w ten sposób otrzymasz błędny wynik. 'T = prev_tcnt - TCNT0;' odpowie na pytanie, ile brakuje licznikowi do osiągnięcia poprzedniego stanu, a nie ile taktów zostało zliczone od poprzedniego zapamiętania stanu.
    Po drugie: stosując zmienną typu 'unsigned char' nie trzeba się przejmować tym, że licznik się przepełnił (chyba, że przepełnił się dwukrotnie). Odejmowanie liczby większej od mniejszej wyjdzie prawidłowo, a otrzymaną w SREG flagę przeniesienia (C) po prostu ignorujesz. Arytmetyka zmiennych 'unsigned' jest trochę inna niż 'signed' i może to wydawać się trochę dziwne.
    Zresztą spróbuj sam, jaki będzie wynik odejmowania np. 3 - 250 przy zastosowaniu zmiennych 'unsigned char'. Wcale nie będzie to -247 (takiej liczby zresztą nie da się przedstawić za pomocą 'unsigned'). Wynikiem będzie 9, czyli 6 do przepełnienia + 3, i taki właśnie wynik przecież nas w tym przypadku interesuje.

    0
  • #16 20 Sie 2010 11:55
    Smok79
    Poziom 9  

    No racja, zapomniałem o 256 (256-prev_tcnt+TCNT0) ale to tak jest gdy człowiek śpi 2h po 16h w pracy.

    A co do tej arytmetyki to nie wiedziałem, że tak dziwnie to działa. Ale cóż, kolejna lekcja na przyszłość. Dzięki :)

    0
  • #17 20 Sie 2010 16:58
    janbernat
    Poziom 38  

    Kopia tego schematu:
    [ATTiny25/45/85][C] Modelarski regulator dwukierunkowy light
    Mosfety w postaci półmostka N-P SI4532, tranzystory smd BC847/857-kondensatorki i oporniki też smd i dzika plątanina kynaru na płytce prototypowej do smd.
    To daje coś koło 3.5A.
    Na płytce trzeba dać pole miedzi połączone z drenami.

    0
  • #18 20 Sie 2010 21:19
    Smok79
    Poziom 9  

    Dzięki janbernat. Schemat znalazłem ale jest zbyt rozbudowany. Zastosuję Mosfety Logic i 4 wyjścia z mikrokontrolera lub przerobię wszystko i skorzystam ze schematu do kitu AVT5011.

    Ogólnie dziękuję za pomoc :) Pozdrawiam.

    0
  • #19 27 Sie 2010 18:29
    Smok79
    Poziom 9  

    Witam ponownie. Pozwoliłem sobie zmienić temat bo już problemy rozwiązane (chyba) i chcę się z Wami podzielić tym co naskrobałem.

    Code:

    // Modelarski regulator dwukierunkowy by Smok

    #define F_CPU 8000000L            /* Częstotliwość kwarcu */

    #include <avr/io.h>
    #include <util/delay.h>   
    #include <avr/interrupt.h>

    #define k1 PB1            // definicja portu wyjścia dla kanału 1 (PWM kanał A)
    #define k2 PB4            // definicja portu wyjścia dla kanału 2 (PWM kanał B)
    #define wejscie   PB2   // definicja wejścia z aparatury (INT0)


    volatile uint8_t prev_tcnt, impulsy;
    volatile uint16_t pwm;
    volatile uint8_t start=0;               // zmienna zabezpieczająca

    const uint8_t top_neu=45;               // wartośc impulsów dla górnego neutrum (zmierzone)
    const uint8_t low_neu=41;               // wartośc impulsów dla dolnego neutrum (zmierzone)
    const uint8_t min_pwm=190;               // min wartość wypełnienia PWM (75%)

    const uint8_t min=35;                  // minimalna wartośc impulsów (zmierzone)
    const uint8_t max=60;                  // maksymalna wartość impulsów (zmierzone)

    /*
    Wzory do obliczeń wypełnienia proporcjonalnego do wychylenia drążka

    Kanał A - do przodu (2/3 suwu drążka)
    Kanał B - do tyłu (1/3 suwu drążka)

    OCR1A= (impulsy-(top_neu+1))*((255-min_PWM)/(max-(top_neu+1)))+min_pwm

    OCR1B= ((low_neu-1)-impulsy)*((255-min_pwm)/((low_neu-1)-min))+min_pwm
    */


    // obsługa przerwania od INT0
    ISR(INT0_vect){
       if(bit_is_set(PINB,2))   {         // jeżeli zbocze narastające zapisz wartośc timera
          prev_tcnt = TCNT0;
       } else   {                           // jeżeli opadające oblicz różnicę
          impulsy = TCNT0 - prev_tcnt;

          if ((impulsy<low_neu)||(impulsy>top_neu)){
             if(start==1){         // sprawdzamy czy po uruchomieniu drążek był w neutrum
                                  //(zabezpieczenie przed uruchomieniem silników podczas włączania)      
                if(impulsy>top_neu){
                   pwm= (impulsy-(top_neu+1))*((255-min_pwm)/(max-(top_neu+1)))+min_pwm;
                   if(pwm>255) pwm=255;
                   OCR1A=pwm;
                   OCR1B=0;         // zabezpieczenie przy odłączonym odbiorniku
                }else {
                   pwm= ((low_neu-1)-impulsy)*((255-min_pwm)/((low_neu-1)-min))+min_pwm;
                   if(pwm>255) pwm=255;
                   OCR1B=pwm;
                   OCR1A=0;         // zabezpieczenie przy odłączonym odbiorniku
                }
             }
          } else {
             OCR1A=0;
             OCR1B=0;
             start=1;
          }
       
       }

    }

    int main(void)
    {
       DDRB &= ~_BV(wejscie);         // ustawienie PB2 jako wejścia (INT0)
       PORTB &= !_BV(wejscie);         // PB2 bez podciągnięcia do plusa (INT0)
       MCUCR |= _BV(ISC00);            // zezwolenie na przerwania od INT0 reagujące na dowolne zbocze
       GIMSK   |= _BV(INT0);           // włączenie przerwania od INT0

       TCCR1|=_BV(COM1A0) | _BV(PWM1A) | _BV(CS13) | _BV(CS10);   
             // preskaler timera1 - właczenie PWM A
       
       GTCCR|=_BV(PWM1B) | _BV(COM1B0);               // włączenie PWM B
       TCCR0B = 0x04;         // preskaler Timera0   

       DDRB |= _BV(k1) | _BV(k2); // PD1 oraz PD4 jako wyjścia   
       OCR1A=0;
       OCR1B=0;

       sei();

       while(1) {}

       return 0;
    }


    Proszę o konstruktywne opinie. Zaznaczam, że mogą być błędy ale na pewno błędem nie jest mała dokładność pomiaru czasu impulsu (moja aparatura na drążku gazu ma grzechotkę 25 pozycyjną).

    Z moich "obliczeń" wynika, że przy 8MHz i preskalerze 256, PWM będzie działać z częstotliwością około 61 Hz. Chyba ;)

    Pozdrawiam. Smok

    0
  • #20 27 Sie 2010 19:57
    janbernat
    Poziom 38  

    Włączyć i sprawdzić.
    Dwa LED-y i dwa oporniki.
    A- jeszcze w tym procesorku jest Dead Time Generator- str.108.
    To może się przy uproszczonym mostku przydać.

    0
  • #21 27 Sie 2010 21:15
    Smok79
    Poziom 9  

    janbernat napisał:
    Włączyć i sprawdzić.
    Dwa LED-y i dwa oporniki.
    A- jeszcze w tym procesorku jest Dead Time Generator- str.108.
    To może się przy uproszczonym mostku przydać.


    Włączone i sprawdzone na płytce stykowej właśnie na dwóch ledach. I działa :)

    Co do DTG to oczywiście sprawdzę choć z tym się pierwszy raz spotykam. Po krótkiej analizie noty katalogowej nic nie rozumiem do końca (mój angielski jest niestety...). Żartuje oczywiście ale muszę się temu lepiej przyjrzeć bo na chwilę obecną nie znajduję zastosowania z uwagi, że obydwa DTG działają niezależnie.

    0
  • #22 27 Sie 2010 21:23
    janbernat
    Poziom 38  

    Zastosowanie się znajdzie- albo nie- jak zobaczymy schemat mostka.

    0
  • #23 27 Sie 2010 21:40
    Smok79
    Poziom 9  

    Proszę bardzo.

    [ATTiny25/45/85][C] Modelarski regulator dwukierunkowy light

    Uploaded from ImageShack.us

    Moderowany przez inventco.eu:

    inventco.eu - proszę zamieszczać obrazki zgodnie z zasadami elektrody. Poprawiłem.

    0
  • #24 27 Sie 2010 21:41
    Andrzej__S
    Poziom 28  

    Smok79 napisał:

    Proszę o konstruktywne opinie.

    Może to nie będzie zbyt konstruktywne, ale chciałbym zwrócić uwagę na pewne rzeczy.

    Smok79 napisał:

    Code:

    const uint8_t top_neu=45;


    To nie błąd, ale dobrą praktyką jest używać zamiast tego:
    Code:

    #define top_neu  45

    Dzięki temu oszczędzasz RAM i przyspieszasz program, bo nie trzeba ładować stałych z RAM do rejestru np. w celu porównania ze zmienną. Wiem, że masz tutaj wystarczający zapas RAM, to tylko uwaga ogólna, bo przy bardziej rozbudowanych programach może to być bardzo istotne.


    Smok79 napisał:

    Code:

       DDRB &= ~_BV(wejscie);         // ustawienie PB2 jako wejścia (INT0)
       PORTB &= !_BV(wejscie);         // PB2 bez podciągnięcia do plusa (INT0)


    To też nie błąd, ale wszystkie rejestry DDRx i PORTx mają wartości początkowe równe 0, więc nie trzeba ich zerować na początku programu.
    Na marginesie: w 'PORTB &= !_BV(wejscie);' masz niewłaściwy operator - zamiast '!' powinien być '~'. W tym wypadku to nic nie zmieni, ale trzeba na to uważać, bo to dwie różne negacje.

    Smok79 napisał:

    Z moich "obliczeń" wynika, że przy 8mHz i preskalerze 256, PWM będzie działać z częstotliwością około 61 Hz. Chyba ;)

    Z moich "obliczeń" wynika: (8000000/256)/256 to daje ~122Hz, ale mogę się mylić ;)

    0
  • #25 27 Sie 2010 21:56
    Smok79
    Poziom 9  

    Kurcze co do tego PWm myślałem, że mam Phase Correct PWM Mode a wtedy dzieli się poprzez 510 a nie 256.

    Co do negatora to oczywiście masz rację :| w "innych" miejscach miałem poprawione (podczas testów #define k1_off PORTB&=~_BV(k1) )

    #define ... kiedyś o tym pamiętałem...

    0
  • #26 27 Sie 2010 22:01
    landy13
    Poziom 28  

    Andrzej__S napisał:

    Smok79 napisał:

    Z moich "obliczeń" wynika, że przy 8mHz i preskalerze 256, PWM będzie działać z częstotliwością około 61 Hz. Chyba ;)

    Z moich "obliczeń" wynika: (8000000/256)/256 to daje ~122Hz, ale mogę się mylić ;)
    A z moich "obliczeń" wynika, że:
    8mHz(miliherców)/256/256= ~122nHz(nanoherce), ale mogę się mylić:D

    0
  • #27 27 Sie 2010 22:03
    Smok79
    Poziom 9  

    Nano herce :) czemu nie... zwykła literówka - na następny raz napiszę mhz i też nie będzie wiadomo o co chodzi ;) pozdrawiam

    0
  • #28 27 Sie 2010 22:11
    janbernat
    Poziom 38  

    Landy13 ma rację- te miliherce czasem drażnią.
    W mostku nie ma diod zabezpieczających ani gasików rc.
    Może się nieoczekiwanie spalić.

    0
  • #29 28 Sie 2010 09:53
    Smok79
    Poziom 9  

    Tranzystory mocy mają diody wewnątrz. A gasiki RC najczęściej i tak są montowane przy wyprowadzeniach bezpośrednio przy silniku. Jeśli to za mało to podpowiedz gdzie i jakiej wartości dać bo w tej materii nie jestem zbyt obeznany.

    0
  • #30 28 Sie 2010 10:56
    Smok79
    Poziom 9  

    janbernat napisał:
    http://www.danyk.wz.cz/mosfety2.png..
    Tam są gasiki.
    Oczywiście nie muszą w tym przypadku być na takie duże napięcia i moce.
    A diody w mosfetach są- ale wolne.
    Do zabezpieczeń stosuje się diody szybkie.
    Ale- Twój mostek i Twoje pieniądze.
    Zrobisz jak chcesz.


    Od dawna korzystam z regulatora ATV-5190 autorstwa pana Wiktora Lasa, i mimo braku jakichkolwiek gasików i diod zabezpieczających działa do dzisiaj. Sterował nawet 4 silniki szczotkowe po 7 A każdy.
    Mój mostek jest konstrukcją również zaczerpniętą z kolekcji AVT a mianowicie regulatora wiertarki modelarskiej "Dwukierunkowy regulator obrotów silników DC" - kit AVT-5011. Tam również nie ma gasików ani diod mimo sterowania silników szczotkowych.

    Na razie pozostanę przy tym mostku a jeśli się kiedykolwiek spali to będę kombinował :)

    Oczywiście dziękuję za pomoc.

    PS: przez przypadek nacisnęło mi się Ocena pod Twoim postem janbernat. Jeśli to coś złego to przepraszam.

    0
TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo