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

Jak zaprogramować generator impulsów 1-20Hz na ATmega8 w Bascom?

tomekz9 30 Sty 2008 19:59 3957 12
REKLAMA
  • #1 4753194
    tomekz9
    Poziom 13  
    Posty: 58
    Pomógł: 2
    Ocena: 15
    Witam,
    Z góry przepraszam za lamerskie pytanie, to moje początki, ale od trzech dni szukam w necie jakiegoś przykładu w Bascomie i nic.
    Mam atmega8-16PI, kwarc 8MHz
    Potrzebuję wykonać generator impulsów (prostokąt) o regulowanych częstotliwościach, 1-20Hz, oraz regulowanym czasie trwania impulsów 0,1-3ms. Nie wiem jak się do tego zabrać. Załużmy że długość trwania impulsów mógłbym regulować współczynnikiem wypełnienia ( procedura dla dwóch przycisków up/down, następnie wpisanie wartości do zmiennej Pwm1a ), to jeśli chodzi o częstotliwość, to nie mam pojęcia jak ją regulować. Czy mam dopisać procedurę kolejnych dwóch klawiszy i regulować nimi prescaler? Czy może istnieje jakiś inny sposób? Nie wiem czy z wypełnieniem też dobrze rozumuję. Jak uzyskać takie niskie częstotliwości?
    Pozdrawiam
    tom
  • REKLAMA
  • #2 4753362
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    nie widze nic trudnego w tym co masz do zrobienia.

    tragiczne jednak jest to, ze skoro w bascomie nie ma gotowej funkcji generuj_pwm(czestotliwosc,wypelnienie), to juz raczej w ogole nie da rady tego zrobic...

    0x41 0x56 0x45!!
  • #3 4753888
    tomekz9
    Poziom 13  
    Posty: 58
    Pomógł: 2
    Ocena: 15
    Wierzę, że nie widzisz w tym nic trudnego, ja pewnie niewidziałbym nic trudngo w wielu rzeczach, o których ty nie masz zielonego pojęcia,
    a tragiczne są takie posty, ale widzę że w twoim przypadku jest to reguła, masz prawie 200 podobnych.:!:
  • REKLAMA
  • #4 4753971
    Lysoleq
    Poziom 17  
    Posty: 264
    Pomógł: 25
    Ocena: 12
    Przykładowo możesz wykorzystać dwa liczniki. Jeden do regulacji częstotliwości, a drugi do regulacji wypełnienia.

    - licznik pierwszy odlicza czas pomiędzy okresami od 1 sek dla 1Hz do 50 ms przy 20Hz.

    - licznik drugi oblicza czas trwania impulsu.

    Powiedzmy że zmiana stanu pinu X generuje przerwanie uruchamiające licznik drugi który po upływie zaprogramowanego czasu zmieni stan pinu i wyłączy przerwania PCINT, wyzeruje i zatrzyma licznik. Natomiast licznik drugi po upływie zaprogramowanego czasu uruchamia ponownie PCINT. I masz prosty generator regulujący szerokość impulsu, oraz częstotliwość.
  • REKLAMA
  • #5 4754033
    tomekz9
    Poziom 13  
    Posty: 58
    Pomógł: 2
    Ocena: 15
    Dzięki,
    zaraz spróbuję coś takiego sklecić
  • #6 4754163
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witaj.
    Skądś znam ten problem, ktoś mnie o coś takiego prosił. Tyle, że wartości częstotliwości i wypełnienia były ustawiane potencjometrami.
    Programik był napisany na ATtiny26, wartości częstotliwości i wypełnienia nieco sie różnią, ale możesz sobie to zmienić. Programik testowałem (ale bez oscyloskopu). W razie błędów proszę o łagodny wymiar kary :)
    
    '-------------------------------------------------------------------------------
    ' Układ ma generować impulsy o zmiennej długości - od 0,03ms do 3ms
    ' i zmiennej częstotliwości - od 20Hz do 80Hz
    ' Potencjometry włączone są między zasilanie a masę, suwak pot. regulacji
    ' częstotliwości podpięty do ADC0, suwak pot. regulacji długości impulsu
    ' podpięty do ADC1. Potencjometr reg. częstotliwości ma być tak podłączony
    ' aby przy skrajnym, lewym położeniu suwaka napięcie na AIN0 było maksymalne.
    ' Potencjometr reg. długości czasu impulsu - odwrotnie. Wtedy przekręcając potencjometry
    ' w prawo będziemy zwiększać częstotliwość i czas impulsu
    ' Wartości Prescale oraz współczynniki  przy liczeniu wartości
    ' wprowadzanych do timerów wynikają z prędkości taktowania ATtiny26 oraz założonych
    ' czasów i częstotliwości. Impulsy wyjściowe pojawiają się na końcówce PORTB.0
    ' ATtiny26 taktowany jest z wewnętrznego oscylatora RC z częstotliwością 4MHz
    ' Układ czyta nastawy potencjometrów około 4 razy na sekundę.
    ' Programik "popełnił" teedd - styczeń 2008
    '-------------------------------------------------------------------------------
    $regfile = "ATtiny26.dat"
    $crystal = 4000000
    $hwstack = 32                                               ' default use 32 for the hardware stack
    $swstack = 10                                               'default use 10 for the SW stack
    $framesize = 40                                             'default use 40 for the frame space
    Config Watchdog = 1024                                      '512 też jeszcze działa
    Config Timer0 = Timer , Prescale = 1024
    Config Timer1 = Timer , Prescale = 64
    Stop Timer1
    On Timer0 Start_impuls
    On Timer1 Stop_impuls
    Enable Interrupts
    Enable Timer0
    Enable Timer1
    Config Pinb.0 = Output
    Reset Portb.0
    Config Adc = Single , Prescaler = Auto
    Start Adc
    Dim Czestotliwosc_impulsu As Single , Dlugosc_impulsu As Single , Pomiar As Word
    Dim Czestotliwosc As Byte , Dlugosc As Byte
    Start Watchdog
    
    Do
    Pomiar = Getadc(0)
    Pomiar = Getadc(0)                                          'ponoć lepiej 2 razy
    Czestotliwosc_impulsu = Pomiar
    Czestotliwosc_impulsu = Czestotliwosc_impulsu / 7
    Czestotliwosc_impulsu = Int(czestotliwosc_impulsu)
    Czestotliwosc_impulsu = Czestotliwosc_impulsu + 61
    If Czestotliwosc_impulsu > 207 Then Czestotliwosc_impulsu = 207
    Czestotliwosc = Czestotliwosc_impulsu
    
    Pomiar = Getadc(1)
    Pomiar = Getadc(1)                                          'ponoć lepiej 2 razy
    Dlugosc_impulsu = Pomiar
    Dlugosc_impulsu = Dlugosc_impulsu * 3
    Dlugosc_impulsu = Dlugosc_impulsu / 16
    Dlugosc_impulsu = Int(dlugosc_impulsu)
    Dlugosc_impulsu = Dlugosc_impulsu + 68
    If Dlugosc_impulsu > 254 Then Dlugosc_impulsu = 254
    Dlugosc = Dlugosc_impulsu
    
    Reset Watchdog
    Waitms 250
    Loop
    
    Start_impuls:
    Load Timer0 , Czestotliwosc
    Tcnt1 = Dlugosc
    Set Portb.0
    Start Timer1
    Return
    
    Stop_impuls:
    Reset Portb.0
    Stop Timer1
    Return
    
    End
    
    


    Pozdrowienia - teedd
  • REKLAMA
  • #7 4762023
    tomekz9
    Poziom 13  
    Posty: 58
    Pomógł: 2
    Ocena: 15
    Dzięki teedd
    To naprawdę działa, jeszcze nie wiem jak z częstotliwościami, nie miałem możliwości zmierzyć, dopiszę jeszcze obsługę lcd, tylko jeśli mógłbyś mnie jeszcze oświecić jak przeliczyć to co ma się pojawiać na wyświetlaczu?
    Jeszcze raz wielkie dzięki
    Pozdrawiam
    tom
  • #8 4762102
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witaj.
    Ale napisz co chcesz wyświetlać na wyświetlaczu? ;)
    teedd
  • #9 4762340
    tomekz9
    Poziom 13  
    Posty: 58
    Pomógł: 2
    Ocena: 15
    WITAM,
    Chciałbym wyświetlać to co jest nastawione, czyli w jednej linii nastawioną częstotliwość w Hz, a w drugiej czas trwania impulsu w mS.
  • #10 4764099
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witaj.
    Postaram się w miarę szybko wyjaśnić algorytm działania programu.
    Procesor jest taktowany z częstotliwością 4MHz, i ta częstotliwość jest dzielona przez 1024 w preskalerze timera 0 - na wejściu timera 0 mamy impuls co 0.256 ms. Timer 0 jest tak skonfigurowany, że wywołuje przerwanie po jego przepełnieniu. Chcemy mieć przerwania z regulowaną częstotliwością między 20Hz a 80Hz (okres 50ms do 12.5ms) - czyli musimy odmierzyć około od 49 do 195 impulsów. Ponieważ timer0 wywołuje przerwanie przy przepełnieniu (to jest licznik 8 bitowy), więc musimy do niego załadować takie wartości, aby po ich odliczeniu było wywołane przerwanie. A więc:
    256-195=61
    256-49=207
    Wartość odczytana z przetwornika A/D jest 10 bitowa - wartości od 0 do 1023. Aby wykorzystać pełny zakres regulacji potencjometru, dzielę wynik przez 7, a potem kombinuję :)
    Reasumując: odmierzaną ilość impulsów=256 - Czestotliwosc (czyli od 49 do 195) przemnóż przez 0.000256, a potem zrób z tego odwrotność i będziesz miał gotową wartość częstotliwości do wyświetlenia.
    W przypadku timera 1 sprawa jest analogiczna.
    Gdybyś chciał zmieniać częstotliwości w większym zakresie (w moim przypadku było to 80Hz/20Hz=4), to może Ci się to nie udać (lub nie dać zadowalających wyników) ze względu na "dyskretny" charakter zmian (ten dyskretny tak mi się nawinął, ale chyba to właściwe słowo w tym miejscu?). W takim przypadku ja bym użył prostego, zewnętrznego generatora regulowanego potencjometrem - ale tego nie da się zrobić na ATtiny26. Ale na ATmega8 tak
    Pozdrowienia - teedd
  • #11 4787243
    tomekz9
    Poziom 13  
    Posty: 58
    Pomógł: 2
    Ocena: 15
    Witam,
    przerobiłem nieco program kol. Teedd, pod swój mikrokontroler i kwarc, niby działa, ale nie mam regulacji częstotliwości, reguluje mi tylko wypełnienie, kończą mi się pomysły..

    $regfile = "m8def.dat"
    $crystal = 8000000
    $hwstack = 32 ' default use 32 for the hardware stack
    $swstack = 10 'default use 10 for the SW stack
    $framesize = 40 'default use 40 for the frame space
    Config Pinb.1 = Output
    Reset Portb.1
    Enable Interrupts
    Enable Timer0
    Enable Timer1
    Config Watchdog = 1024 '512 też jeszcze działa
    Config Timer0 = Timer , Prescale = 256
    Config Timer1 = Timer , Prescale = 64
    Stop Timer0
    On Timer1 Start_impuls
    On Timer0 Stop_impuls
    Config Adc = Single , Prescaler = Auto , Reference = Internal
    Start Adc
    Dim Czestotliwosc_impulsu As Single , Dlugosc_impulsu As Single , Pomiar As Word
    Dim Czestotliwosc As Byte , Dlugosc As Byte
    Start Watchdog

    Do
    Pomiar = Getadc(0)
    Pomiar = Getadc(0) 'ponoć lepiej 2 razy
    Czestotliwosc_impulsu = Pomiar
    Czestotliwosc_impulsu = Czestotliwosc_impulsu * 7
    Czestotliwosc_impulsu = Int(czestotliwosc_impulsu)
    Czestotliwosc_impulsu = Czestotliwosc_impulsu + 58195
    If Czestotliwosc_impulsu > 65146 Then Czestotliwosc_impulsu = 65146
    Czestotliwosc = Czestotliwosc_impulsu

    Pomiar = Getadc(1)
    Pomiar = Getadc(1) 'ponoć lepiej 2 razy
    Dlugosc_impulsu = Pomiar
    Dlugosc_impulsu = Dlugosc_impulsu * 3
    Dlugosc_impulsu = Dlugosc_impulsu / 16
    Dlugosc_impulsu = Int(dlugosc_impulsu)
    Dlugosc_impulsu = Dlugosc_impulsu + 68
    If Dlugosc_impulsu > 253 Then Dlugosc_impulsu = 253
    Dlugosc = Dlugosc_impulsu

    Reset Watchdog
    Waitms 250
    Loop

    Start_impuls:
    Timer1 = Czestotliwosc
    Set Portb.1
    Timer0 = Dlugosc
    Start Timer0
    Return

    Stop_impuls:
    Reset Portb.1
    Stop Timer0
    Return

    End
  • #12 4787531
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witaj.
    Tak na pierwszy rzut oka, to podejrzewałbym sposób ładowania wartości Czestotliwosc do Timera1. Nie na darmo robiłem to inaczej w moim przykładzie.
    Ponieważ nie mogę tego sprawdzić w tej chwili, a Bascomem zajmuję się od czasu do czasu (a i skleroza swoje robi :) ), więc radzę Ci to sprawdzić.
    Pozdrowienia - teedd
  • #13 4792040
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witaj.
    Zajrzałem do helpa -
     Timer1=Czestotliwosc

    jest prawidłową instrukcją.
    Wcześniej masz -
    Dim Czestotliwosc As Byte 

    a później operujesz na 16-bitowym Timerze1. W ATtiny26 Timer1 jest 8-bitowy, ale w Mega8 już 16-bitowy.
    Zmień na -
    Dim Czestotliwosc As Word 

    i sprawdź rezultat.
    teedd

