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

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

Smok79 18 Sie 2010 12:03 5535 29
REKLAMA
  • #1 8410810
    Smok79
    Poziom 10  
    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.

    
    
    #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;
    }
    
  • REKLAMA
  • Pomocny post
    #2 8411122
    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.

    
    // 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:
    
    // 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ść.
  • #3 8411229
    tmf
    VIP Zasłużony dla elektroda
    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.
  • #4 8411789
    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.
  • #5 8412189
    tmf
    VIP Zasłużony dla elektroda
    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.
  • REKLAMA
  • #6 8412285
    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ę.
  • #7 8412344
    janbernat
    Poziom 38  
    https://www.elektroda.pl/rtvforum/topic1123962.html
    To jest w Bascomie- ale bez żadnych Bascomowych sztuczek.
    Rejestry ustawiane "ręcznie"- więc nie powinno być kłopotu z przerobieniem na C.
    W zasadzie prawie goły sprzęt.
    Wykorzystałem to do sterowania silnika przez mostek za pomocą PWM.
    Sprawdzone- działało.
  • #8 8412422
    tmf
    VIP Zasłużony dla elektroda
    Andrzej__S - ale ja wcale nie czuję się urażony :) Tym bardziej, że z przerwaniami co 10us przy zegarze 1MHz masz całkowitą rację.
  • REKLAMA
  • #9 8414791
    Smok79
    Poziom 10  
    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?
  • #10 8414913
    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.
  • #11 8414953
    Smok79
    Poziom 10  
    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]
  • Pomocny post
    #12 8415151
    Andrzej__S
    Poziom 28  
    Możesz spróbować mniej więcej tak:
    
    // 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.
  • Pomocny post
    #13 8416445
    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.
  • #14 8418262
    Smok79
    Poziom 10  
    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:
    
        // jeżeli opadające - oblicz różnicę
       else 
         if (TCNT0>prev_tcnt) T = TCNT0 - prev_tcnt; 
         else
         T = prev_tcnt - TCNT0;
    
  • #15 8418351
    Andrzej__S
    Poziom 28  
    Cytat:

    PS: odnośnie obliczania Andrzej__S, dołożyłbym jeszcze sprawdzenie przekręcenia Timera:
    
        // 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.
  • REKLAMA
  • #16 8418519
    Smok79
    Poziom 10  
    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 :)
  • #17 8419497
    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.
  • #18 8420387
    Smok79
    Poziom 10  
    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.
  • #19 8445676
    Smok79
    Poziom 10  
    Witam ponownie. Pozwoliłem sobie zmienić temat bo już problemy rozwiązane (chyba) i chcę się z Wami podzielić tym co naskrobałem.

    
    // 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
  • #20 8445993
    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ć.
  • #21 8446315
    Smok79
    Poziom 10  
    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.
  • #22 8446354
    janbernat
    Poziom 38  
    Zastosowanie się znajdzie- albo nie- jak zobaczymy schemat mostka.
  • #23 8446426
    Smok79
    Poziom 10  
    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.

  • #24 8446430
    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ł:

    
    const uint8_t top_neu=45;
    


    To nie błąd, ale dobrą praktyką jest używać zamiast tego:
    
    #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ł:

    
       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ć ;)
  • #25 8446515
    Smok79
    Poziom 10  
    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...
  • #26 8446553
    landy13
    Poziom 31  
    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
  • #27 8446564
    Smok79
    Poziom 10  
    Nano herce :) czemu nie... zwykła literówka - na następny raz napiszę mhz i też nie będzie wiadomo o co chodzi ;) pozdrawiam
  • #28 8446610
    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ć.
  • #29 8447469
    Smok79
    Poziom 10  
    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.
  • #30 8447645
    Smok79
    Poziom 10  
    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.
REKLAMA