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

Ledowy obrotomierz do motocyklu - nie potrafię napisać kodu

zybi1306 02 Lip 2014 19:54 2949 31
  • #1 02 Lip 2014 19:54
    zybi1306
    Poziom 7  

    Witam, od paru dni męczy mnie myśl zrobienia ledowego obrotomierza do motocyklu. Nie wiem jak zacząć, szukając w sieci podobnych tematów natrafiam na same z wyświetlaczami. Chciałbym zrobić zliczanie impulsów w ciągu jednej sekundy, wynik miałby być zmienna według której główny program zapalałby odpowiednie diody. Pisałem proste programy do testowania silników krokowych, do migania diodami, lecz nie potrafię napisać kodu zliczającego ilość stanów wysokich na danym porcie:/ Pomoże ktoś zacząć? Dodam, że uczę się w sieci podstaw języka C, i uczę się 3 rok Elektroniki w szkole :) za pomoc z góry dziękuje:)

    0 29
  • Filament
  • #2 02 Lip 2014 20:02
    94075
    Użytkownik usunął konto  
  • #3 02 Lip 2014 20:31
    Brutus_gsm
    Poziom 25  

    Najprościej będzie wykorzystać timer jako licznik impulsów. Przestudiuj notę jakiegoś mikrokontrolera, a konkretnie rozdział o Timerach i trochę powinno ci się wyjaśnić.

    0
  • Filament
  • #4 02 Lip 2014 22:14
    zybi1306
    Poziom 7  

    Albert, brakuje wiedzy, nie znam zbytnio C poza prostymi komendami. Zrobię tak jak radzi Brutus poczytam o timerach:) ale puki co nie chciał by któryś z kolegów mi pomóc troszkę z tym kodem tu?:) Nie to nie z lenistwa tylko na gotowym przykładzie zapamiętuje wiedzę na dłużej niż po samym przeczytaniu:)

    0
  • #5 02 Lip 2014 22:16
    Brutus_gsm
    Poziom 25  

    Może warto na początek nauczyć się samej składni C, zamiast brnąć w konkretny projekt? Wypożycz/kup jakąś książkę do C, np. "Język ANSI C" i dopiero potem staraj się rozwiązać konkretne problemy. Bo teraz walczysz z dwoma żywiołami na raz, nie dość, że nie znasz składni, to jeszcze musisz rozwiązać problem zliczania impulsów.

    0
  • #6 02 Lip 2014 22:26
    zybi1306
    Poziom 7  

    Wiem wiem, to może starsi koledzy pokazali by mi jak rozwiązać ten problem z impulsami, będe bardzo wdzięczny:) bardzo zależy mi aby zrobić to w najbliższym czasie:) ewentualnie wkleili by zdjęcie kodu który można by zmodernizować pod mój projekt i pokazali co i jak? chciałem napisać to sam ale bez waszej pomocy widze że nie dam rady:/

    0
  • #7 02 Lip 2014 22:47
    94075
    Użytkownik usunął konto  
  • #8 02 Lip 2014 22:50
    el2010tmp
    Poziom 25  

    Zacznij pisać program i wklej tutaj na forum bo na razie to wygląda jakbyś czekał na gotowca :)

    0
  • #9 02 Lip 2014 22:57
    zybi1306
    Poziom 7  

    postaram się jutro wieczorkiem coś wrzucić:) O Timerach już czytałem, ale póki co wiem jak działają jako generatory a chciałbym mimo wszystko licznik:)

    0
  • #10 02 Lip 2014 22:58
    Brutus_gsm
    Poziom 25  

    Code:
    http://mikrokontrolery.blogspot.com/2011/04/obrotomierz-diy.html

    Całą resztę też możesz przejrzeć ;)

    0
  • #11 02 Lip 2014 23:04
    zybi1306
    Poziom 7  

    odwiedziłem ten link już wcześniej, nie mogłem sobie poradzić z "usunięciem" wyświetlacza:/ dobra poczytam, pokombinuje, nauczę się, spróbuje stworzyć i odezwę się w razie pytań a na tę chwile już dużo pomogliście:)
    :)

    czyli w tym kodzie wystarczy, że zrozumiem jak zamiast "wynik" zapalać odpowiednie sekwencje diodowe? nie mam pojęcia jak to ugryźć, póki co po usuwałem treści wyświetlacza:


    Cytat:
    /*

    OBROTOMIERZ v.1

    Obrotomierz przeznaczony do prostych pomiarów prędkości obrotowej.
    Pokazuje:
    - czas jednego obrotu,
    - liczbę obrotów na sekundę (rps),
    - liczbę obrotów na minutę (rpm).

    Autor: Dondu
    Data: 2012.11.25
    */


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


    //tutaj ustaw własne zasady pomiaru
    #define POMIAR_ILOSC_IMPULSOW_NA_OBROT 1 //ilość inpulsów na jeden obrót
    #define POMIAR_ILOSC_OBROTOW 10 //ile obrotów ma trwać pomiar


    volatile unsigned long int pomiar_ilosc_cykli;
    volatile unsigned int ilosc_przepelnien;
    volatile unsigned char pomiar_zbocze_nr;
    volatile unsigned char pomiar_gotowy;

    volatile unsigned int ICR1_moment_A;
    volatile unsigned int ICR1_moment_B;

    char wynik[16]; //bufor wyświetlacza

    //------------------------------------------------------

    ISR(TIMER1_CAPT_vect){

    //Obsługa zdarzenia na ICP1

    static unsigned int ICR1_aktualny; //wartość ICR1 złapana w aktualnie
    //złapanym zboczu

    //odczytaj złapany stan licznika
    ICR1_aktualny = ICR1;

    //czy to pierwsze złapane zbocze?
    if(pomiar_zbocze_nr == 1){

    //tak, pierwsze zbocze pomiarowe,

    //uruchamiamy zliczanie przepełnień Timer1

    //zgaś flagę przerwania od przepełnienia
    TIFR |= (1<<TOV1);

    //włącz przerwania od przepełnienia Timer1
    TIMSK |= (1<<TOIE1);

    //zeruj licznik przepełnień Timera1
    ilosc_przepelnien = 0;

    //zapamiętujemy stan licznika początku obrotu (moment A)
    ICR1_moment_A = ICR1_aktualny;

    }else{

    //każde następne zbocza pomiarowe

    //czy to ostatnie zbocze (koniec pełnego obrotu silnika)?
    if(pomiar_zbocze_nr == POMIAR_ILOSC_IMPULSOW_NA_OBROT
    * POMIAR_ILOSC_OBROTOW){

    //tak, wykryto ostatnie zbocze pomiarowe,
    //czyli wykonał się pełny ostatni obrót tarczy

    //wyłączamy przerwania z Input Capture Unit
    //oraz przepełnienia Timer1




    TIMSK &= ~( (1<<TICIE1) | (1<<TOIE1) );

    //zapamiętujemy zmienne dla main()
    ICR1_moment_B = ICR1_aktualny;
    pomiar_gotowy = 1;

    }

    //w pozostałych przypadkach nic nie robimy i czekamy na zliczanie
    //dalszych zboczy

    }

    //zwiększ licznik wykrytych zboczy
    pomiar_zbocze_nr++;

    }

    //------------------------------------------------------

    ISR(TIMER1_OVF_vect){

    //powiększ licznik przepełnień Timera1
    ilosc_przepelnien++;

    }

    //------------------------------------------------------


    void wykonaj_pomiar(void){

    //Funkcja włącza pomiar

    //zerujemy licznik przepełnień Timer0
    ilosc_przepelnien = 0;

    //ustawiamy nr pierwszego zbocza
    pomiar_zbocze_nr = 1;

    //zerujemy flagę gotowości pomiaru
    pomiar_gotowy = 0;

    //włącz przerwania z ICP1 Timer1
    TIMSK |= (1<<TICIE1);

    }


    //------------------------------------------------------

    int main(void){

    //zmienne do obliczeń
    double czas_jednego_obrotu;
    double obrotow_na_sekunde;

    PORTB |= (1<<PB0); //włącz pullup transoptora

    //Ustawienie Timer1
    TCCR1A = 0;
    TCCR1B = (1<<CS10); //preskaler 1, bez noise
    //canceler dla ICP1

    //lub z modułem Noise Canceler:
    //TCCR1B = (1<<CS10) | (1<<ICNC1); //preskaler 1, włącz
    //noise canceler dla ICP1

    sei(); //włącz przerwania globalne

    wykonaj_pomiar(); //włącz pierwszy pomiar

    //pętla główna
    while(1){

    if(pomiar_gotowy){

    // gdy pomiar został wykonany

    //obliczenia

    pomiar_ilosc_cykli = 65536 * ilosc_przepelnien - ICR1_moment_A
    + ICR1_moment_B;

    czas_jednego_obrotu = (double) pomiar_ilosc_cykli
    / POMIAR_ILOSC_OBROTOW / F_CPU ;

    obrotow_na_sekunde = 1.0 / czas_jednego_obrotu;

    //wyświetlenie wyników

    //obroty na minutę
    sprintf(wynik,"%7u ", (int) (60.0 * obrotow_na_sekunde));

    //pomiary co pół sekundy
    _delay_ms(500);

    //wykonaj następny pomiar
    wykonaj_pomiar();

    }
    }
    }



    czy wmiejscu wyświetlania wyników moge dać prosty warunek if? np:
    ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    if (obroty_na_minute < 500) {
    DDRB |= (1<<PB1)
    }

    else if (obroty_na_minute < 1000) {
    DDRB |= (1<<PB1)
    DDRB |= (1<<PB2)
    }

    else if (obroty_na_minute < 1500) {
    DDRB |= (1<<PB1)
    DDRB |= (1<<PB2)
    DDRB |= (1<<PB3)
    }
    ||||||||||||||||||||||||||||||||||||||||||||||

    czy coś takiego by dało radę? kombinuje jak umiem w razie błędów przepraszam:)

    0
  • #13 04 Lip 2014 16:02
    Brutus_gsm
    Poziom 25  

    Wstawiając kod na forum użyj tagu "syntax", bo teraz tego się nie da czytać niestety. Jeśli chodzi o warunek, to oczywiście, że możesz go dać - to od ciebie zależy jak sobie wszystko opracujesz.

    0
  • #14 04 Lip 2014 16:41
    atom1477
    Poziom 43  

    Ale jak już dajesz te ify to nie tylko zaświecaj diody ale i je gaś.
    Np.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    No i pamiętaj o średnikach.

    0
  • Pomocny post
    #15 05 Lip 2014 09:17
    el2010tmp
    Poziom 25  

    Rejestr DDRB służy do zmiany kierunku portu [wybór wejście/wyjście]. Do zmiany stanu portu służy rejestr PORTB:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Funkcja void wynik_na_LED(uint16_t obroty_na_minute) najpierw wygasza wszystkie diody, następnie zapala odpowiednią ich liczbę. Wybierz funkcję odpowiednia do sposobu podłączenia diod.

    Zapis 0bxxxxxxxx oznacza liczbę w kodzie binarnym.

    Zwróć uwagę na to że obroty_na_minute równe np.:2000 są większe zarówno od 1500 jak i od 1000 i 500.

    0
  • #16 07 Lip 2014 22:43
    zybi1306
    Poziom 7  

    Dochodzę do wniosku że to nie dla mnie.. Od dwóch dni próbuje zrozumieć jak kolega wyżej chciał żebym to zrobił. Wkleiłem to "bezmyślnie" nie wiem który kod obliczający obroty na minutę chodzi:/ nie potrafię wywołać funkcji wyświetlania wyników, także ten temat pozostanie pewnie otwarty dopóki tego na studiach nie zrozumie:) chyba że znajdzie się ktoś kto mi to uporządkuje?
    Przepraszam i dziękuje:)


    "efekt dwu dniowych prac" czyli nic...

    Kod: csharp
    Zaloguj się, aby zobaczyć kod

    0
  • #17 07 Lip 2014 23:41
    Brutus_gsm
    Poziom 25  

    Pisałem już wcześniej, że do takich zadań musisz znać chociażby podstawy języka C, a widać, że u ciebie one kuleją. Wstawienie tutaj gotowego rozwiązania nic Ci nie da, bo niczego się nie nauczysz. Zacznij naprawdę od nauki ANSI C, jego podstaw, funkcji itp. Potem takie przerobienie nie będzie dla ciebie problemem, bo na razie poruszasz się po omacku. Tego wszystkiego można dowiedzieć się z dowolnej książki lub kursu, których w internecie pełno...

    PS. Nie licz, że studia Cie czegoś nauczą, jeśli Ty sam tego nie zrobisz. Studia nie uczą, studia pomagają się nauczyć i można się obejść bez nich ;-)

    0
  • #18 08 Lip 2014 00:43
    zybi1306
    Poziom 7  

    Brutus, miałbyś chwilkę czasu żeby wprowadzić te zmiany? Trochę mi zależy na tym, a zanim się nauczę to to sporo czasu upłynie:)
    PS: myślisz, że "blue book" Mirosława Kardasia będzie dobry na początek?:)

    0
  • #19 08 Lip 2014 00:50
    Brutus_gsm
    Poziom 25  

    To zależy. Jeśli lubisz zbędne lanie wody i tłumaczenie "jak krowie na granicy", to tak, będzie dobra. Kilku moich znajomych ja sobie chwali, ja osobiście nie polecam. Jeśli lubisz natomiast konkrety, to kup książkę Tomasza Francuza. Zresztą jest o książkach wyczerpujący temat na elektrodzie.

    Poczytaj o funkcjach, ich definicjach, deklaracjach i sposobie używania a sam naprawisz ten kod w mgnieniu oka :-) Nie przyglądałem się szczegółowo ale chyba nie dużo brakuje do poprawnego działania.

    0
  • #20 08 Lip 2014 01:15
    zybi1306
    Poziom 7  

    Postaram się to zrobić sam:)

    0
  • #21 08 Lip 2014 17:37
    el2010tmp
    Poziom 25  

    Prawie dobrze.

    Definicja funkcji wynik_na_LED() czyli:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    musi być przed funkcją int main(void).
    W całym programie funkcja int main(void) może być tylko jedna [ta pierwsza].

    Poza tym zamień linię wyświetlającą wynik:
    zybi1306 napisał:
    sprintf(wynik,"%7u ", (int) (60.0 * obrotow_na_sekunde));

    na:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Inne linie z sprintf() usuń i tyle.

    Dobra książka była by dobrą inwestycją. Również polecam książki Tomasza Francuza.

    0
  • #22 08 Lip 2014 20:17
    atom1477
    Poziom 43  

    el2010tmp napisał:
    Definicja funkcji wynik_na_LED() czyli:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    musi być przed funkcją int main(void).

    To nie jest definicja, i wcale nie musi być przed main.

    0
  • #23 08 Lip 2014 20:30
    el2010tmp
    Poziom 25  

    atom1477 napisał:
    To nie jest definicja, i wcale nie musi być przed main.

    A co to jest, jeśli wolno spytać? :D

    Oczywiście może być za main(), jeśli przed main() znajdzie się deklaracja:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #24 08 Lip 2014 20:52
    atom1477
    Poziom 43  

    Pomyłka :D To jednak jest definicja.
    Ale właśnie dlatego nie musi być przed main (tak jak napisałeś, tam musi być tylko deklaracja).

    0
  • #25 09 Lip 2014 00:25
    zybi1306
    Poziom 7  

    Czyli końcowa wersja miała by wyglądać tak? :

    Kod: csharp
    Zaloguj się, aby zobaczyć kod


    sprint, to funkcja wyświetlania tak?
    i mam wykrzyknik przy int main(void):

    błąd z konsoli :

    " ../maina.c: In function 'main':
    ../maina.c:192: warning: 'main' is normally a non-static function
    Finished building: ../maina.c"



    PS: po ponownym uruchomieniu eclips'a nie ma błedu:)

    0
  • Pomocny post
    #26 09 Lip 2014 00:44
    Brutus_gsm
    Poziom 25  

    Masz dwie funkcje main, nie może tak być.

    0
  • #27 09 Lip 2014 00:57
    zybi1306
    Poziom 7  

    to jak sie jednego pozbyć?:)


    Kod: csharp
    Zaloguj się, aby zobaczyć kod


    tak jest źle?

    0
  • Pomocny post
    #28 09 Lip 2014 17:39
    el2010tmp
    Poziom 25  

    To jest niepotrzebne, pochodzi z drugiej funkcji:

    zybi1306 napisał:
    DDRB=0b11111111;//wszystkie bity ustawione na 1 czyli osiem wyjść


    Skasuj również to:
    zybi1306 napisał:
    uint16_t aktualne_obroty;

    wynik_na_LED(aktualne_obroty);// wywołanie funkcji wyświetlającej wynik
    // ...
    Ponieważ obr. na min liczysz bezpośrednio podczas wywołania wynik_na_LED((uint16_t) (60.0 * obrotow_na_sekunde));

    Ten zapis ustawia "1" na PB0
    zybi1306 napisał:
    PORTB|=(1<<PD0); //pierwsza dioda
    a z Twojego kodu wynika że jest tam transoptor:
    zybi1306 napisał:
    PORTB |= (1<<PB0); //włącz pullup transoptora
    Więc jak w końcu masz to podpięte?
    PB0 i PD0 to definicje określające po prostu zero 0. Istotna jest definicja PORTx [PORTB,PORTD,...] określająca gdzie to zero zostanie wpisane.

    0
  • #29 09 Lip 2014 20:43
    zybi1306
    Poziom 7  

    powinno być

    PORTD |= (1<<PD0); //pierwsza dioda

    bo na pb 1 jest czujnik:)

    PD to wyjścia na diody:)

    Dodano po 38 [minuty]:

    gra i trąbi:D tylko nie wygasza diod i jak zapalą sie więiksze od np 500. 100 i 1500 to sie już ciągle palą:) czyli brak wygaszania po if'ie?

    0
  • Pomocny post
    #30 09 Lip 2014 21:16
    el2010tmp
    Poziom 25  

    zybi1306 napisał:
    gra i trąbi:D tylko nie wygasza diod i jak zapalą sie więiksze od np 500. 100 i 1500 to sie już ciągle palą:) czyli brak wygaszania po if'ie?

    tzn.???
    Chciałeś żeby obrotomierz świecił tylko jedną diodą? W takim razie testuj w warunkach zakresy np.:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0