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

Jak wygenerować 40kHz z AT90s2313? Kod nie działa poprawnie.

JollyRoger 01 Sie 2005 13:28 2147 14
  • #1 1697531
    JollyRoger
    Poziom 21  
    Posty: 538
    Pomógł: 21
    Ocena: 30
    Witam, nie moge programowo wygenerować 40Khz z tego procka (potrzebne do nadajnika ultradźwięków):
    Poniżej kod:

    
    $crystal=4000000
    Enable Interrupts
    Config Portb = Output
    Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle
    Enable Timer1
    Start Timer1
    Timer1 = 65436
    On Timer1 Przerwanie
    
    Do
    Loop
    End
    
    Przerwanie:
    Timer1 = 65436
    Return
    


    Przy wpisanej wartości 65436 i prescalerze 1 przerwanie wywoływane jest co 0,000025s a więc na wyjściu OC1A powinno być 40KhZ, jednak dźwięk jest słyszalny... Mam na kompie program do pomiaru częstotliwośći (przez karte dźwiękową) i pokazuje on jakieś 1,2KhZ... Co jest nie tak?
  • #2 1697771
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    JollyRoger napisał:

    Przy wpisanej wartości 65436 i prescalerze 1 przerwanie wywoływane jest co 0,000025s a więc na wyjściu OC1A powinno być 40KhZ, jednak dźwięk jest słyszalny... Mam na kompie program do pomiaru częstotliwośći (przez karte dźwiękową) i pokazuje on jakieś 1,2KhZ... Co jest nie tak?

    Powiem krótko - źle to obliczyłeś :|
    65536-65436=100 OK
    do tych 100 , należy dodać ~56 cykli , jakie procesor zużyje na odłożenie na stos rejestrów , w procedurze obsługi przerwania, czyli razem ~156 cykli i dopiero po tym , załaduje rejestry Timer1.
    Teraz częstotliwość z jaką będzie się zmieniał stan na OC1A wynosi 4000000/156=~25640 Hz.Ponieważ na wygenerowanie 1 okresu dźwięku potrzebne są 2 przerwania , więc dźwięk na wyjściu będzie miał "tylko" 25640/2=12820Hz.

    Pozdrawiam
    Piotrek
  • #4 1698338
    JollyRoger
    Poziom 21  
    Posty: 538
    Pomógł: 21
    Ocena: 30
    Zumek -- dzięki za wskazówki ale niestety w moim procesorze nawet po ustawieniu Timer1 na 65492 max. częstotliwość jaką udaje mi się osiągnąć to ~16KhZ.
    Light'I -- jak chcesz to zrobić za pomocą PWM?
  • Pomocny post
    #5 1698490
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    JollyRoger napisał:
    Zumek -- dzięki za wskazówki ale niestety w moim procesorze nawet po ustawieniu Timer1 na 65492 max. częstotliwość
    jaką udaje mi się osiągnąć to ~16KhZ.

    Może tak: (Nadal w Bascomie , choć nie całkiem w Basicu)
    
    $crystal = 4000000
    Config Portb = Output
    Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle
    On Compare1a Introc1a Nosave
    Timer1 = 0
    Compare1a = 40   'tu możesz poeksperymentować ;-)
    Enable Compare1a
    Enable Interrupts
    Start Timer1
    Do
    
    Loop
    
    Introc1a:
    PUSH R24
    LDI R24,0
    '!OUT TCNT1H , R24
    !OUT TCNT1L , R24
    POP R24
    Return
    

    JollyRoger napisał:

    Light'I -- jak chcesz to zrobić za pomocą PWM?

    Też się zastanawiam :D

    Piotrek
  • #6 1698602
    JollyRoger
    Poziom 21  
    Posty: 538
    Pomógł: 21
    Ocena: 30
    Dzięki za pomoc, ale i tak mi coś nie wychodzi... Chyba lepiej bedzie jak to zrobie na układzie CD4049 :))
  • #7 1699056
    Elektrooonik
    Poziom 29  
    Posty: 1212
    Pomógł: 127
    Ocena: 83
    zumek napisał:

    JollyRoger napisał:

    Light'I -- jak chcesz to zrobić za pomocą PWM?

    Też się zastanawiam :D

    przydałby sie jeszcze zewnetrzny przetwornik współczynnika wypełnienia na częstotliwość :)

    ps Jolly Roger, czy ta czestotliwosc musi byc równa dokładnie 40kHz? moze spróbujesz wygenerowac ta czestotliwosc z wykorzystaniem komend typu WAIT? to rozwiazanie dla wyjatkowo zdesperowanych ale za to proste :)
  • #8 1699233
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    Nieścisle się wyraziłem, wspólczynnik wypełnienia zostawiamy w spokoju, tylko korzystamy z rejestrów od PWM ustawionych na Toggle & Reset Counter on compare match - im mniejsza wartość w TCNTC, tym wieksza częstotliwość na wyjściu . Ma to ta zaletę, że sobie działa w tle, a my zajmujemy się czym innym.... ;) No chyba, że coś pomieszałem z nowszymi AVR, bo już ledwo na oczy teraz widzę... Dobranoc Państwu ;)
  • #9 1699281
    Jarema
    Użytkownik obserwowany
    Posty: 1179
    Pomógł: 86
    Ocena: 32
    Skoro proc ma sprzetowy PWM, to wystarczy ustawić współczynnik wypełnienia np. 50% i do rejestru wpisać wartość która pozwoli wygenerować przebieg o f=40kHz, to chyba żadna filozofia...
  • #10 1699511
    JollyRoger
    Poziom 21  
    Posty: 538
    Pomógł: 21
    Ocena: 30
    Light'I napisał:
    Nieścisle się wyraziłem, wspólczynnik wypełnienia zostawiamy w spokoju, tylko korzystamy z rejestrów od PWM ustawionych na Toggle & Reset Counter on compare match - im mniejsza wartość w TCNTC, tym wieksza częstotliwość na wyjściu


    Który rejestr odpowiada za częstotliwość PWM? Jakoś czytałem PDFa ale nigdzie nie mogem tego znaleźć :)
  • #11 1699517
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    Light'I napisał:
    Nieścisle się wyraziłem, wspólczynnik wypełnienia zostawiamy w spokoju, tylko korzystamy z rejestrów od PWM ustawionych na Toggle & Reset Counter on compare match - im mniejsza wartość w TCNTC, tym wieksza częstotliwość na wyjściu . Ma to ta zaletę, że sobie działa w tle, a my zajmujemy się czym innym.... ;) No chyba, że coś pomieszałem z nowszymi AVR, bo już ledwo na oczy teraz widzę... Dobranoc Państwu ;)

    Właściwie tak chciałem to zrobić , tylko symulator(Bascoma) nie chciał działać z ustawionym bitem CTC1 w rejestrze TCCR1B.Dzisiaj zrobiłem to na żywym procku i ...działa.W kodzie , który podałem wyżej wystarczy dopisać polecenie :
    Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
    zrezygnować z przerwania od "compare1a" i mamy piękny generatorek "prostokąta" z możliwością prostej regulacji częstotliwości
    :D

    Piotrek
    PS
    Żywy proc to ATMega32 ale w AVRStudio 4 też działa na 90s2313 :D
  • #12 1701648
    ko_rex
    Poziom 19  
    Posty: 253
    Pomógł: 38
    Ocena: 2
    JollyRoger, myślę, że nie powinieneś się sugerować wskazaniami tego programu do pomiaru częstoliwości za pomocą karty dźwiękowej, jesli masz do czynienia z częstotliwościami powyżej połowy częstotliwości próbkowania. Na pewni nie uda Ci się zmierzyć tych 40kHz w ten sposób.
  • #13 1703960
    JollyRoger
    Poziom 21  
    Posty: 538
    Pomógł: 21
    Ocena: 30
    ko_rex napisał:
    JollyRoger, myślę, że nie powinieneś się sugerować wskazaniami tego programu do pomiaru częstoliwości za pomocą karty dźwiękowej, jesli masz do czynienia z częstotliwościami powyżej połowy częstotliwości próbkowania. Na pewni nie uda Ci się zmierzyć tych 40kHz w ten sposób.


    Niestety to zauważyłem :(. Jeżeli chodzi o 40KhZ to narazie spróboje jeszcze to zrobić na procesorze a jak sie nie uda to zrobie na jakimś scalaku typu CD4049. Mam jeszcze jedno pytanie, jakie powinno być zasilanie dla takiego nadajnika 40Khz aby zasięg był na jakieś 1,5-2 m?
  • #14 1888979
    czaina
    Poziom 14  
    Posty: 89
    Pomógł: 2
    Ocena: 3
    Widzę że kolega szykuje robota. Ja też pracuję nad tym problemem. Generacja to jedno, siła sygnału to osobny problem. Przeanalizowałem wiele projektów i znalazłem tylko jeden sensowny. Na płytce na ogół mamy 5V, daje to słaby sygnał. Można go podwoić przełączając buforami trój stanowymi nadajnik. Teraz eksperymentuje z modułem MAX232. Jest to przetwornik RS-TTL. Daje on z 5V ok. +/- 7,5V, a że jest on podwójny bez trudu da się z niego wydusić +/- 15V.
    Do generacji polecam też NE555. Z potencjometrem i dwoma kondensatorami daje całkiem dobry sygnał.
  • #15 2048819
    JollyRoger
    Poziom 21  
    Posty: 538
    Pomógł: 21
    Ocena: 30
    Witam, a co sądzicie o tym (chyba najprostsze rozwiązanie ;) ):
    
    .include "2313def.inc"
    .def acc = r16 ;
    
    .cseg
    .org 0x00
    rjmp start
    
    start:
    
    ldi acc, 127 ;
    out SPL, acc 
    ldi acc,0
    out ocr1ah, acc
    ldi acc, 50; dla 40 khz, dla 36khz: 55
    out ocr1al,acc
    ldi acc, 0b01000000
    out tccr1a, acc
    ldi acc, 0b00001001
    out tccr1b, acc
    ldi acc, 0b11111111 ;
    out DDRB, acc
    
    costam:
    nop
    rjmp costam
    


    Konfiguracja Timer1 w trybie CTC i na wyjściu Portb.3 mamy sygnał 40kHz :)

    P.S I właśnie w takich przypadkach dostrzegam jak przydatny jest assembler.

