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

[Atmega8][Bascom] MEMS, pomiar przeciążeń i prędkości

mpkalach 18 Lut 2010 10:29 3586 13
REKLAMA
  • #1 7712396
    mpkalach
    Poziom 10  
    Witam.
    Mam do zrobienia w szkole stanowisko badające przeciążenia kierowcy podczas symulacji zderzenia samochodu. Całość w skrócie wygląda tak, że na metalowej konstrukcji jest umieszczony fotel z pasami bezwładnościowymi wraz z czujnikiem akcelerometrycznym (MMA3202DR2 Freescale). Fotel ten jest ustawiony pod pewnym kątem do podłoża, zjeżdżając uderza w miękką belkę.
    Z pomiarem przeciążeń raczej kłopotu nie będzie gdyż ma być rejestrowany oscyloskopem, więc wyjścia Xout, Yout przez filtr RC i z gniazd BNC na oscyloskop.
    Problem pojawia się z pomiarem prędkości. Jak mniemam podłączone wyjścia z obu osi przez filtr RC na ADC Atmegi. Jak wiadomo prędkość to całka przyspieszenia po czasie. Z teoretycznych wyliczeń na tej konstrukcji uzyskuję 3,6 m/s^2. Więc przykładowo po 1s prędkość wyniesie 3,6 m/s , po 2s - 7,2 m/s itd. Sygnał przeliczam na przyspieszenie i zegar musiałby wystartować w momencie a>0 (pomijając przyspieszenie statyczne-grawitacja). I tutaj tkwi problem gdyż nie bardzo wiem jak zaimplementować to w bascomie. Dodatkowo muszę najwyższą uzyskaną prędkość (tuż przed zderzeniem) wyświetlić na lcd. Dotychczas nie było problemów z programowaniem lcd i udało mi się wyświetlić wartości z czujnika, ale chodzi właśnie o wspomnianą wcześniej najwyższą wartość prędkości.

    Prosiłbym o jakieś podpowiedzi, wskazówki.
  • REKLAMA
  • #2 7712547
    Kabuto15
    Poziom 19  
    Chciałbym dodać, że wcale całka nie jest dobrym zastosowaniem jeśli chcesz coś wyliczyć w sprzęcie. Często błąd jednego bitu powoduje, że efektem końcowym jest odpływanie wyniku.
  • REKLAMA
  • #3 7712714
    mpkalach
    Poziom 10  
    U mnie czas pomiaru będzie wynosił ok. 1,5s od momentu startu do zatrzymania fotela. Myślę, że nie będzie odpływania wyniku od rzeczywistej wartości. Próbki będę odczytywał przypuśćmy co 10ms. I tak dla 10ms będzie ok 0,036m/s, dla 20ms - 0,072m/s, dla 30ms - 0,108m/s itd. Każde drgania się odbiją na przyspieszeniu więc również prędkość będzie rosła znacząco, więc myślę żeby uśrednić 10 wyników i dopiero wtedy je dodawać. Można również zastosować mechaniczne filtrowanie i płytke z akcelerometrem umieścić na gąbce lub czymś pochłaniającym w jakimś stopniu drgania.
    Tylko problem tkwi w tym, że nie znalazłem nigdzie kodu czy też jakiś pomocnych instrukcji do tego jak zaprogramować to w bascomie. Większość tematów z akcelerometrami została zapomniana i opuszczona albo poprostu nikt nie wrzucał wsadu do procka.
  • #4 7713106
    Kabuto15
    Poziom 19  
    Program będziesz musiał napisać sam. Bascom trudny nie jest a z jego nauki można czerpać dużą przyjemność. Co do samego programu to zazwyczaj akcelometry dają sygnał napięciowe dla każdej z osi. Musisz obsłużyć przetwornik ADC w mikrokontrolerze AVR i do tego Timery (odmierzanie czasu). Funkcje LCD są wbudowane, więc tak naprawdę najcięższe zadanie za Tobą.
    Swoją drogą nie wiem jak wygląda cała konstrukcja części mechanicznej, ale co jeśli układ będzie poruszał się ruchem jednostajnym do momentu uderzenia ? Rozumiem, że raczej jest to równia pochyła, więc przyspieszenie będzie rosnąć i tego problemu unikniesz (kiedy przyspieszenie równe zero).
  • #5 7713785
    mpkalach
    Poziom 10  
    Tak, jest to równia pochyła, więc non stop działa przyspieszenie równe:
    a=g(sinα) (pomijając siły tarcia)
    gdzie:
    α-kąt nachylenia szyn a podłożem
    g-przyspieszenie ziemskie

    A pytanie co do tego przetwornika ADC, jak zaimplementowac żeby przypuśćmy 2,5V to 0g, 2,55V to 1g, 2,6V to 2g... i żeby wartości pośrednie również zmieniały się liniowo zależnie od napięcia.
  • #6 7713818
    Kabuto15
    Poziom 19  
    Przetwornik konfigurujesz, przykład np. w dokumentacji
    http://ds5.agh.edu.pl/~czaro/naukowo/avr_adc.htm
    Z przetwornika będziesz dostawał wartości liczbowe: od 0 do 1023. W zależności od wybranego napięcia referencyjnego, otrzymywana wartość cyfrowa będzie proporcjonalna do wejściowego napięcia w odniesieniu do referencyjnego.
    Z dokumentacji możesz odczytać czułości akcelometru w odpowiednich osiach. Zazwyczaj jednak kalibruje się taki czujnik. Ustawiasz np. w osi X tak aby wskazywał -1g, a następnie obracasz aby w tej osi wskazywał +1g. Przy obu ustawieniach sczytujesz napięcie i możesz obliczyć funkcję przetwarzania, a także pozbyć się offsetu (programowo).
  • #7 7713835
    mpkalach
    Poziom 10  
    Dzięki, zajrze tam (szkoda jak dla mnie, że jest w C a nie w bascomie). Jak uda mi się coś zaprogramować to się odezwę.
  • REKLAMA
  • #8 7714214
    leon1313
    Poziom 15  
    Masz już zrobioną część elektryczną? IMO, zrób sobie zapis na kartę SD i późniejszy odczyt i analizę na PC( choć tu juz musisz się zastanowić nad ATMEGA32). Po twojej stronie będzie tylko kalibracja, aby uzyskać max rozdzielczość.
    Masz obslugę ADC w bascom ( to przetwornik z linijką świetlną i wynikiem napięcia i wartości z ADC na LCD):
    PortB podłączamy przewodami do diod, Vref za pomocą kondensatora do GND na płytce, PINA.0 do wyjścia któregoś z potencjometrów
    LCD według konfiguracji z programu.
    
    $regfile = "m32def.dat"
    $crystal = 16000000
    
    'konfiguracja wyświetlacza LCD
    Config Lcdpin = Pin , Rs = Portc.2 , E = Portc.3 , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7
    Config Lcd = 16 * 2
    Cursor Off
    'konfiguracja portu b - dla wyswietlania diod
    Config Portb = Output
    Portb = 255
    
    
    Dim Val0 As Word                                            ' wartosc odczytana
    Dim Val0_str As String * 4                                  ' wartosc odczytana- string
    Dim Volt As Single                                          ' w voltach
    Dim Vol_str As String * 4                                   ' volty w przyjanym formacie
    Dim Val1 As Word                                            ' pomocnicza przy aktualizacji lcd
    Val1 = 1024                                                 ' aby pierwszy raz wyswietlilo wartosc
    Dim Channel As Byte                                         ' kanal (pin)
    
    Config Adc = Single , Prescaler = Auto , Reference = Avcc   'prescaler (7 bit, najlepiej auto) i zrodlo odniesienia
    
    Start Adc
    
    Channel = 0
     Cls
     Lcd "Volt:"
     Lowerline
     Lcd "ADC: "
    
    
    Do
       Val0 = Getadc(channel)
       Portb = 255
       If Val0 > 50 Then Reset Portb.0
       If Val0 > 150 Then Reset Portb.1
       If Val0 > 300 Then Reset Portb.2
       If Val0 > 450 Then Reset Portb.3
       If Val0 > 600 Then Reset Portb.4
       If Val0 > 750 Then Reset Portb.5
       If Val0 > 900 Then Reset Portb.6
       If Val0 > 1000 Then Reset Portb.7
    
       Volt = Val0 * 0.0048828
       Vol_str = Fusing(volt , "#.##")
       Val0_str = Str(val0)
       Val0_str = Format(val0_str , "0000")
    
       If Val0 <> Val1 Then
          Val1 = Val0
          Locate 1 , 7
          Lcd Vol_str
          Locate 2 , 7
          Lcd Val0_str
       End If
    Loop 
    
  • #9 7718023
    mpkalach
    Poziom 10  
    Dzięki. Pokombinuje coś z tym. Aktualnie walcze z timerami i próbą obliczenia prędkości z przyspieszenia i czasu na zegarze.
    Pozdrawiam
  • REKLAMA
  • #10 7899169
    mpkalach
    Poziom 10  
    Witam ponownie. Mam już wykonany program do pomiaru przyspieszeni, niestety mam spory problem z obliczeniem z tego prędkości.
    Próbowałem odczytywać wartość z przetwornika ADC co pół sekundy (16000000/256/500/125 = 1, a dla 63 to dwa razy na sekunde) i do tego wykorzystałem:
    
    $crystal = 16000000  
    ...
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    Load Timer0 = 500
    A2 = 0
    V2 = 0
    
    Do
    Start Adc
       X = Getadc(1)
       Voltx = X * 0.00493
       Gx = Voltx - 2.4946
       Gx = Gx / 0.02
    ...
       Dt = 0.5
       On Timer0 Odmierz
    ...
    Loop
    End
    
    
    Odmierz:
    Load Timer0 = 500
    Incr Czas
    If Czas = 63 Then
    Cls
    Ax = Gx * 9.80665
    A1 = Ax - A2
    V1 = A1 / Dt
    V1 = V1 + V2
    Locate 1 , 1
    Lcd Fusing(v1 , "##.##")
    End If
    If Czas = 125 Then
    Cls
    Czas = 0
    Ax = Gx * 9.80665
    A2 = Ax - A1
    V2 = A2 / Dt
    V2 = V1 + V2
    Locate 1 , 1
    Lcd Fusing(v2 , "##.##")
    End If
    Return
    

    a więc od aktualnego przyspieszenia (Ax) odejmuje przyspieszenie które było 0,5s temu, dziele to przez różniczke czasu (Dt=0.5) a uzyskaną prędkość dodaje do prędkości poprzedniej.
    Niestety nie chce działać to prawidłowo i dlatego zwracam się o pomoc do ludzi którzy już mieli z tym styczność.

    Poniżej zamieszczam mój działający program mierzący przyspieszenia z dwóch osi.
    $regfile = "m8def.dat"
    $crystal = 16000000
    
    Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.5 , Db4 = Portb.4 , Db5 = Portb.3 , Db6 = Portb.2 , Db7 = Portb.1
    Config Lcd = 16 * 2
    Cursor Off
    
    Dim X As Word , Y As Word
    Dim Voltx As Single
    Dim Gx As Single
    Dim Volty As Single
    Dim Gy As Single
    Dim Licznik As Byte
    Dim Gx_sum As Single
    Dim Gy_sum As Single
    
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    
    
    
    
     Cls
     Lcd "Gx:"
     Lowerline
     Lcd "Gy: "
    
    
    Do
    Start Adc
       X = Getadc(1)
       Voltx = X * 0.00493
              Gx = Voltx - 2.4946
       Gx = Gx / 0.02
    
    
       Y = Getadc(2)
       Volty = Y * 0.00493
       Gy = Volty - 2.543
       Gy = Gy / 0.04
    
    Incr Licznik
    Gx_sum = Gx_sum + Gx
    Gy_sum = Gy_sum + Gy
    
    If Licznik = 63 Then
    Licznik = 0
    
    Gx_sum = Gx_sum / 64
    Gy_sum = Gy_sum / 64
    
    If Gx_sum >= 0 Then
    Locate 1 , 4
    Lcd " "
    Locate 1 , 5
    Lcd Fusing(gx_sum , "#.##")
    Elseif Gx_sum < 0 Then
     Locate 1 , 4
    Lcd Fusing(gx_sum , "##.##")
    End If
    
    If Gy_sum >= 0 Then
    Locate 2 , 4
    Lcd " "
    Locate 2 , 5
    Lcd Fusing(gy_sum , "#.##")
    Elseif Gy_sum < 0 Then
     Locate 2 , 4
    Lcd Fusing(gy_sum , "##.##")
    End If
    End If
    
    Loop
    
    End
  • #11 7905599
    mpkalach
    Poziom 10  
    Ponawiam prośbę.
  • #12 7906379
    sorex86
    Poziom 15  
    Kawałek kodu, który powinien Ci pomóc z odmierzaniem czasu:

    
    Odmierz_1s:
    
    
       Load Timer1 = 12500
       Incr Licz_10ms
    
       If Licz_10ms = 10 Then
          Licz_10ms = 0
    
       End If
    
    Return
    
    Zlicz:
    
       Incr Czestotliwosc
    
    Return


    Odmierza 1s, a potem zlicza ilość przerwań na timer0. Przerób na swój kwarc.
  • #13 7912454
    szun
    Poziom 19  
    A dlaczego nie robisz pomiaru prędkości na moment przed zderzeniem .
    Umieść dwa czujniki A i B np. co 10cm. przed zderzeniem .
    Chyba pomiar czasu jaki pokona fotel na drodze od A do B nie będzie dla ciebie problemem .
    A błąd pomiaru prędkości w ostatniej fazie będzie minimalny ,i powtarzalny w kilometrach na godzinę .
  • #14 7985067
    szun
    Poziom 19  
    mpkalach napisał:
    Ponawiam prośbę.

    Koniec roku szkolnego blisko działasz dalej :?:
REKLAMA