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.

Atmega8 - Chronometr- pomiar porędkosci

Pablo2015 27 Cze 2013 00:24 3573 21
  • #1 27 Cze 2013 00:24
    Pablo2015
    Poziom 18  

    Witam,
    Konstruuje sobie chronograf na Atmega8. Inspirowałem się tym- http://www.e-tawerna.pl/viewtopic.php?t=2099&postdays=0&postorder=asc&start=0..

    Schemat:

    Atmega8 - Chronometr- pomiar porędkosci

    Jednak że z programowaniem mam na pieńku to skleciłem takie coś... pomiar czasu przepisałem z książki i lekko zmodyfikowałem. Zależy mi na dokładności pomiarów.

    Program zamieszczam, nie chce się skompilować, nie bardzo ogarniam co mam źle, mile widziane sugestie itp.

    Założenia urządzenia:
    - pomiar prędkości średniej ( regulowany programowo odstęp między bramkami ),

    - pomiar prędkości chwilowej ( odstęp również regulowany programowo ),

    - pomiar napięcia zasiania i ostrzeżenie o wymianie baterii,

    - Regulowane podświetlenie.

    "Algorytm"

    1)Urządzenie się włącza i jeśli zasilanie jest za słabe to ostrzega o tym,
    2)Wybór trybu pracy- prędkość chwilowa czy średnia- po wyborze wpisujemy wartość droga, ostatnie ustawienia (wszystkiego) zapisywane do eeprom,
    3)Regulacja podświetlenia

    Proszę o propozycje zmian w kodzie, może inny pomiar czasu itp.

    Pozdrawiam Paweł


    Code:


    $regfile = "m8def.dat"
    $crystal = 16000000                                         'trzeba zmienić fusebity na 16MHz
     
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portd.7 , Db7 = Portb.0 , E = Portd.4 , Rs = Portd.3
    Cursor Off
     
    Config Adc = Single , Prescaler = Auto , Reference = Avcc   'konfiguracja wewnętrznego przetwornika A/c
    Start Adc                                                   'uruchomienie wewnętrznego przetwornika A/C
     
    Config Timer2 = Timer , Prescale = 64                       'timer0 do PWM dla wyświetlacza
    On Timer2 Pwm_lcd
    Timer2 = 0
    Enable Interrupts
    Enable Timer2
     
    Config Timer0 = Timer , Prescale = 1                        'zwiekszanie T/C2 co 16 us (64*0,24us)




    On Timer0 Czas_przejazdu_a
    Enable Interrupts
    Enable Timer0
     
     
     
    '********** Konfiguracja uC kontynuacja  ************
    '******************  Nazwy **************************
    '****************************************************
     
    Config Portc.4 = Output                                     'wyjście na podświetlenie LCD
    Reset Portc.4                                               'zakładam, że będzie tam tranzystor NPN
     
    Config Portc.0 = Input                                      'FOTOTRANZYSTOR 1
    Set Portc.0
    Config Portc.1 = Input                                      'FOTOTRANZYSTOR 2
    Set Portc.1
    Config Portc.2 = Input                                      'FOTOTRANZYSTOR 3
    Set Portc.2
    Config Portc.3 = Input                                      'FOTOTRANZYSTOR 4
    Set Portc.3
     
    Fototranzystor1a_poczatek Alias Pinc.0
    Fototranzystor2a_koniec Alias Pinc.1
    Fototranzystor3b_poczatek Alias Pinc.2
    Fototranzystor4b_koniec Alias Pinc.3
     
    Config Portd.0 = Input                                      'przycisk "+"
    Set Portd.0
    Config Portd.1 = Input                                      'przycisk "M"
    Set Portd.1
    Config Portd.2 = Input                                      'przycisk "-"
    Set Portd.2
     
    Plus Alias Pind.0
    M Alias Pind.1
    Minus Alias Pind.2
     
    Config Portb.1 = Output                                     'buzzer - tranz. NPN
    Set Portb.1
    Buzzer Alias Portb.1
                                                                  'Diody- tranz. NPN
    Config Portb.5 = Output
    Set Portc.5
    Config Portb.4 = Output
    Set Portb.4
     
    Led_a Alias Pinb.5
    Led_b Alias Pinb.4
     
     
     
     
    '*************  Nazwy Koniec  ****************
    '****************  Zmienne *******************
    '*********************************************
     
    Dim Menu As Byte
     
    Dim Czass_a As Double                                       'czas przekazdu
    Dim Czass_b As Double
     
     
    Dim Predkosc_a As Double
    Dim Predkosc_b As Double
     
    Dim Predkosc_ekran_a As Double
    Dim Predkosc_ekran_b As Double
     
    Dim Nap_adc As Word                                         'wartość odczytana z ADC
    Dim Napiecie As Single                                      'wartość napięcia do pokazania na ekranie
     
     
    Dim Dzies_tys_sek As Byte
    Dim Tys_sek As Byte
    Dim Setsek As Byte
    Dim Dziesek As Byte
    Dim Sekjed As Byte
    Dim Sekdzies As Byte
    Dim Sekset As Byte
    Dim Sektys As Byte
    Dim Licz As Byte
    Dim 10ms As Byte
     
    Dim Dzies_tys_sek_b As Byte
    Dim Tys_sek_b As Byte
    Dim Setsek_b As Byte
    Dim Dziesek_b As Byte
    Dim Sekjed_b As Byte
    Dim Sekdzies_b As Byte
    Dim Sekset_b As Byte
    Dim Sektys_b As Byte
    Dim Licz_b As Byte
    Dim 10ms_b As Byte
     
    Dim Pwm_lcd_licznik As Byte                                 'wewnętrzny licznik PWM-u
    Dim Pwm As Byte                                             'ustawiona wartość PWM dla podświetlenia lcd
    Dim Pwm_zaladowane As Byte                                  'wartość wypełnienia, które będzie faktycznie działała - przydatne przy funkcji StarLight
     
     
     
     
    '*************  Zmienne koniec  ****************
    '***************  podprogramy ******************
    '***********************************************
     
     
    Declare Sub Odczytnapiecia                                  'odczyt napięcia z ADC i konwersja na liczbę
    Declare Sub Konwert_zmienna_na_czas_a
    Declare Sub Konwert_zmienna_na_czas_b
    Declare Sub Przelicz_vsr
    Declare Sub Przelicz_vch
     
     
    '***********************************************
     
    'Pwm_zaladowane = Pwm                                        'zalanczam podswietlenie
     
    Menu = 1
    If M = 0 Then
    Incr Menu
    End If
    If Menu >= 4 Then Menu = 0
    End If
     
    Gosub Odczytnapiecia                                        'odczyt napięcia z ADC
     
     
    If Napiecie_ekran < 6 Then
    Locate 1 , 1
    Lcd "UWAGA!  Niski   "
    Locate 2 , 1
    Lcd " stan baterii ! "
     
    Wait 3
     
    Locate 1 , 1
    Lcd " Zmien baterie  "
    Locate 2 , 1
    Lcd "6 x bateria AAA "
     
     
    End If
     
     
    Locate 1 , 1                                                'pierwsza liczba to numer wiersza; druga - numer kolumny w której ustawia się kursor do pisania
    Lcd "     Witaj!     "
    Locate 2 , 1
    Lcd "                "
    End If
     
     
    Wait 3                                                      'czas wyświetlania napisu
     
    Locate 1 , 1                                                'pierwsza liczba to numer wiersza; druga - numer kolumny w której ustawia się kursor do pisania
    Lcd "  CHRONOMETR    "
    Locate 2 , 1
    Lcd "                "
    End If
     
    Wait 3
     
     
     
     
    '-----------------------------------------------------------------------------
    'obsługa przycisków
    '-----------------------------------------------------------------------------
     
    If Menu >= 1 And Plus = 0 Then
    Incr Menu
       If Menu >= 4 Then : Menu = 0 : End If                    'po przekręceniu się menu, wracamy do pulpitu
    End If
     
    If Menu >= 1 And Minus = 0 Then
    Decr Menu
       If Menu >= 4 Then : Menu = 6 : End If                    'po przekręceniu się menu, wracamy do pozycji ostatniej
    End If
     
     
    '-----------------------------------------------------------------------------
     
    '-----------------------------------------------------------------------------
    If Menu = 0 Then
     
    Do
                                      'odczyt napięcia z ADC i konwersja na liczbę
    Gosub Konwert_zmienna_na_czas_a
    Gosub Konwert_zmienna_na_czas_b
    Gosub Przelicz_vsr
    Gosub Przelicz_vch
     
     
     
    If Menu = 0 Then
     
     
    Locate 1 , 1
    Lcd "Pomiar predkosci"
    Locate 2 , 1
    Lcd "   sredniej     "
     
    Wait 3
     
    Locate 1 , 1
    Lcd "   Podaj droge  "
    Locate 2 , 1
    Lcd "                "
     
    Lcd "     DROGA      "
    Locate 2 , 1
    Lcd "" ; Droga_a ; "      centymetrow"
     
    If Plus = 0 Then
    Incr Droga_a
     
    End If
     
    If Minus = 0 Then
    Decr Droga_a
     
    End If
     
     
     
     
    If M = 0 Then
     
    Writeeeprom Droga_a , 2 : End If
     
    Locate 1 , 1
    Lcd "Predkosc:   Czas:"
    Locate 2 , 1
    Lcd "" ; Predkosc_ekran_a ; "km/h" ; Czass_a ; "s"
     
     
    End If
     
    '####################################################################################################
     
     
    If Menu = 2 Then
     
     
    Locate 1 , 1
    Lcd "Pomiar predkosci"
    Locate 2 , 1
    Lcd "   chwilowej    "
     
     
    Wait 3
     
    Locate 1 , 1
    Lcd "  Podaj odstep  "
    Locate 2 , 1
    Lcd "miedzy bramkami "
     
     
    If Plus = 0 Then
    Incr Droga_b
     
    End If
     
    If Minus = 0 Then
    Decr Droga_b
     
    Lcd "   ODSTEP       "
    Locate 2 , 1
    Lcd "" ; Droga_b ; "  centymetrow"
     
    End If
     
    If M = 0 Then
     
    Writeeeprom Droga_b , 2 : End If
     
    Locate 1 , 1
    Lcd "Predkosc:   Czas:"
    Locate 2 , 1
    Lcd "" ; Predkosc_ekran_b ; "km/h" ; Czass_b ; "s"
     
     
     
     
    End If
     
     
    '-----------------------------------------------------------------------------
    'przejście do menu nastaw jasności LCD    2/6
    '-----------------------------------------------------------------------------
    If Menu = 2 And Podmenu = 0 Then
     
    Locate 1 , 1
    Lcd " Ustaw  Jasnosc "
    Locate 2 , 1
    Lcd "  podswietlenia "
     
    If M = 0 Then : Podmenu = 1 : Opcja = 0 : Waitms 500 : End If       'po wciśnięciu M przejdź do nastawy jasności ręcznej
    End If
     
    '-----------------------------------------------------------------------------
    'Fragment obsługujący ręczną nastawę jasności
    '-----------------------------------------------------------------------------
     
    If Menu = 3 Then
     
    Locate 1 , 1
    Lcd "  Jasnosc LCD   "
    Locate 2 , 1
    Lcd "-    " ; Pwm ; "%   +"
     
    Waitms 150
    Locate 1 , 1
    Lcd "                     "
    Waitms 150
    Locate 2 , 1
    Lcd "     " ; Pwm ; "     "
     
    If Plus = 0 Then
    Pwm = Pwm + 10
    If Pwm >= 101 Then
    Pwm = 0
    End If
    End If
     
    If Minus = 0 Then
    Pwm = Pwm - 10
    If Pwm >= 101 Then
    Pwm = 100
    End If
    End If
     
    If M = 0 Then : Writeeeprom Pwm , 4 : End If                ' po wcisnieciu m przejdz do nastepnej pozycji
    End If
     
     
     
     
    Loop
    End
     
    '******************************************************************************************
    '##########################################################################################
    '******************************************************************************************
     
    Co10ms:
    Timer0 = 655343.75                                          ' zakaduj do timier, zeby zliczyl 625        (= 655350- 655343 , 75) impulsów cp 0,1 ms
     
    If Fototranzystor1a_poczatek = 0 Then Licz = 1              'sprawdź stan 1 bramki i ewentualnie rozpocznij zliczanie czasu
    If Fototranzystor1a_koniec = 0 Then Licz = 0                'sprawdź stan 2 bramki i ewentualnie zakoncz zliacznie czasu
    If Licz = 1 Then
       Incr Dzies_tys_sek                                       'co 10 ms zwieksz wartosc licznika setnych
       If Dzies_tys_sek = 10 Then
          Dzies_tys_sek = 0
          Incr Tys_sek
             If Tys_sek = 10 Then
                Tys_sekk = 0
                Incr Setsek
                   If Setsek = 10 Then
                      Setsek = 0
                      Incr Dziesek
                         If Dziesek = 10 Then
                            Dziesek = 0
                            Incr Sekjed
                               If Sekjed = 10 Then
                                  Sekjed = 0
                                  Incr Sekdzies
                                     If Sekdzies = 10 Then
                                        Sekdzies = 0
                                        Incr Sekset
                                           If Sekset = 10 Then
                                              Sekset = 0
                                              Incr Sektys
                                                 If Sektys = 10 Then Sektys = 0       'liczy do 99,9999 sekund
       End If
          End If
             End If
                End If
                   End If
                      End If
                         End If
                            End If
     
     
    If Fototranzystor3b_poczatek = 0 Then Licz = 1              'sprawdź stan 1 bramki i ewentualnie rozpocznij zliczanie czasu
    If Fototranzystor4b_koniec = 0 Then Licz = 0                'sprawdź stan 2 bramki i ewentualnie zakoncz zliacznie czasu
    If Licz = 1 Then
       Incr Dzies_tys_sek_b                                     'co 10 ms zwieksz wartosc licznika setnych
       If Dzies_tys_sek_b = 10 Then
          Dzies_tys_sek_b = 0
          Incr Tys_sek_b
             If Tys_sek_b = 10 Then
                Tys_sekk_b = 0
                Incr Setsek_b
                   If Setsek_b = 10 Then
                      Setsek_b = 0
                      Incr Dziesek_b
                         If Dziesek_b = 10 Then
                            Dziesek_b = 0
                            Incr Sekjed_b
                               If Sekjed_b = 10 Then
                                  Sekjed_b = 0
                                  Incr Sekdzies_b
                                     If Sekdzies_b = 10 Then
                                        Sekdzies_b = 0
                                        Incr Sekset_b
                                           If Sekset_b = 10 Then
                                              Sekset_b = 0
                                              Incr Sektys_b
                                                 If Sektys_b = 10 Then Sektys = 0       'liczy do 99,9999 sekund
       End If
          End If
             End If
                End If
                   End If
                      End If
                         End If
                            End If
     
     
    '******************************************************************************************
    '##########################################################################################
    '******************************************************************************************
     
     
    Pwm_lcd:
    Incr Pwm_lcd_licznik
     
    If Pwm_lcd_licznik >= 100 Then
    Pwm_lcd_licznik = 0
    End If
     
    If Pwm_lcd_licznik < Pwm_zaladowane Then
    Set Portc.3
    Else
    Reset Portc.3
    End If
    Return
     
    '******************************************************************************************
    '##########################################################################################
    '******************************************************************************************
     
     
    Sub Odczytnapiecia
     
     
    Nap_adc = Getadc(5)
     
    Napiecie = Nap_adc * 0.0151113                              'maksimum to 1650
     
    Napiecie_ekran = Fusing(napiecie , "##.&&")
     
     
    End Sub
     
     
     
    '******************************************************************************************
    '##########################################################################################
    '******************************************************************************************
     
     
    Sub Konwert_zmienna_na_czass_a
     
    Czass_a =(sektys * 1000 ) +(sekset * 100 ) +(sekdzies * 10 ) + Sekjed +(dziesek * 0 , 1) +(setsek * 0 , 01) +(tys_sek * 0 , 001) +(dzies_tys_sek * 0 , 0001)
     
     
    End Sub
     
    '******************************************************************************************
    '##########################################################################################
    '******************************************************************************************
     
     
    Sub Konwert_zmienna_na_czass_b
     
    Czass_b =(sektys_b * 1000 ) +(sekset_b * 100 ) +(sekdzies_b * 10 ) + Sekjed_b +(dziesek_b * 0 , 1) +(setsek_b * 0 , 01) +(tys_sek_b * 0 , 001) +(dzies_tys_sek_b * 0 , 0001)
     
     
    End Sub
    '##########################################################################################
    '******************************************************************************************
     
    Sub Przelicz_vsr
     
    Predkosc_a =(droga_a \ Czass_a) * 3.6                       'droga w m/s
     
     
    Predkosc_ekran_a = Fusing(predkosc_a , "##.&&")
     
     
    End Sub
     
    '******************************************************************************************
    '##########################################################################################
    '******************************************************************************************
     
    Sub Przelicz_vch
     
    Gosub
     
    Predkosc_a =(droga_b \ Czass_b ) * 3 , 6
     
    Predkosc_ekran_b = Fusing(predkosc_b , "##.&&")
     
     
    End Sub

    0 21
  • #2 27 Cze 2013 00:54
    laki_17
    Poziom 17  

    Mało znam się na BASCOM'ie ale proponuję przesłać jakie błędy wyrzuca kompilator bo to może być bardzo istotne przy "naprawie" tego programu.

    0
  • #3 27 Cze 2013 06:09
    emarcus
    Poziom 35  

    Pablo2015 napisał:
    Witam,


    Program zamieszczam, nie chce się skompilować, nie bardzo ogarniam co mam źle, mile widziane sugestie itp.




    Bez urazy, ale praktycznie wszystko co napisałeś jest pozbawione sensu, albo błąd jest niemal w każdej linii programu.
    1. W jakim celu dokonujesz wpisów do eeprom jeżeli nigdy ich nie odczytujesz(!)
    2. Wszyskie funkcje "Fusing"masz błędny syntax,
    3. Subrutyna dla Timera0 "co 10ms:"

    Timer0 = 655343.75 ' zakaduj do timier, zeby zliczyl 625 (= 655350- 655343 , 75) impulsów cp 0,1 ms

    - chcesz wpisac liczbę dziesiętną do 8 - bitowego rejestru, który może akceptowac tylko liczby całkowite i nie większe niż 255(!)
    4. Pomiar napięcia przez ADC :

    Napiecie = Nap_adc * 0.0151113
    jest zupełnie pozbawiony sensu rachunkowego;
    -przy napięciu referencyjnym = Vcc (5V) współczynnik X = 5/1024 = 0.0049 (cztery miejsca dziesiętne to jest więcej niż faktycznie potrzebujesz).

    5. Wprowadzenie do programu zmiennych na pozimie "double"- po co ?????? i kto to potrzebuje?????
    6. Po co ci tyle zmiennych związanych z pomiarem czasu (każda cyfra/miejsce dziesiętne oddzielnie(!) - jedna zmienna wystarczy z powodzeniem, nie ważne jak wielka ona jest.
    Rozkładanie liczby na poszczególne cyfry ma sens i koniecznośc tylko w przypadku wyswietlenia jej na wyświetlaczach 7-segm. LED; ty stosujesz LCD.
    7. instrukcję 'gosub' stosujesz dla skoku do subrutyny/label (etykiety);
    "Sub" wymaga innej instrukcji: "Call (Nazwa Sub) " albo zwyczajnie tylko Nazwa Sub.
    Nie chcę już komentowac sposobu pomiaru czasu pomiędzy impulsami/bramkami (!!!!!!!!). Obłęd....

    To co ty nazywasz algorytm - rozbij ten program na kilka części i opanuj każdą z nich oddzielnie zaczynając od: konfiguracji timerów dla róznych ich trybów pracy a następnie zastosowanie ADC i jego związek z przyjętym napięciem referencyjnym.
    Stosowanie interruptów:
    Jeżeli masz
    On Timer0 Czas_przejazdu_a
    to gdzieś w programie winna znaleźc sie sybrutyna/label;

    Czas_przejazdu_a:
    ..........
    Return

    To tylko kilka podstawowych błedów jaki sie pobieżnie 'rzuciły' na poczatek.

    e marcus

    0
  • #4 27 Cze 2013 10:26
    Pablo2015
    Poziom 18  

    Nie mam żadnego urazu ;-)

    Stosuje zmienne double ponieważ prędkość śrutu jest bardzo duża i zależy mi na jak dokładniejszym pomiarze, tak samo z timerem0 chciałem mieć pomiar czasu z dokładności do 4 miejsca po przecinku.

    W innym projekcie stosowałem taki pomiar napięcia jak proponujesz i było dużo za duże. Wartość dobrałem doświadczalnie i jet OK, też mnie to zdziwiło...

    Jak proponujesz zrealizować pomiar czasu pomiędzy bramkami?

    0
  • #5 27 Cze 2013 13:21
    emarcus
    Poziom 35  

    Pablo2015 napisał:


    Jak proponujesz zrealizować pomiar czasu pomiędzy bramkami?


    Spróbuj wykorzystac Timer1 i funkcję 'Capture' czasu pomiędzy dwoma zboczami.
    Gdybyś nawt zastosował prescaler=64 to i tak otrzymasz rozdzielczośc 4 µsec., a maxymalny czas do Ovf1 = 0.26214 sec.; przy taktowaniu 16 MHz.
    Czy potrzebujesz jeszcze wyższą dokładnośc ?

    Zmienna czasu zwymiarowana "as Single" ci wystarczy.


    e marcus

    0
  • #6 27 Cze 2013 22:08
    Pablo2015
    Poziom 18  

    Na schemacie są 4 bramki, do pomiaru prędkości chwilowej i średniej. Czy jednym Timerem można mieć niezależny pomiar czasu z 2 par bramek, czy trzeba użyć 1 timera na 1 parę bramek? Timer2 ma inny rejestr, tak?

    0
  • #7 29 Cze 2013 23:15
    Pablo2015
    Poziom 18  

    Poczytałem trochę bo właściwie nie wiedziałem nic, na temat timerów i napisałem ich subrutyny.

    Podczas liczenia prędkości zmienne czas_s/czas_ch będę mnożył przez 0.004 i dzielił przez podaną drogę. Co ty na to?

    KOD:

    Code:
    '***********PROGRAM POMIAR PREDKOSCI************
    
    '*************** Konfiguracja uC ***************

    $regfile = "m8def.dat"
    $crystal = 16000000                                         'trzeba zmienić fusebity na zewnetrzny zegar o taktowaniu 16 MHz

    Config Lcd = 16 * 2                                         'konfiguracja wyswietlacza LCD 16x 2
    Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portd.7 , Db7 = Portb.0 , E = Portd.4 , Rs = Portd.3
    Cursor Off

    Config Adc = Single , Prescaler = Auto , Reference = Avcc   'konfiguracja wewnętrznego przetwornika A/c
    Start Adc                                                   'uruchomienie wewnętrznego przetwornika A/C


    Config Timer0 = Timer , Prescale = 1                        'timer0 do PWM dla wyświetlacza
    On Timer0 Pwm_lcd
    Timer0 = 0
    Enable Interrupts
    Enable Timer0
                                                                  'timer1 dla bramki predkosci sredniej
    Config Timer1 = Timer , Prescale = 1
    On Timer1 predkosc_srednia
    Enable Interrupts
    Enable Timer2
                                                                  'timer2 dla bramki predkosci chwilowej
    Config Timer2 = Timer , Prescale = 1
    On Timer2 predkosc_chwilowa
    Enable Interrupts
    Enable Timer0



    '********** Konfiguracja uC kontynuacja  ************
    '******************  Nazwy zmiennych ****************

    's- predkosc srednia, ch- chwilowa

    Config Portc.4 = Output                                     'wyjście na podświetlenie LCD
    Reset Portc.4                                               'tranzystor NPN

    Config Portc.0 = Input                                      'FOTOTRANZYSTOR 1
    Set Portc.0
    Config Portc.1 = Input                                      'FOTOTRANZYSTOR 2
    Set Portc.1
    Config Portc.2 = Input                                      'FOTOTRANZYSTOR 3
    Set Portc.2
    Config Portc.3 = Input                                      'FOTOTRANZYSTOR 4
    Set Portc.3

    Foto1s Alias Pinc.0
    Fotot2s Alias Pinc.1
    Fotot1ch Alias Pinc.2
    Fotot2ch Alias Pinc.3

    Config Portd.0 = Input                                      'przycisk "+"
    Set Portd.0
    Config Portd.1 = Input                                      'przycisk "M"
    Set Portd.1
    Config Portd.2 = Input                                      'przycisk "-"
    Set Portd.2

    Plus Alias Pind.0
    M Alias Pind.1
    Minus Alias Pind.2

    Config Portb.1 = Output                                     'buzzer - tranz. PNP
    Set Portb.1
    Buzzer Alias Portb.1
                                                                  'Lasery- tranz. NPN
    Config Portb.5 = Output
    Set Portc.5
    Config Portb.4 = Output
    Set Portb.4

    Laser_s Alias Pinb.5
    Laser_ch Alias Pinb.4

    Config Portb.3 = Output                                     'Led- tranz. NPN
    Set Portc.3
    Config Portb.2 = Output
    Set Portb.2
                                                                   'ustawiona w programie wartosch predkosci z ktora bedzie porownywana ta z pomiaru
    Led_dobrze Alias Pinb.3
    Led_zle Alias Pinb.2

    '*************  Nazwy Koniec  ****************

    '****************  Zmienne *******************

    Dim Pwm_lcd_licznik As Byte                                 'wewnętrzny licznik PWM-u
    Dim Pwm As Byte                                             'ustawiona wartość PWM dla podświetlenia lcd
    Dim Pwm_zaladowane As Byte                                  'wartość wypełnienia, które będzie faktycznie działała - przydatne przy funkcji StarLight


    Dim Czas_s As Double
    Dim Czas_ch As Double

    Dim Licz1 As Bit
    Dim Licz2 As Bit

    Dim Nap_adc As Word                                         'wartość odczytana z ADC
    Dim Napiecie As Single                                      'wartość napięcia do pokazania na ekranie
    Dim Napiecie_ekran As String * 6                            'wartość napięcia do wyświetlenia na ekranie
    '*************  Zmienne koniec  ****************

    '***************  podprogramy ******************

    Declare Sub Odczytnapiecia                                  'odczyt napięcia z ADC i konwersja na liczbę

    '***********************************************
    'tu bedzie petla glowna
    Do

    Loop
    End

    '******************************************************************************************
    'etykiety:

    Pwm_lcd:

     Incr Pwm_lcd_licznik

     If Pwm_lcd_licznik >= 100 Then
     Pwm_lcd_licznik = 0
     End If

     If Pwm_lcd_licznik < Pwm_zaladowane Then
     Set Portc.3
     Else
     Reset Portc.3
     End If
    Return

    Predkosc_srednia:

    Timer1 = 1536                                               '2^16= 65536, przy prescale 1, 16MHz* 0,004= 64000, 65536-6400=1536
    'tutaj polecenia wykonuja wykonuja sie co 0,004s
    If Foto1s = 0 Then Licz1 = 1
    If Foto2s = 0 Then Licz1 = 0
    If Licz1 = 1 Then
    Incr Czas_s                                                 'wynik (czas) bedzie
                                                                'co 4ms zwieksz wartosc Czas_s o 1
    End If
       End If
          End If


    Return

    Predkosc_chwilowa:

    Timer2 = 1536

    If Foto1ch = 0 Then Licz2 = 1
    If Foto2ch = 0 Then Licz2 = 0
    If Licz2 = 1 Then
    Incr Czas_s                                                 'wynik (czas) bedzie w
                                                                'co 4ms zwieksz wartosc Czas_ch o 1
    End If
       End If
          End If

    Incr Czas_ch

    Return

    Odczytnapiecia:

    Nap_adc = Getadc(5)

    Napiecie = Nap_adc * 0.0049
    Napiecie_ekran = Fusing(napiecie , "##.##")
    Napiecie_ekran = Napiecie_ekran + "V"

    Return

    0
  • #8 30 Cze 2013 04:11
    emarcus
    Poziom 35  

    Pablo2015 napisał:
    Poczytałem trochę bo właściwie nie wiedziałem nic, na temat timerów i napisałem ich subrutyny.

    Podczas liczenia prędkości zmienne czas_s/czas_ch będę mnożył przez 0.004 i dzielił przez podaną drogę. Co ty na to?


    Dalej jest nie dobrze....., bardzo nie dobrze(!)

    Zacznijmy od Timera2:
    Cytat:

    Predkosc_chwilowa:

    Timer2 = 1536


    Timer2 ma rejestr 8-bitowy, więc nie zaakceptuje wpisu wiekszego niz 255..., zdaje się że pisałem o tym wcześniej.

    Odnośnie Timera1:
    Mimo że stosujesz prescaler = 1, może wydawac się że mierzysz czas dośc dokładnie , gdy tymczasem ta dokładnoiśc jest nijaka (żadna).
    Popatrz na ten fragment :
    Po pierwsze nie masz w kodzie zezwolenia na OVF1, (brak 'enable Timer1') powiedzmy że tam masz pomyłkę, to i tak ta metoda jest błędna.

    Cytat:

    Predkosc_srednia:

    Timer1 = 1536 '2^16= 65536, przy prescale 1, 16MHz* 0,004= 64000, 65536-6400=1536
    'tutaj polecenia wykonuja wykonuja sie co 0,004s
    If Foto1s = 0 Then Licz1 = 1
    If Foto2s = 0 Then Licz1 = 0
    If Licz1 = 1 Then
    Incr Czas_s 'wynik (czas) bedzie
    'co 4ms zwieksz wartosc Czas_s o 1



    Mierzony przedział czasu pomiędzy Foto1s a Foto2s jest incrementowany odstępami co 4 ms; a jaki "czas_s" będzie liczony (z jaka dokładnością) jeżeli impuls na Foto2s wystąpi gdześ pomiedzy: powiedzmy 4 i 5; w/g twojego rachunku otrzymasz czas_s = 16 ms gdy tymczasem może on byc 19 ms.
    Musisz mierzyc całkowity czas nie tylko przepełnienia, ale także pozostały czas naliczony przez timer do momentu impulsu z dokładnościa do ostatniej microsec.
    Mało tego, metoda sprawdzania (polling) stanu portu jest wyjątkowo nie dokładna, a w czczególności dla pomiarów bardzo krótkich czasów tak jak w twoim przykładzie wręcz bezużyteczna. Masz zbędne stawiane flagi i ich odczytanie i porównywanie stanów zabiera czas w instrukcjach warunkowych. Za dużo tego masz.
    Musiałbyś w odpowiednich momentach zerowac/startowac timer, w innym, zatrzymywac/odczytywac.

    Proponowałbym użycie odpowiednio skonfigurowanego interruptu zewnętrznego i mierzyc czas dokładnie pomiędzy dwoma impulsami. Przeszukaj forum; było tu bardzo dużo przykładów podanych w tematach z tachometrami.
    Możesz użyc ten sam interrupt dla impulsu z Foto1s oraz z Foto2s przy odpowiedniej kombinacji zboczami.

    Cytat:

    Napiecie_ekran = Fusing(napiecie , "##.##")


    Poprawnie:
    Napiecie_ekran = Fusing(napiecie , "#.##") ' przed znakiem dziesiętnym ma byc tylko jeden znak # (hash).


    e marcus

    0
  • #9 30 Cze 2013 11:48
    Pablo2015
    Poziom 18  

    Z timerem2 się pomyliłem, myślałem że jest 8 bitowy ;-). Przejrzałem DS i jak byk jest napisane:
    "Two 8- bit Timer/Counters with Separate Prescaler, one Compare Mode
    One 16- bit Timer/Counter with Separate Prescaler, Compare Mode, and Capture Mode"

    Atmega8 ma 2 wejścia zewnętrznego interruptu, INT0(PD2) i INT1(PD3), bramki są 4, jak "odpowiednio kombinować" zboczami aby dało się podpiąć 2 bramki wejściowe pod jeden interrupt? Jak zrealizować to w hardware'rze? Czy wystarczy podpiąć 2 fotorezystory pod jeden interrupt? Będą one prawdopodobnie na długim kablu(20- 30m), czy znacząco wpłynie to na pomiar?

    0
  • #10 30 Cze 2013 12:05
    BlueDraco
    Specjalista - Mikrokontrolery

    Cały prawy górny sektor schematu to jedna wielka pomyłka. Niepotrzebne komparatory i potencjometry (łatwiej mierzyć napięcie na dzielnikach złożonych z rezystorów i fotorezystorów. Brak rezystorów przy LED. Diody prostownicze uniemożliwiające działanie komparatorów.

    0
  • #11 30 Cze 2013 12:31
    Pablo2015
    Poziom 18  

    Co do diod to https://www.elektroda.pl/rtvforum/viewtopic.php?t=2413125&highlight=

    Potencjometry służą do regulacji czułości- przy mocnym oświetleniu z otoczenia, np. Słońca.

    Przy LED rzeczywiście brakuje rezystorów, dzięki ;-)

    Nad komparatorami się zastanowię, myślę nad propozycją użytkowania emarcus o wykorzystaniu zewnętrznych interruptów.

    0
  • #12 30 Cze 2013 12:38
    BlueDraco
    Specjalista - Mikrokontrolery

    Czułość możesz wyregulować w oprogramowaniu, bez potencjometrów i komparatorów. Diody są potrzebne przy jednym komparatorze dla wielu fotorezystorów, a warunkiem zadziałania takiego połączenia jest obecność rezystora oznaczonego jako R5 na schemacie w wątku, który zalinkowałeś. Reasumując, wyrzucając diody, potencjometry i komparatory poprawisz własności użytkowe swojego urządzenia i przy okazji ułatwisz sobie montaż.

    Przy okazji wyrzuć R4 i R10.

    0
  • #13 30 Cze 2013 12:51
    Pablo2015
    Poziom 18  

    No nie wiem czy łatwiej jest klikać switchem kilka naście/dziesiąt razy czy przekręcić sobie potencjometr ;-).

    Zastanowię się jeszcze nad tymi potencjometrami.

    Co do diod to rzeczywiście brakuje mi tego rezystora, dzięki.

    0
  • #14 30 Cze 2013 13:42
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie brakuje Ci rezystora, tylko masz wstawione bezensowne i zbędne diody, które byłyby potrzebne wyłącznie wtedy, gdybyś miał jeden wspólny komparator dla wszystkich fotorezystorów.

    0
  • #15 30 Cze 2013 15:04
    Pablo2015
    Poziom 18  

    Ok, jak wykorzystać dwa interrupty INT0 i INT1 do 4 bramek?

    0
  • #16 30 Cze 2013 15:17
    emarcus
    Poziom 35  

    Pablo2015 napisał:

    Nad komparatorami się zastanowię,.............


    Pablo,
    Byłem niemal pewny że ten diagram masz tylko jako koncept...
    Zrezygnuj z fotorezystorów, a w to miejsce daj albo fototranzystor oświetlany diodą IR, albo komplet określany w opgólności jako "Photo Interrupter".
    Mozesz je dostac gotowe ze szczeliną nawet 10mm, lub możesz je wykonac we własnom zakresie.
    Przykład takiego urządzenia masz tu:
    https://www.sparkfun.com/products/9299
    Fotorezystory mają zbyt dużą bezwładnośc i w twoim projekcie mogą nie spełnic oczekiwanego efektu.
    W necie znajdziesz dużo na ten temat.

    e marcus

    0
  • #17 30 Cze 2013 15:29
    Pablo2015
    Poziom 18  

    Nie chcę transoptora, skoro fotorezystor ma dużą bezwładność (bo ma) użyję fototranzystora, będzie go oświetlała dioda laserowa 5mW.

    Jak rozwiązać sprawę z podłączeniem 2 fototranzystorów do jednego interruptu?

    0
  • #18 30 Cze 2013 15:37
    BlueDraco
    Specjalista - Mikrokontrolery

    Proponuję zacząć od początku: założenia, wymagania na mikrokontroler, dobór elementów. Nie jestem pewny, czy potrzbujesz rzeczywiście 4 przerwań, ale jeżeli tak, to znajdź mikrokontroler, który ma 4 wejścia przerwań, np. chociażby seria ATtiny lub cokolwik, co ma "port change interrupt". Rozpoczynanie od wyboru mikrokontrolera - to zupełnie zły pomysł.

    oczywiście bariery powinny być zrobione na fototranzystorach. nie wiem, czemu boisz się słowa "transoptor", skoro to, co chcesz zrobić, to właśnie jest transoptor, w tym przypadku złożony z lasera diodowego i fototranzystora.

    Jeżeli koniecznie potrzbujesz tych przerwań i uparłeś się na ATmega8, to pomyśl o użyciu funkcji capture timera - możesz nawet nie czytać rejetru Capture, a wykorzystać samo przerwanie. Jeśli nie używasz wszystkich timerów, to 2 przerwania "zwykłe" i 2 capture dadzą Ci brakującą funkcjonalność czterech wejść przerwań.

    0
  • #19 30 Cze 2013 15:52
    Pablo2015
    Poziom 18  

    Używam 3 timerów, po jednym na parę bramek+ sterowanie podświetleniem wyświetlacza na PWM.

    BlueDraco napisał:

    Jeżeli koniecznie potrzbujesz tych przerwań i uparłeś się na ATmega8, to pomyśl o użyciu funkcji capture timera - możesz nawet nie czytać rejetru Capture, a wykorzystać samo przerwanie. Jeśli nie używasz wszystkich timerów, to 2 przerwania "zwykłe" i 2 capture dadzą Ci brakującą funkcjonalność czterech wejść przerwań.


    Rozwiń

    0
  • #20 30 Cze 2013 22:36
    emarcus
    Poziom 35  

    Pablo2015 napisał:
    Nie chcę transoptora, skoro fotorezystor ma dużą bezwładność (bo ma) użyję fototranzystora, będzie go oświetlała dioda laserowa 5mW.


    To nie jest transoptor (!)..., mimo że jest zbudowany z podobnych elementów.
    Transopotor (opotocoupler) jest w obudowie zamknietej, a z tego tytułu odległośc od foto tranzystora do diody emitującej (IR) jest niewielka, a zatem moc tej dioidy jak i czułośc tranzystora są nie wielkie.
    Foto Interrupter jest układem optycznie otwartym. podobnym do elementów w starego typu (mechanicznej) myszy komputerowej, lecz ma pojedynczy foto tranzystor jako odbiornik o zwiekszonej czułości, bądź ze wzmacniaczem pozwalający na zwiększenie odległosci pomiędzy diodą IR a tranzystorem.
    Praktycznie będziesz budował to co jest gotowe i powszechnie dostępne.

    Zrobisz jak zechcesz...

    Cytat:


    Jak rozwiązać sprawę z podłączeniem 2 fototranzystorów do jednego interruptu?


    Jeżeli twoje foto tranzystory [pracuja w układzie "Common emitter" ( open colector) tak jak na poniższym rysunku,
    Atmega8 - Chronometr- pomiar porędkosci

    to układ generuje przejście wyjścia ze stanu wysokiego do niskiego podczas detekcji światła. Analogicznie przy przesłonięciu światła będziesz miał odwrotny efekt.
    Do tej funkcji skonfigurujesz /wybierzesz zbocze na które ma byc uczulony Interrupt.
    Wyjścia obydwu tranzystorów podłączysz do wejśc bramki OR a z bramki na pin wejściowy processora z interruptem.
    Obydwa tranzystory jezeli aktywne będą generowały interrupt, jednak każdy w innym czasie.
    Zróżnicujesz ich funkcje dopiero w subrutynie wywołanej przez interrupt.
    Pierwszy będzie startował/zerował Timer oraz stawiał flagę. Przy następnym wywołaniu tej samej subrutyny tymsamym interruptem lecz innym tranzystorem;
    sprawdzisz warunek: czy jest flaga- jeżeli tak to zatrzymasz/odczytasz zawartośc timera oraz wyzerujesz flagę.
    Praktycznie robi sie to w nieco innej kolejności stosując instrukcję warunkową z 'else'.

    Możesz oczywiscie zastosowac inny processor i wykorzystac dowolny PCINT oddzielnie dla kazdego tranzystora (hint from Draco), którymi w efekcie końcowym będziesz kontrolował pracą tego samego timera.
    Ważne jest aby te pomiary czasów były pozbawione błędów.

    Istnieje także możliwośc pomiaru czasu pomiędzy impulsami bez użycia interruptów stosując instrukcje "While...wend".
    Metoda z interruptami wymaga aby 'odległośc czasowa' pomiedzy interruptami (bramkami) była co najmniej 100 cykli (czas wymagany na obsługę interruptu oraz powrót).

    e marcus

    0
  • #21 01 Lip 2013 21:08
    Pablo2015
    Poziom 18  

    A co jeśli w obu bramkach startowych pojawi się zbocze w tym samym momencie i będą generowały interrupt?

    Napisz coś więcej o instrukcji While... wend

    0
  • #22 02 Lip 2013 22:37
    Pablo2015
    Poziom 18  

    A co jeśli wykorzystać do tego ADC?

    Jeśli dajmy na to fototranzystor jest oświetlany na wejściu ADC mamy powiedzmy wartość 100. Jeśli wiązka zostanie przerwana to na wejściu będzie wartość dużo wyższą czyli na przykład 800. Wystarczy tu warunek if wartosc_adc >800 then

    Mogę się mylić bo to tak na szybko pomyślane bez głębszych przemyśleń.

    0
  Szukaj w 5mln produktów