Podsumowanie tematu

✨ Dyskusja dotyczy problemu generacji sygnału 40 kHz za pomocą mikrokontrolera AT90S2313, wykorzystywanego do nadajnika ultradźwiękowego. Autor zgłasza, że pomimo ustawienia Timer1 z prescalerem 1 i wartością porównawczą 65436, na wyjściu OC1A uzyskuje częstotliwość około 1,2 kHz zamiast oczekiwanych 40 kHz. Wskazano, że błąd wynika z niedoszacowania czasu obsługi przerwania, który wydłuża okres sygnału, co skutkuje niższą częstotliwością wyjściową. Zaproponowano wykorzystanie sprzętowego trybu PWM z ustawieniem trybu CTC (Clear Timer on Compare Match) i generowaniem sygnału prostokątnego na wyjściu, co pozwala na stabilne uzyskanie 40 kHz bez konieczności obsługi przerwań. Podano przykładowy kod w asemblerze i Bascomie, który konfiguruje Timer1 do pracy w trybie CTC z wyjściem Toggle na pinie OC1A. Zwrócono uwagę, że pomiar częstotliwości 40 kHz za pomocą karty dźwiękowej jest niewiarygodny ze względu na ograniczenia częstotliwości próbkowania. W dyskusji pojawiły się także sugestie dotyczące zwiększenia mocy nadajnika, m.in. poprzez zastosowanie buforów trójstanowych lub modułu MAX232 do podniesienia napięcia sygnału oraz alternatywne rozwiązania z wykorzystaniem układu CD4049 lub NE555. Poruszono także kwestie doboru zasilania nadajnika dla uzyskania zasięgu 1,5-2 m.
Wygenerowane przez model językowy.
REKLAMA