Podsumowanie tematu

✨ Dyskusja dotyczy programowania generatora impulsów prostokątnych o regulowanej częstotliwości 1-20 Hz oraz regulowanym czasie trwania impulsów 0,1-3 ms na mikrokontrolerze ATmega8 z kwarcem 8 MHz w języku Bascom. Proponowane rozwiązania obejmują wykorzystanie dwóch liczników (timerów): jeden do regulacji częstotliwości impulsów, drugi do regulacji szerokości impulsu (wypełnienia). Sugerowano obsługę przerwań i odpowiednie ładowanie wartości do timerów, aby uzyskać niskie częstotliwości. Przykładowy kod bazujący na pomiarach ADC z potencjometrów do regulacji parametrów został udostępniony i przystosowany do ATmega8. Omówiono także sposób przeliczania wartości do wyświetlania na LCD, gdzie częstotliwość i czas trwania impulsu są prezentowane w Hz i ms. Wskazano na konieczność odpowiedniego typu zmiennych (np. Word zamiast Byte) dla 16-bitowego timera w ATmega8 oraz poprawne ładowanie wartości do rejestrów timerów. Dyskusja zawierała także uwagi dotyczące konfiguracji prescalerów i przerwań w Bascomie, co jest kluczowe dla uzyskania stabilnych i regulowanych niskich częstotliwości impulsów.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA