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

Obrotomierz w C na Atmega8 i wyświetlaczu LED

LashloE 08 Lis 2010 11:46 6263 21
  • #1 08 Lis 2010 11:46
    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.

    Code:


    #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ś?

    0 21
  • #2 08 Lis 2010 13:02
    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.

    Code:
    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ś :|

    0
  • #3 08 Lis 2010 14:53
    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.

    0
  • #5 08 Lis 2010 17:40
    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.

    0
  • #6 18 Lis 2010 16:46
    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ć?

    0
  • #8 26 Lis 2010 06:51
    emarcus
    Poziom 35  

    tombus napisał:
    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ć?


    Do zliczania impulsów w dobranej jednostce czasu nie musisz stosowac interruptu (przerwania) zewn. Możesz do tego użyc Timer/Counter0 lub1 a pozostały wolny timer lub Timer2 użyc do pomiaru czasu. W tej metodzie spotkasz się z relatywnie kiepska rozdzielczościa. Lepsze wyniki dla tak niskich obrotów daje druga metoda; - pomiar czasu pomiędzy impulsami i tu możesz posłużyc się interruptem i jednym timerem.
    Doradzałbym zrezygnować z kontaktronów do generowania impulsów. Może nieco droższe ale o wiele wygodniejsze jest użycie 'Hall effect switch' (switch nie sensor).
    Np. któryś z A3213/A3214 Allegro MicroSystems, Inc. , lub moze łatwiej do nabycia w Posce TLE4905 - Infinion. Zaletą ich jest czysty cyfrowy sygnał na wyjściu nie wymagający stosowania Debounce. Pracują one w różnym zakresie napięć a zapotrzebowanie mocy liczone jest w µW; co jest bardzo istotne przy zasilaniu systemu z baterii o napięciu niższym niz 5V. Innym rozwiązaniem równeż z wyjsciem cyfrowym może byc samochodowy sensor pozycji wału korbowego (Crank Shaft Position Sensor) lub sensor hamulców ABS. Te dwa nie wymagają magnesów (mają je wbudowane) reagują na obecnośc objektów w ogólności stalowych, lecz wymagają 5 Volt zasilania. Nie wspomne tu już o gotowych zamkniętych encoderach optycznych, ktorych ceny prawdopodobnie wybiegałyby daleko poza zakrers realnych potrzeb projektu.

    e marcus

    0
  • #9 26 Lis 2010 12:58
    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ą.

    0
  • #10 26 Lis 2010 13:35
    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.

    0
  • #11 26 Lis 2010 14:18
    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ł.

    0
  • #12 26 Lis 2010 15:20
    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?

    1
  • #13 15 Gru 2010 20:11
    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 :)

    0
  • #14 16 Gru 2010 20:35
    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.

    0
  • #15 16 Gru 2010 20:54
    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:

    Code:
    #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.

    0
  • #16 19 Gru 2010 18:10
    gromleon
    Poziom 32  

    A nie lepiej od razu wykorzystać alternator, "szukać" momentu przejścia napięcia na jednym z uzwojeń przez zero? Zliczanie impulsów w czasie jednej sekundy i potem przeliczanie to średni pomysł, dodasz gazu potem zwolnisz obroty a obrotomierz wskaże 2 tyś obr/min. Nie będzie to zbyt dynamiczny obrotomierz. Są na elektrodzie rozwiązania gotowe na wykorzystanie ADC procesora z wykorzystaniem przetwornika częstotliwość/napięcie i poszedł bym tym tropem Laszlo.

    0
  • #17 19 Gru 2010 18:24
    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

    0
  • #18 19 Gru 2010 18:31
    gromleon
    Poziom 32  

    E... mam zapłon w takim motocyklu na atmedze i działa, także to jest sprawdzone, nie przesadzajmy z tymi zakłóceniami.
    A tu sposób na obrotomierz, wg mnie najlepiej mierzyć napięcie z wykorzystaniem przetwornika F/U (sinusoida z alternatora) bądź pomiar czasu między impulsami, zliczanie impulsów w czasie jednej sekundy to zły pomysł nawet jak ten czas skrócisz.

    https://www.elektroda.pl/rtvforum/topic567488.html

    http://www.tme.eu/pl/katalog/przetworniki-ui-...5#id_category%3D100579%26id_producer%3D105%26

    0
  • #19 19 Gru 2010 18:55
    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ą.

    0
  • #20 19 Gru 2010 20:06
    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.

    0
  • #21 19 Gru 2010 20:23
    gromleon
    Poziom 32  

    Laszlo ale jesteś świadomy, że odświeżanie obrotów będziesz miał co sekundę, a jeśli nawet zmniejszysz ten czas to zmniejszy się rozdzielczość.
    Zresztą nie ma co pisać jak wykonasz to się przekonasz. Wykonaj sobie generator na ne555 i się przekonaj jak to będzie działać, nawet nie trzeba ci czujnika po prostu podaj na nogę timera sygnał z generatora (z regulacją) a jak nawet nie z generatora to na pewno posiadasz komputer z kartą muzyczną, ściągnij program jakiś generator i podaj przebieg na układ (tylko odpowiednio go dopasuj). Przy układzie z sieci będziesz miał stałą częstotliwość i kiepsko przetestowany układ.
    No poza krzakami na wyświetlaczu to to będzie wyglądać mniej wiecej tak ---> http://www.youtube.com/watch?v=yzuLyeRsvW0

    0
  • #22 20 Gru 2010 17:01
    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

    0
  Szukaj w 5mln produktów