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.

[Atmega88][Bascom] a'la Alfabet Morsa

olaf_madej 30 Kwi 2009 02:40 1572 6
  • #1 30 Kwi 2009 02:40
    olaf_madej
    Poziom 9  

    Witam Panowie (Panie?)
    Jetem początkującym elektronikiem a tym bardziej programistą uP.
    Kiedyś lubiłem, jeszcze na Commodore, bawić się w pisanie programików w Basicu, więc jako tako znam i lubię ten język. Więc dlatego zdecydowałem się na realizację projektu w tym języku...

    O ile z samym językiem nie ma problemu, gdyż coś tam ze składni i zasad pisania pamiętam. Zaopatrzyłem się też w książkę Pana Marcina W.

    To nie za bardzo wiem jak się zabrać do realizacji tej części programu.

    Otóż Timer0 generuje mi przerwania o częstotliwości 200Hz (plus minus, gdyż korzystam z wewnętrznego oscylatora - ale dokładność nie jest tu krytyczna).
    Te 200Hz stanowi mi nośną która jest podawana na wyjście procesora, który steruje tranzystorem (kwadrat uzyskiwany przez instrukcję

    Code:
    Toggle PortB.0
    ).
    To wszystko działa jak powinno.

    Ale teraz w wywołaniu tego przerwania muszę, że tak powiem poszatkować tę nośną, aby uzyskać coś na zasadzie kropek i kresek.
    I nie wiem jak to zrealizować??? Jak zapisać (raczej w liniach danych DATA - przynajmniej tak mi się wydaje, ale co i jak tam zapisać) i później jak tę zapisaną sekwencję wykorzystać...

    Sekwencja to kilku sekundowy ciąg kresek i kropek powtarzany co kilka sekund w pętli.

    A jeszcze żeby nie było za łatwo to muszę mieć 2-3 takie sekwencje na różnych wyjściach i oczywiście każda sekwencja inna.


    Mam nadzieję iż zwykły początkujący programista może liczyć na pomoc bardziej doświadczonych programistów i znawców jeżyka Basom i procesorów Atmega.

    Pozdrawiam i z góry mocno dziękuję za wszelką udzieloną pomoc. Czy to w postaci ogólnej koncepcji rozwiązania problemu, czy gotowych kodów lub choć by ich części.

    Olaf

    0 6
  • #2 30 Kwi 2009 08:43
    sp3ots
    Poziom 35  

    Witaj Olaf !
    Po baw się rozkazem sound w bascomie.
    Czy chcesz napisać program do Becona ?
    Powodzenia życzę. Stefan

    0
  • #3 30 Kwi 2009 15:54
    olaf_madej
    Poziom 9  

    Dzięki za zainteresowanie tematem.

    Dość ciekawe rozwiązanie i nie pomyślałem o takim rozwiązaniu.
    Ale nie rozwiązuje tu problemu.
    Komenda sound działa liniowo i nie da się na raz generować różnych "tonów" na różnych końcówkach.
    A potrzebuję równolegle "pikać" na kilku końcówkach (oczywiście różne sekwencje)

    Prawdę mówiąc nie wiem co to za układ "Becona"

    Chcę zrobić massager mięśni.
    Wiem że to nie cud i cudów nie sprawi. Ale jestem osobą na wózku i używam motylka do masaży - mniej w tedy cierpnie mi mięsień.
    Ale motylek mam kilka wad - choć by to że po 5min sam się wyłącza. Mam też stary aparat, taki jeszcze w dużym pudle i z niego pożyczyłem sobie trafo którye generuje impulsy - ale za to nie ma zróżnicowania impulsów.
    W oryginale tego starego, za generowanie impulsów odpowiadał prosty generator na bramkach.
    Ja postanowiłem do tego zaprzęgnąć mikroprocesor.
    I prosty jedno liniowy masaż zastąpić różnymi programami.

    Czyli połączyć efektywność motylka z nielimitowanym czasem działania tego starego urządzenia.

    0
  • #4 30 Kwi 2009 19:35
    PiotrPitucha
    Poziom 33  

    Witaj
    Myślę że tymi 200Hz powinieneś ustawiać jakąś zmienną, w szczególnym przypadku cały bajt na 0 lub 255, niech ta zmienna nazywa się A, teraz na zmienną B wysyłasz sekwencję impulsów sterujących i po każdym przerwaniu robisz A or B i wysyłasz na port, jeśli inaczej sterujesz to może to być A and B ale z tym już sobie poradzisz, przy takiej częstotliwości możesz spokojnie uznać że wysterujesz równocześnie 8 wyjść.
    Piotr

    0
  • #5 30 Kwi 2009 21:26
    janbernat
    Poziom 38  

    Ale powiedz co to jest "motylek"?
    I dlaczego równolegle-to ma kilka elektrod?

    0
  • #6 01 Maj 2009 02:16
    olaf_madej
    Poziom 9  

    Dzięki za pomysły.

    A motylem, co to? Ot takie bździewka oferuje TVMango, Allegro i straganowi sprzedawcy.
    W kształcie to właśnie przypomina motylka. Po bokach elektrody samoprzylepne - przewodzące a pośrodku elektronika sterująca i zasilanie. One są jednokanałowe.
    To stare co mam z niego transformatory jest 2 kanałowe - 4 elektrody na przewodach.

    A wracając do oprogramowania...

    Dziś przeglądając tematy forum trafiłem na ten wątek:
    https://www.elektroda.pl/rtvforum/viewtopic.php?t=359777

    i postanowiłem wykorzystać tamtejszy opis konfiguracji Timera do generowania impulsów.
    Da mi to też szerokie pole do zmian częstotliwości generowanych impulsów.

    W Atmedze88 mam 3 zegary i postanowiłem je wykorzystać.

    Tak więc:
    Timer 0 ma liczyć czas - w programie mogę wybrać czas pracy.
    Timer 1 będzie pracował jako generator PWM, który będzie sterował mocą impulsów (plus potencjometr na wyjściu)
    Timer 2 będzie właśnie odpowiedzialny za nośną impulsów.

    W tej chwili kod piszę który sekwencyjnie zapala diody aby łatwiej wizualizować obróbkę kodu programu.

    I tak to wygląda na chwilę obecną:

    Code:

      Do
         For X = 1 To 20
             Czas_impulsu1 = Lookup(x , Program1a)
             Czas_impulsu2 = Lookup(x , Program1b)

             If Czas_impulsu1 <> 0 Then Flaga1 = 1
             If Czas_impulsu2 <> 0 Then Flaga2 = 1

             If Flaga1 = 1 Then
                Led1 = 1
                Incr I1
                If I1 = Czas_impulsu1 Then

                   I1 = 0
                   Led1 = 0
                End If
             End If

             If Flaga2 = 1 Then
                Led2 = 1
                Incr I2
                If I2 = Czas_impulsu2 Then
                   I2 = 0
                   Led2 = 0
                End If
             End If
         Waitms 10
         Next X
      Loop Until Minuty = 0 And Sekundy = 0



    W skrócie wygląda pętla tak: Zapalam diodę. Pobieram daną wartość Czas_impulsu, dla danego kanału z linii DATA i porównuję ze zwiększaną co 10ms wartością I jeżeli wartości obie się zgadzają dioda jest gaszona.
    Na początku sprawdzany jest też warunek, czy pobrana wartość jest różna od zera - zera chciałem zarezerwować na przerwy.
    cała pętla powtarza się 20 razy, gdyż w tej chwili mam wpisanych tyle wartości w DATA.
    Całość jest wykonywana dopóki nie skończy się czas ...

    No właśnie i tu jeszcze mam mały problem. Długość przerwy między czasem w którym doda się pali ograniczona jest do tych 10ms ustalających częstotliwość powtarzania pętli...

    Na początku sprawdzane jest czy pobrana dana danego kanału nie jest zerem ale nie potrafię tego wykorzystać.
    Gdy wstawię w warunku na przykład Jeżeli wartość to 0 odczekaj xx ms to zablokuje mi to przejście dalej i wykonanie operacji na drugim kanale do czasu zakończenia tej przerwy. A tego nie chcę....

    Oczywiście w tej chwili procedura pracuje na zasadzie włącz/wyłącz diodę ale ostatecznie być tam włącz/wyłącz TIMER.

    Może jeszcze coś w związku z tym zaproponujecie? Będę wdzięczy...

    Pozdrawiam serdecznie

    0
  • #7 01 Maj 2009 18:25
    olaf_madej
    Poziom 9  

    Pozwolę sobie zamieścić to co udało mi się w nocy i dziś wymodzić.

    Code:

      Do
    ' ------------------------------------ Pierwszy kanał ----
         If Flaga1 = 1 Then                                     ' sprawdź flage1 - dla WLACZ
            If I1 = Czas_impulsu1 Then                          ' porównaj liczbe ms z DATA dla WLACZ
               I1 = 0                                           ' wyzeruj licznik ms
               Toggle Flaga1                                    ' przestaw flage1
               Toggle Led1                                      ' przelacz diode (traznystor)
               Incr X : If X = 20 Then X = 0                    ' przesun lub wyzeruj znacznik dla DATA
               Czas_impulsu1 = Lookup(x , Program1a)            ' pobierz mową daną z DATA dla WLACZ
            End If
         Else                                                   ' sprawdź flage1 - dla WLACZ
            If I1 = Czas_impulsu1 Then                          ' porównaj liczbe ms z DATA dla WYLACZ
               I1 = 0                                           ' wyzeruj licznik ms
               Toggle Flaga1                                    ' przestaw flage1
               Toggle Led1                                      ' przelacz diode (traznystor)
               Incr X : If X = 20 Then X = 0                    ' przesun lub wyzeruj znacznik dla DATA
               Czas_impulsu1 = Lookup(x , Program1a)            ' pobierz mową daną z DATA dla WYLACZ




            End If
         End If
    ' -------------------------------------- Drugi kanał ------
    ...

    ' ----------------------------------- Dokonczenie procedur -
         Waitms 1                                               ' odczekaj 1ms
         Incr I1                                                ' zwieksz liczniki ms dla obu kanalow
         Incr I2

      Loop Until Minuty = 0 And Sekundy = 1                     ' powtarzaj dopuki minuty i sekundy na 0


    Kod działa. Nie wiem, może można to zrobić ładniej lub czytelniej. Ale tak umiałem i tak działa.
    Oba kanały działają niezależni od siebie.

    Działa to tak:
    W liniach data na przemian zapisane są wartości dla czasu włączenia i czasu wyłączenia Wartości zapisane są w ilości milisekund (nie wiem tylko dlaczego gdy w DATA mam "0" to program się zatrzymuje?? Tymczasowo zastąpiłem ewentualne "0" 1ką, Choć oczywiście dane są na razie tylko orientacyjne aby coś migało).
    Procedura sprawdza flagę jeżeli "1" to pobrana dana tyczy się włączenia diody, gdy "0" tyczy się czasu wyłączenia. Następnie porównuje pobraną daną z zwiększanym licznikiem (licznik zwiększa się co 1ms, tak więc odczytana dana odpowiada liczbie sekund danego stanu diody). Gdy licznik osiągnie wartość pobranej danej, licznik ms jest zerowany, zmienia się stan flagi i pobierana jest nowa dana z DATA (linie danych DATA są osobne dla obu kanałów).

    Drugi kanał wygląda analogiczne z pierwszym.
    Cała pętla jest wykonywana do chwili gdy zeruje się licznik czasu działania.

    Uff i to mam już z głowy :)

    Teraz muszę jeszcze zapisać dane dla zmiany PWM w czasie. Ale to już nie powinno być problemem. Gdyż opierać będzie się w analogiczny sposób dla danego kanału.
    Wydaje mi się iż ten stan nie musi być zmieniany częściej niż co 100ms, dla jakiejś tam płynności. A w razie czego, zawsze można to zmienić.

    Oczywiście gdyby ktoś miał jakieś sugestie czy pomysły z chęcią je przyjmę.
    Wiedzy i rad bardziej doświadczonych fachowców nigdy za dużo.
    Pozdrawiam

    0