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

Obrotomierz w C na Atmega8 i wyświetlaczu LED

LashloE 08 Lis 2010 11:46 7193 21
  • #1 8717186
    LashloE
    Poziom 13  
    Witam.
    Jestem początkującym programistą AVR ;)
    Grzebałem i szukałem "trochę" po forum ale nie znalazłem nic co by mi pomogło.
    Próbuje zbudować obrotomierz do motocykla na układzie Atmega8 który wynik wyświetla na panelu LED a nie jak większość projektów na LCD 2x16. Dodatkowo mam takie Ciśnienie by napisać program w języku C który dla mnie jest mniej czytelny i trudniejszy a większość obrotomierzy jakie wdziałem śmigają na Bascom'ie.
    Problem dotyczy mojej niewiedzy, nie wiem jak ustawić Timer by zliczał impulsy.
    Tu: http://www.portalnaukowy.republika.pl/obrotomierz_2.htm jest projekt obrotomierza na LCD i z wykorzystaniem Bascom'a, chciałbym właśnie tak ustawić Timer jak w tym projekcie tylko że w języku C.

    
    
    #include <avr/io.h>
    #define F_CPU 1000000
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    unsigned char liczba_LED[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
    
    volatile long licznik= 0;
    
    volatile uint8_t jeden, dwa, trzy, cztery;
    volatile int8_t wysw;
    
    
    
    ISR(TIMER1_COMPA_vect){
    
     switch (wysw)
        {
            case 0:
                PORTC =0x0;
                PORTC =0x8;
                PORTB = liczba_LED[jeden];
                wysw=1;
            break;
    
            case 1:
                PORTC =0x0;
                PORTC =0x4;
                PORTB = liczba_LED[dwa];
                wysw=2;
            break;
    
                    case 2:
                PORTC = 0x0;
                PORTC = 0x2;
                PORTB = liczba_LED[trzy];
                wysw=3;
            break;
    
                    case 3:
                PORTC = 0x0;
                PORTC = 0x1;
                PORTB = liczba_LED[cztery];
                wysw=0;
            break;
    
        }
    }
    
    ISR(INT0_vect){
            licznik++;
    }
    
    ISR(BADISR_vect){}
    
    int main(void){
    
            DDRC = 0xFF;
            DDRB = 0xFF;
    
            DDRD &= ~(1<<DDD2);
            PORTD |= _BV(PD2);
    
            MCUCR = _BV(ISC01);
            GICR |= (1<<INT0);
    
    
            TCCR1B |= (1 << WGM12); // Ustawia timer1 w tryb CTC
        OCR1A = 500; // Ustawia warto�� po��dan� na 100Hz dla preskalera 1
        TCCR1B |= (1 << CS10); // Ustawia timer z preskalerem Fcpu/1
        TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
        sei(); // Zezwolenie globalne na przerwania
    
    
    
            for(;;){
                    jeden = licznik / 1000; 
                    dwa = (licznik - jeden * 1000)/ 100; 
                    trzy = ((licznik - jeden * 1000) - dwa * 100) /10;
                    cztery = licznik % 10;
                    _delay_ms(50);
    
            }
       
    
            return 0;
    }
    


    Wyżej umieściłem swój program który został zlepiony z tego co znalazłem w sieci.
    Jeden timer już używam do wyświetlania liczb na wyświetlaczu, teraz chcę drugi skonfigurować na liczenie impulsów.
    Pomoże ktoś?
  • #2 8717398
    gaskoin
    Poziom 38  
    A zaglądałeś do DS ? Bo widzę, że niespecjalnie. Sygnał podpinasz pod nogę T0 a licznik konfigurujesz na zewnętrzny sygnał zegarowy.

    TCCR0 = (1 << CS02) | (1 << CS01);   // External clock source on T0 pin. Clock on falling edge.


    i teraz w TCNT0 masz liczbę impulsów.

    Odpalasz jeszcze jeden timer i co chwilę obliczasz prędkość za pomocą czasu jaki naliczy

    ----------------------------------

    Dopiero po przejrzeniu kodu zorientowałem się o co chodzi. W takim razie wystarczy go skonfigurować jedynie na liczenie czasu. Ale nie wiem z czym konkretnie masz problem, bo przecież 1 licznik odpaliłeś :|
  • #3 8717734
    LashloE
    Poziom 13  
    No bo widzisz, przeczytałem książkę a rozdział o timerach dwa razy i nic z niego nie rozumiem. Nie potrafię, skonfigurować, wystartować i zatrzymać oraz a jedyne przykłady w sieci odnośnie tego co mnie interesuje to tylko w Bascom.
    To co skonfigurowałem to przez przypadek mi się udało dzięki stronie wkretak.pl
    Właśnie ściągnąłem sobie PDF'a 80 stron o programowaniu w C dla AVR może po przeczytaniu tego coś więcej zrozumiem.

    Do tego programu chciałbym dodać coś co zliczy mi impulsy w ciągu 1s na jakimś pinie. Ale chyba dam sobie z tym spokój na jakiś czas.
    Przepraszam za ten szum.
  • #5 8718387
    sulfur
    Poziom 24  
    Podobny temat był ostatnio tylko dotyczył takiej zabawki do roweru. Z obliczeń wyszło, że pomiar impulsów na sekundę jest mało dokładny. Wypada liczyć ilość ms jednego obrotu. Przy motocyklu będzie tylko wyższa prędkość maksymalna.
  • #6 8759405
    tombus
    Poziom 15  
    Witam. Podepnę się pod temat.
    Kolega "sulfur" mógłby podać link do tematu?
    Chciałbym zliczyć ilość obrotów na minutę ( max 250 ). Są 2 wyjścia.
    - Jedno, to zliczanie impulsów przez zewnętrzne przerwanie oraz obróbka w programie na rpm.
    - Drugie to zliczanie czasu między impulsami przez timer oraz obróbka w programie.
    Impulsy będą generowane przez zwieranie kontaktronu oraz zastosowanie sprzętowej eliminacji drgań styków. Wynik będzie wyświetlany na LCD. Sprzęt to Atmega32. Jedne przerwanie zewnętrze już wykorzystuję w innych celach.
    Pytanie, który sposób wybrać?
  • #8 8790562
    Konto nie istnieje
    Poziom 1  
  • #9 8791374
    rpal
    Poziom 27  
    Jeśli to jest motocykl a nie motorower i jest to konstrukcja młodsza niż lata 80-te i w dodatku nie jest to twór z demoludów to na 100% masz tam kolego zapłon bezstykowy którego nadajnik impulsów w postaci magnesu znajduje się na kole zamachowym czyli wzudzeniu alternatora. Masz na 100 % zapłon bezstykowy więc z tamtąd możes sobie sygnał obrotów pobrać. Możesz tez użyć jednego z uzwojeń (3fazy) alternatora. Dodatko jeśli to silnik wysookobrotowy to machnij ręką na mierzenie odległości między impulsami tylko mierz ich ilość (czyli częstotliwość) bo i tak obroty maksymalne będzięsz miał w okoliy 12,14 tys obr/min a te użuteczne koło 6-8 tys/min. No chyba że wsadzasz obrotomierz do Harleya ale tam on już jest z pewnością:) I na samym początku pomyśl jak zrobić obudowę tak aby nie była jakimś tworem z kosmosu a co najważniejsze była szczelna i chroniła prze wodą i wilgocią.
  • #10 8791506
    tombus
    Poziom 15  
    Dzięki sulfur za linka. Rzecz cała będzie mierzyć (liczyć) kadencję rowerową. Kadencja rowerowa to ilość obrotów korby na minutę. Dzięki tej informacji można jeszcze bardziej sterować treningiem ;)
    Wszystkie liczniki rowerowe ( te tańsze i te kosztujące grubo ponad 900zł ) korzystają z kontaktronu, więc chyba nie ma sensu specjalnie podnosić koszta projektu.
    Program piszę w C. Poprzez takie układy uczę się tego języka.
  • #11 8791636
    rpal
    Poziom 27  
    tombus napisał:
    Dzięki sulfur za linka. Rzecz cała będzie mierzyć (liczyć) kadencję rowerową. Kadencja rowerowa to ilość obrotów korby na minutę. Dzięki tej informacji można jeszcze bardziej sterować treningiem ;)
    Wszystkie liczniki rowerowe ( te tańsze i te kosztujące grubo ponad 900zł ) korzystają z kontaktronu, więc chyba nie ma sensu specjalnie podnosić koszta projektu.
    Program piszę w C. Poprzez takie układy uczę się tego języka.

    jesteś w błedzie te liczniki np. za 50 PLN używają właśnie halotronu albo czujnika magnetorezystancyjnego. Kontaktronu przyznam że nigdy nie widziałem poza tym na wybojach słabo by się sprawdzał.
  • #12 8791834
    tombus
    Poziom 15  
    Hmm. Nie będziemy się teraz przekonywać do swoich racji, ale z doświadczenia wiem, że wszystkie przewodowe liczniki Sigmy (od 506, do 1606, nie wiem jak jest w DTSach i STSach), wszystkie ATECH, wszystkie wynalazki typu SHARK, przewodowe CATEYE mają kontaktrony.

    Co do sposobu pomiaru myślę, że najlepszy byłby pomiar czasu pomiędzy impulsami. Pytanie, czy przy tak niskich obrotach wynik będzie dokładny np. do 2 rpm?
  • #13 8873046
    LashloE
    Poziom 13  
    Witam, motocykl jest z 1987r ale to demolud :P
    Jako czujnik używam sensora hall'a, w silniku będą 2 takie sensory, bo ten motocykl to Jawa 350 a dalszym rozszerzeniem tego układu będzie bezstykowy układ zapłonowy DC/CDI.
    Tak więc motor ten osiągnie może 8k/obr na min. jak się go na pierwszym biegu bujnie z górki tak więc gigantycznych obrotów ten obrotomierz nie będzie mierzył a wydaje mi się ze użycie 2 czujników znacznie poprawi wskazywany wynik :)
  • #14 8877220
    rpal
    Poziom 27  
    moim zdaniem starczy spokojnie 1 czujnik, natomiast sugerowałbym zastanowić się nad miejscem zamontowania tego czujnika bo weź pod uwagę że koło zamachowe jest także wzbudzeniem prądnicy prądu zmiennego czy też alternatora (nie pamietam co ta Java tam ma) czyli czujniki hala mogą być mocno zakłocane przez wirujące pole magnetyczne, magnesów stałych zamontowanych na kole zamachowym.
  • #15 8877345
    LashloE
    Poziom 13  
    Witaj :) co do zakłóceń z alternatora to ja mam je zamiar wykorzystać.
    Wiadomo jest że takie sprzęty zakłócają pracę µC ale to przez cewki wysokiego napięcia, jeśli uda mi się uruchomić ten układ na standardowej instalacji zapłonowej i nie będzie "krzaków" to mam zamiar czujnik halla włożyć do alternatora i za pomocą wirnika który tam będzie się kręcił pobierać impulsy.
    Wiadomo że ten wirnik ma wiele biegunów, będę musiał sprawdzić ile impulsów obrotek dostanie na jeden obrót i odpowiednio go wyskalować.
    Jeszcze nie wiem czy siła pola magnetycznego wirnika wystarczy sensorowi hall'a ale jak nie spróbuję to się nie dowiem.

    Puki co mam już taki kod:
    #include <avr/io.h>
    #define F_CPU 1000000
    #include <util/delay.h>
    #include <avr/interrupt.h>
    /* funkcje */
    void intro(void); 				// funkcja pokazuj?ca intro po w??czeniu zasilania
    /* zmienne */
    unsigned char liczba_LED[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
    
    volatile long licznik = 0; 			//zmienna w której naliczane s? impulsy w ci?gu sekundy
    volatile long obroty = 0; 			//zmienna przechwuj?ca przeliczone obroty
    volatile uint8_t jeden, dwa, trzy, cztery; 	//zmienne przechowywuj?ce cyfry dla wy?wietlaczy LED
    volatile int8_t wysw; 				//zmienna przechowywuj?ca dane aktywnego wy?wietlacza LED
    
    
    //tu obs?ugujemy wy?wietlacz LED
    ISR(TIMER2_COMP_vect){
    
     switch (wysw)
        {
            case 0:
                PORTC =0x0;
                PORTC =0x8;
                PORTB = liczba_LED[jeden];
                wysw=1;
            break;
    
            case 1:
                PORTC =0x0;
                PORTC =0x4;
                PORTB = liczba_LED[dwa];
                wysw=2;
            break;
    		
    	case 2:
                PORTC = 0x0;
                PORTC = 0x2;
                PORTB = liczba_LED[trzy];
                wysw=3;
            break;
    
    	case 3:
                PORTC = 0x0;
                PORTC = 0x1;
                PORTB = liczba_LED[cztery];
                wysw=0;
            break;
    		
        }
    }
    
    //Gdy timer1 da przerwanie wyzeruje licznik
    ISR(TIMER1_COMPA_vect)
    {
        licznik=0;
    }
    
    //gdy na int0 pojawi si? impuls inkrementujemy licznik
    ISR(INT0_vect){
    	licznik++;
    }
    
    //gdy pojawi? si? inne przerwania to nic nie robimy (robimy nic)
    ISR(BADISR_vect){}
    
    int main(void){
    
    	DDRC = 0xFF;
    	DDRB = 0xFF;
    	
    	DDRD &= ~(1<<DDD2);
    	PORTD |= _BV(PD2);
    	
    	intro();
    	
    	MCUCR = _BV(ISC01);
    	GICR |= (1<<INT0);
    	
    	/* Timer wy?wiatlacza */
    	TCCR2 |= (1 << WGM12); 	 // Ustawia timer1 w tryb CTC
    	OCR2 = 250;		 // Ustawia warto?ci po??danej na 200Hz dla preskalera 1
    	TCCR2 |= (1 << CS10);	 // Ustawia timer z preskalerem Fcpu/1
    	TIMSK |= (1 << OCIE2);	 // Zezwolenie na przerwania dla CTC
    	
    	/*timer licznika */
    	TCCR1B |= (1 << WGM12); 		// Ustawia timer w tryb CTC
    	OCR1A = 15625; 				// Ustawia warto?? po??dan? na 1Hz dla preskalera 64
    	TCCR1B |= ((1 << CS10) | (1 << CS11)); 	// Ustawia timer z preskalerem Fcpu/64
    	TIMSK |= (1 << OCIE1A); 		// Zezwolenie na przerwania dla CTC
    	
    	
    	sei(); 		// Zezwolenie globalne na przerwania
    
    	for(;;){
    		//liczba impulsów w ci?gu 1s przerobiona na RPM
    		obroty = licznik * 60;
    		//rozdzielenie liczby na odpowie segmenty wy?wiatlacza
    		jeden = obroty / 1000; 
    		dwa = (obroty - jeden * 1000)/ 100; 
    		trzy = ((obroty - jeden * 1000) - dwa * 100) /10;
    		cztery = obroty % 10;
    		_delay_ms(50);
    
    	}
       
    	return 0;
    }
    
    void intro(void){
        PORTC =0x0;
        PORTC =0x8;
        PORTB = liczba_LED[0];
        _delay_ms(250);
        PORTC =0x0;
        PORTC =0x4;
        PORTB = liczba_LED[0];
        _delay_ms(250);
        PORTC = 0x0;
        PORTC = 0x2;
        PORTB = liczba_LED[0];
        _delay_ms(250);
        PORTC = 0x0;
        PORTC = 0x1;
        PORTB = liczba_LED[0];
        _delay_ms(250);
    }
    


    Nie sprawdzałem czy poprawnie to działa, jedynie machałem ręką z magnesem i wyświetlacz coś tam pokazuje, jutro zrobię elektro-megnes podłączę do sieci i zobaczę czy dobrze pokazuje, powinno pokazać jeśli się nie mylę 3000rpm.
  • #16 8888925
    Konto nie istnieje
    Poziom 1  
  • #17 8888993
    asembler
    Poziom 32  
    Nie uda ci sie odpalic w jawie gdzyz bez niezbedbych przeróbek procek sie bedzie wieszał nie tylko w motorze ale w odległosci 0.5m od niego:-) Sprawdzone.
    Do precyzyjnego pomiaru obrotów najlepiej wykorzystac wejscie ICP.
    Wyświetlacz LED w tym zstosowanie to poroniony pomysł.
    W dzien mało widoczne w nocy bez automatycznej regulacji oslepiające.
    Już lepiej skorzystac z jakiegos graficznego LCD z podswietleniem
  • #18 8889023
    Konto nie istnieje
    Poziom 1  
  • #19 8889144
    asembler
    Poziom 32  
    Nie mówie że sie nie da tylko zaznaczam problem który cesto występuje.
    Do mojego to nawet nie mogłem podejsć ze zwykłym multimetrem przed przeróbką.
  • #20 8889522
    LashloE
    Poziom 13  
    Gromleon takie układy to dla mnie komplikowanie układu, nie potrzeba mi jakiś przetworników, mam czujnik halla, w alternatorze jest elektromagnes, wszystko jest.
    A co do zakłóceń to pisałem już że jestem o nich baaardzo świadom.
  • #21 8889625
    Konto nie istnieje
    Poziom 1  
  • #22 8892583
    LashloE
    Poziom 13  
    Temat założyłem ponieważ nie wiedziałem jak się konfiguruje timery - w sumie do tej pory nie jestem biegły w tym temacie, ale jakoś udało mi się osiągnąć to co chciałem.
    Problemy dotyczące, sposobu pomiaru, odświeżania wyników nie są mi obce, jestem tych problemów świadom ale nie mam zamiaru tu gdybać o nich, wolę odpalić motor i kombinować w warsztacie. Mam kilka pomysłów jak się tych problemów pozbyć jak nie wypalą to będę tu szukał pomocy :P
    Puki co nikt nie doczepił się do kodu programu z którego jestem zadowolony a więc temat uważam za wyczerpany i można go zamknąć, dziękuję za pomoc :)
    P.S. uwielbiam AvP :D
REKLAMA