Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.
  • #1
    PioSz
    Level 12  
    Witam
    W prockach dopiero raczkuje.
    Robię obrotomierz do samochodu (choć można zastosować to wszedzie). Oparłem to na atmega16 bo taki akurat teraz mam, ale docelowo ma byc na 2312.Na razie jest wszystko w fazie testowej na biurku, ale założenia są takie: na kole zamachowym umieszczam siakiś czujnik, podaje to na układ formowania impulsu, z którego będę otrzymywał dodatnie impulsy,każda o czasie trwania 1ms(lub mniej bo procek i tak se to wychwyci).Impulsy testowe generuje sobie na innym procku, na przerwaniach, wiec są bardzo dokładne.
    Zasada pomiaru polega na pomiarze czasu między impulsami.Dla 60obr/min. koła zamachowego otrzymuje 1sek, dla 6000obr/min otrzymuje 0,01sek czyli 10ms.Program napisałem w przeklętym BASCOM'ie, ale widze, że trza powoli się przesiąść na asm i C.Ale póki co robię to w bascom'ie.Mam dwie wersje.W ver1 pomiar polega na tym, że impulsy są podawane na zew. przerwanie (wyzwalane zerem ale to szczegol), gdy wystapi przerwanie zatrzymuje sie timer1 zapamietuje stan licznika, zaruje timer, startuje od nowa, przeliczenie licznika na oborty ,licznik*czas 1 taktu timera (bascom robi to szczegolnie wolno) wyswietla obroty, wraca do petli glownej , i tak w kółko.WADA: odswierzanie wyniku zalezy od obrotów ,nie wiem czy on nadąża przeliczać obroty,powyzej 3000obr wyswietlanie się "kaszani", procek miedzy impulsami nic nie robi.Druga wersja:przenioslem wszystko do petli glownej programu i wykorzystalem polecenie BITWAIT.Tu tez wyswietlenie wyniku zalezy od obortow ale nie jest juz tak czeste i nic sie nie kaszani.Nie moge wykorzystac przrwania do wyswietlenia wyniku bo wtedy pojawiaja sie bledy w pomiarze czasu miedzy impulsami a wiec w obrotach.
    Gdyby nie zaokrąglenie do obrotycal(kowite), bo nie chce az tak dokładnie, to obrotomierz jest dokładny do 3 miejsca po przecinku.Ta wersja pracuje OK.
    Mile widziane jakieś sugestie ,uwagi porady.Dziękuję
    Ponizej listingi:
    ver1------------------------------------------------------------------------
    $crystal = 16000000                                         'atmega16-16
    Config Portd = &B1111010
           Portd = &B1111111
    
    Dim Licznik As Word
    'do tej zmniennej przypisuje stan licznika
    Dim Czas As Single
    'czas między impulsami,licznik*czas 1 taktu
    Dim Obroty As Single
    'przeliczony czas na obroty
    Dim Obrotycal As Integer
    'przeliczony czas na obroty
    
    Config Timer1 = Timer , Prescale = 256
    'czas taktu 16us
    
    Enable Interrupts
    Enable Int0
    On Int0 Measurement
    'wlaczenie obslugi przerwania int0
    'w razie przerwania skocz do podprogramu: pomiar
    
    Stop Timer1
    'zatrzymanie timera
    Cls
    
    '-----------petla glowna-------------
    Do
    
    Loop
    End
    '------------nudno tu---------------
    
    'podprogram pomiar
    Measurement:
    Stop Timer1
    'zatrzymanie timera
    Licznik = Timer1
    'przypisanie jego zawartosci do zmiennej licznik
    Timer1 = 0
    'zerowanie timera
    Start Timer1
    'start timera
    
    Czas = 0.000016 * Licznik
    Obroty = 60 / Czas
    Obrotycal = Obroty
    'oblicznia licznika na obroty
    
    Locate 1 , 10
    Lcd Obrotycal ; " obrtow"
    'wyswietlenie wyniku
    Return
    'procek wraca odpoczywac
    ver2------------------------------------------------------------------------
    $crystal = 16000000                                         ' atmega16-16
    Config Portd = &B1111010
           Portd = &B1111111
    
    Dim Pom As Integer
    'pomaga opóźnic wyswietlenie obr
    Dim Licznik As Word
    'do tej zmniennej przypisuje stan licznika
    Dim Czas As Single
    'czas między impulsami,licznik*czas 1 taktu
    Dim Obroty As Single
    'przeliczony czas na obroty
    Dim Obrotycal As Integer
    'przeliczony czas na obroty
    
    Config Timer1 = Timer , Prescale = 256
    'czas taktu 16us
    
    Stop Timer1
    
    Cls
    Pom = 0
    '--------------petla glowna--------------
    Do
    Timer1 = 0
    'zerowanie timera1
    Bitwait Pind.2 , Reset
    Start Timer1
    'oczekiwanie na impuls (tu akurat na "zero")
    'oraz start timer1
    Waitus 1200
    'chwila przerwy az impuls 1ms sie skocznczy
    Bitwait Pind.2 , Reset
    Stop Timer1
    'oczekiwanie na kolejny impuls
    'zatrzymanie timera
    
    Licznik = Timer1
    'przypisanie zawartosci timera do zmiennej licznik
    Czas = 0.000016 * Licznik
    'przeliczenie licznika na czas
    Obroty = 60 / Czas
    'przeliczenie czasu na oborty
    Obrotycal = Obroty
    'przeliczenie obrotow na wartosci calkowite
    
    If Pom = 10 Then
     Locate 1 , 10
     Lcd Obrotycal ; "    "
     Pom = 0
    End If
    Pom = Pom + 1
    ' ten warunek sprawia, ze wynik nie jest wyswietlany co 10ms tylko co 100ms
    Loop
    '------------------------------------
    End
  • #2
    szymtro
    Level 30  
    Zrób tak żeby w przerwaniu zatrzymywało tylko licznik i startowało go na nowo i zapisywało to do jakiejś zmiennej. Potem w pętli głównej robisz obliczanie obrotów na bierząco = cały czas. do tego można użyć jeszcze tajmer0 aby co jakiś czas odświerzyć wynik na jakimś wyswietlaczu. W ten sposób procek cały czas będzie coś robił. A swoją drogą to chyba coś skopałeś bo 2313 jest cho..e szybki - wstaw maksymalny kwarc jaki się da a do tajmera1 użyj presccalera.
    
    ...
    do
     pomoc_long=3750000\zmienna
     obroty=pomoc_long
    loop
    end
    
    Przerwanie:
     stop timer1
     zmienna=timer1
     timer1=0
     start timer1
    Return
    
    tajmer1_przerwanie:
     stop timer1
     timer1=&hffff
    return
    
    tajmer0_przerwanie:
     'i tu dajesz procedurke wyswietlenia zmiennej obroty na wyswietlaczu
    return
    
  • #3
    diag
    Level 29  
    Najprościej licz impulsy w określonej jednostce czasu, np w 0.1s 100 imp. to 6000obr/min.
  • #4
    szymtro
    Level 30  
    ups chyba się walnąłem. Jak zrobisz tak jak ci podałem to najmniejsza ilość obrotów to będzie 3750000\65535=57. A i znaczek dzielenia musi być taki:"\" - czyli dzielenie całkowite. Teoretycznie te 57 obrotów min wystarczy przy zwykłym silniku który i tak zapali dopiero przy ok 350RPM. Sposób z obliczaniem obrotów \w określonym czasie jest wystarczający do prostych przyrządów - aby uzyskać w nim określoną dokładność trzeba mierzyć w bardzo długim okresie czasu a czasami jest potrzeba żeby odswierzanie było na poziomie 12-15FPS bo wtedy oko ludzkie zdąży jeszcze zauważyć różnicę. Można jeszcze odpowiednio dopracować obliczenia tak aby rozdzielczość nie była lepsza niż 5RPM bo i przy nawet najnowszym silniku obroty skaczą ok +-20RPM więc trudno było by odczytać ostatnie dwie cyfry a tak powinno być dobrze - sprawdzone.
  • #5
    diag
    Level 29  
    Grunt to dokładność, więc proponuje dać jeszcze do procka kwarc ze stabilizacja temperatury i zamontować sobie w oku fotokomórkę by doczytać te cyferki przy 15FPS.
    I jak jedziesz to patrz cały czas na obrotomierz.
    A tak na marginesie , czemu producenci stosują zegary anlogowe?
  • #6
    PioSz
    Level 12  
    [...A swoją drogą to chyba coś skopałeś bo 2313 jest cho..e szybki - wstaw maksymalny kwarc jaki się da a do tajmera1 użyj presccalera...]

    no niby nic nie skopalem, algorytm jest dosc prosty, moze bascom cos namieszal, czort wie co on robi.wlasnie tez, mnie to dziwi zeby ten procek nie mogl sobie poradzic z kilkoma obliczeniami w czasie 10ms.taka wersje, z obliczeniami w peli glownej tez mam.

    [...Najprościej licz impulsy w określonej jednostce czasu, np w 0.1s 100 imp. to 6000obr/min...]
    dobre rozwiazanie ale niezbyt dokladne w miare zmniejszania obrotow.

    [...Grunt to dokładność,...A tak na marginesie , czemu producenci stosują zegary anlogowe?...]
    ...chce tego czasami uzywac do sprawdzania w innych autkach czy fabryczny obrotomierz nie przeklamuje, wiec musze miec dokladnosc +/-5 obr., analogowy lepiej sie odczytuje ale nie mam takowego w aucie i taki cyfrowy najprosciej mi jest zrobic, a dokladnosc docelowa w aucie chce co do 50obr. pomysle tez nad wysterowaniem obrotomierza wyciagnietego z innej deski bo mam takowy, z tego samego modelu auta (tez vw passat,rocznik tez ten sam) ale inny silnik bo beznynowy.skale wiec ma do 7000obr wiec nie korzystal by z calego.Jest w nim siliczek pradu stalego, z dwoma cewkami(nie jest to na pewno krokowy), nie mam regulowanego zasilacza ale jesli na jedna z cewek podam 5v to wychli mi sie na o/2500obr, jesli podam na druga to wychyli mi sie na o/4800obr.Wiec zostaje sprawa zamiany tych impulsow na proporcjonalny prad plynacy przez ten silniczek.Z PWM jeszcze nie korzystalem bo poewnie najlepiej to jest uzyc, i wysterowac jakiegos mosfeta tym.Dobrze bedzie?
    Dzieki.
  • #7
    mareks
    Level 12  
    [no niby nic nie skopalem, algorytm jest dosc prosty, moze bascom cos namieszal, czort wie co on robi.wlasnie tez, mnie to dziwi zeby ten procek nie mogl sobie poradzic z kilkoma obliczeniami w czasie 10ms.taka wersje, z obliczeniami w peli glownej tez mam.]

    Ile cykli zegara zabiera obliczenie obrotow ? Moze tutaj tkwi problem ?
  • #8
    szymtro
    Level 30  
    O już chyba wiem. Nie rób mnozenia przez liczbę z przecinkiem tylko dzielenie. Ty masz 0.000016*licznik i potem to dzielone przez 60. Ten sam wynik będzie jak dasz tak: 3750000\licznik i to samo masz w jednym równaniu bez używania przecinków(to w baskomie działa bardzo wolno) a dlaczego akurat tak? No bo broty(np 1000) = 16,67imp/sek=imp co 0,06 sek i teraz tak: kwarc 16000000 i prescale 256 = impuls co 0.000016 sek. iI teraz 0.06 /0.000016=3750 i jezeli dla tej wartości chcesz aby zmienna miała wartość 1000(niektórzy robią 100,10....) to 3750*1000=3750000. I teraz wystarczy w programie tą wartość(3750000) podzielić przez wartość licznika i masz od razu w obrotach na minutę. I w bascomie działa szybko.
  • #9
    PioSz
    Level 12  
    ...
    Czas = 0.0000256 * Licznik
    Obroty = 60 \ Czas
    Obrotycal = Obroty
    ...
    to zabiera 1792 cykle procka, (nie mylic z licznikiem timera).
    pzdr.
  • #10
    szymtro
    Level 30  
    A to:
    
       Pomoc_long = 112500 \ Licznik_do_obliczen                
       Obroty = Pomoc_long
    

    zabiera tylko 89 cykli więc zweryfikuj swój program. JA tu użyłem 112500 bo mam kwarc tylko 6Mhz a i tak wychodzi że jest szybszy niż u ciebie(2313)
  • #11
    BoskiDialer
    Level 34  
    a ja sie zastanawiam.. jak by odświeżanie zrobić 5FPS a żeby czas pomiaru trwał 2 sekundy można zastosować prosty stos FIFO z 10 zmiennych.
    przerwanie z czujnika by inkrementowało wszystkie 10 zmiennych,
    przerwanie z licznika odmieżającego 1/5 sekundy by kopiowało pierwszą zmienną stosu (stos_0) do rejestru roboczego, mnożenie przez 30 i wysłanie na LCD, potem przesówanie stosu typu:
    stos_0=stos_1;
    stos_1=stos_2;
    ..
    stos_9=0;
    i w ten sposób osiągnie się dziesięciokrotny zysk dokładności w stosunku do wyświetlania.
    [wada: wynik jest średnią z 2 sekund]

    dodatkowa metoda może być taka:
    jeśli czujnik jest skonstruowany z folii i zespołu fotodioda-fotorezystor na folii zamiast 1 przerwy mozna zastosować 30 przerw dzięki czemu jeszcze bardziej zwiększy sie dokładność, i w programie uniknie mnożenia przez 30.
  • #12
    Ryszardp
    Level 11  
    Jedna uwaga do konstruktora obrotomierza :D
    Kolego nie przesadź z dokładnością tego wskaznika, moim zdaniem wskazania na poziomie setek obrotów są wystarczające, ponieważ dziesiątki a tym bardziej jednostki obrotów silnika nie dadzą się odczytać przez ludzką percepcję. Kiedyś zrobiłem obrotomierz (w prawdzie na TTL-ach ale dzialał) i była do jedna gonitwa cyfr. Dopiero setki obrotów były jakieś spokojne i dające się odczytać. W związku z tym dodam swoje trzy grosze w kwesti programu obsługi procesora i moim zdaniem przerwanie zewnętrzne np. INT0 powinno być wyzwalane czujnikiem od koła zamachowego i z każdym obrotem powiekszać przechowywaną w jakiejś zmiennej ilość dokonanych obrotów. Natomiast przerwanie timera generowane w stałej jednostce czasu powinno wartość tę przepisywać i przeliczać do drugiej zmiennej, z której to głowny program mógły pobierać dane do wyświetlenia. No i oczywiście przerwanie timera powinno zerować ilość dotychczas zliczonych obrotów.