Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

ATTiny2313A - C - Program do obsługi diod przez przyciski monostabilne.

m_hauf 04 Sty 2016 10:45 1131 9
  • #1 04 Sty 2016 10:45
    m_hauf
    Poziom 9  

    Witam,
    Od kilku dni walczę z pewnym problemem. Szukałem rozwiązań w różnych źródłach, na różnych stronach, w rożnych książkach i poradnikach... Jednak wszystkie wykonywane przeze mnie operacje nie przynoszą pożądanego rezultatu...
    Przyznam się bez bicia, że mam za sobą już bardziej zaawansowane projekty, ale jak widać, najtrudniejsze do rozwiązania są pozornie najprostsze zadania... :cry:

    Moim zadaniem jest zbudowanie układu złożonego z dwóch diod LED oraz dwóch przycisków monostabilnych.

    Przycisk monostabilny powinien wywoływać zmianę stanu (zliczanie). Dla wartości parzystych powinien ustawiać odpowiednie wyjście na stan wysoki, dla wartości nieparzystych powinien podawać stan niski.

    Program na spełniać następujące warunki:
    Jeśli przycisk 1 wciśnięty - zapal LED 1
    ponowne wciśnięcie przycisku 1 - zgaś LED 1 (symulacja przycisku bistabilnego)
    Jeśli przycisk 2 wciśnięty - zapal LED 2
    ponowne wciśnięcie przycisku 2 - zgaś LED 2 (symulacja przycisku bistabilnego)

    (powyższe można ewentualnie zastąpić przyciskami bistabilnymi, ale odgórnie narzucono aby było to zrealizowane na przyciskach monostabilnych...)

    Ponadto:
    Równoczesne świecenie obu diod jest zabronione, czyli wciśnięcie jednego przycisku wyłącza drugą diodę i odwrotnie.

    TABELA PRAWDY
    ATTiny2313A - C - Program do obsługi diod przez przyciski monostabilne.

    Schemat działania można rozpisać w postaci programu drabinkowego, jednak nawet to nie pomaga. Próbowałem wielu wariantów i uzyskałem pewien nie do końca satysfakcjonujący mnie efekt. Mianowicie, program cały czas realizuję operację bitową (zliczanie bitów) kiedy ja tylko chciałbym zmieniać poszczególne stany pomiędzy 0 i 1. Próbowałem wykonać to na zmiennych globalnych uzależniając od nich działanie diody, ale wtedy pojawiał się problem związany z instrukcjami warunkowymi. Gdy program wszedł do jednego ifa, to już tam zostawał, miast wrócić na początek ;/ żadne funkcje switch-case, przerwania, nawet nieszczęsne goto itp nie dawały pożądanego rezultatu.

    Działanie programu wygląda w praktyce na zliczanie bitów (przyciski wykazują zmianę stanu dopiero po kilkukrotnym wciśnięciu) dla przykładu, poniższy program dla wciskanego przycisku nr 1 zmienia stany w następujący sposób:

    ATTiny2313A - C - Program do obsługi diod przez przyciski monostabilne.

    a dla dla wciskanego przycisku nr 2 zmienia stany w następujący sposób:
    ATTiny2313A - C - Program do obsługi diod przez przyciski monostabilne.

    Choć dla mnie to i tak zbytni chaos.
    Próbuję zrealizować program, który będzie zliczał ilość wciśnięć przycisku i w zależności, czy jest to wciśnięcie nieparzyste ustawi stan wysoki lub jeśli jest to wciśnięcie parzyste ustawi stan niski.

    Przeanalizowałem następujące wątki:
    Włączanie i wyłączanie diody za pomocą jednego przycisku

    Wzorowałem się również na tym kodzie:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tu mój kod w obecnej postaci:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Naprzemienne wciskanie przycisków, powoduje totalny chaos... Nie wiem już jak podejść do tego tematu. Może ktoś z Was, spojrzy na to "świeżym okiem" i dostrzeże coś, co cały czas umyka mojej uwadze.

    Pozdrawiam :)

    Moderowany przez tmf:

    Poprawiłem tytuł - C++ to nie C

    0 9
  • #2 04 Sty 2016 11:08
    dr.hannibal
    Poziom 22  

    A może jest to kwestia drgań przycisków? - niby konkretnie wciskamy dany przycisk, a gdyby obejrzeć pod oscyloskopem stan danych pinów to pokazały by się "szpilki" zamiast ładnego zbocza opadającego/narastającego. Problem raczej dość powszechny ;)
    Można programowo to próbować skorygować, np:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Sorki jeśli są jakieś błędy w kodzie - pisałem na szybko z głowy, generalnie chodzi o to aby stan wejścia ładować sobie na najmłodszy bit zmiennej, następnie robimy przesunięcie bitowe zmiennej w lewo... i tak w kółko. W efekcie zmienna przechowuje 16 ostatnich stanów wejścia - co pozwala eliminować drgania przez szukanie wartości 0xFFFF i 0x0000 i odrzucanie wszystkich innych.

    0
  • #3 04 Sty 2016 11:19
    szczywronek
    Poziom 27  

    Czołem!
    Może to kwestia minionego Sylwestra, ale nie bardzo rozumiem co ten program właściwie ma robić:
    1) najpierw piszesz o zliczaniu (rozumiem, że wciśnięć)
    2) we fragmencie "Program na spełniać następujące warunki:" piszesz, że ma (w uproszczeniu) symulować dwa przyciski bistabilne + pilnować aby obie diody się nie świeciły jednocześnie
    3) z tabeli prawdy rozumiem, że odpowiednie diody mają się świecić gdy odpowiadające im przyciski są wciśnięte i gasnąć po puszczeniu (czyli już nie bistabilne)
    Więc jak to w końcu ma być? :)

    -------
    I tak jeszcze a propos Twojego kodu kilka takich luźnych... czepialstw:
    1. Nie definiuj F_CPU w kodzie programu: lektura
    2. Unikaj "magicznych" liczb w kodzie programu, i staraj się nie mieszać systemów liczbowych.
    3. Zerowanie wyzerowanych rejestrów nie ma większego sensu :)
    4. Przemyśl te linijki, bo one raczej nie robią tego co sugeruje komentarz:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    5. Skoro zmienne AA i AG przyjmują tylko stan 0/1 to nie ma sensu stosować typu int.

    0
  • #4 04 Sty 2016 11:28
    BlueDraco
    Specjalista - Mikrokontrolery

    Jeśli naciśniemy oba przyciski po 6 razy, to LED1 ma równocześnie świecić i nie świecić - to dopiero jest wyzwanie dla programisty!

    A tak poważniej, to rada standardowa: zacznij od przerwania timera 100 Hz (jak często trzeba to powtarzać?).

    0
  • #5 04 Sty 2016 12:09
    m_hauf
    Poziom 9  

    dr.hannibal - weryfikowałem to pod kątem drgań przycisków wymieniając je po prostu na inne, albo dłużej przytrzymując. Problem mimo wszystko występował. Nie mam możliwości sprawdzenia tego na oscyloskopie, ale o drganiach przycisków też dużo się naczytałem... dzięki za program - próbowałem już i tego sposobu jednak jak pisałem - nie wiem z czego to wynika, ale przy takiej kombinacji wielu IFów, program po wejściu do pierwszego wywołanego IFa nie wychodzi z niego... :cry:

    szczywronek - pisałem o podchodzeniu do tematu na rożne sposoby. A ogólna zasada działania jest zaprezentowana w programie (dość przejrzysty kod z warunkami dla IFów):

    jeśli AA wciśnięty (i puszczony) i AG niewciśnięty: LED AA świeci, LED AG nie świeci
    jeśli AA ponownie wciśnięty (i puszczony) i AG niewciśnięty: LED AA gaśnie, LED AG nie świeci

    jeśli AA niewciśnięty i AG wciśnięty (i puszczony): LED AA nie świeci, LED AG świeci
    jeśli AA niewciśnięty i AG ponownie wciśnięty (i puszczony): LED AA nie świeci, LED AG gaśnie

    jeśli LED AA świeci i AG zostaje wciśnięty (i puszczony) : LED AA gaśnie, zapala się LED AG
    jeśli LED AG świeci i AA zostanie wciśnięty (i puszczony): LED AG gaśnie, zapala się LED AA


    Diody świecą lub są wygaszone cały czas do momentu zmiany stanu (do wciśnięcia przycisku)

    idea jest taka by za pomocą przycisków monostabilnych stworzyć układ działający jak opisałem powyżej. Tzn, wciśnięcie przycisku (i puszczenie go) zmienia stan na przeciwny (stan na danym wyjściu się utrzymuje - coś jak samopodtrzymanie). Ponowne wciśnięcie przycisku (i puszczenie go) ponowna zmiana stanu na przeciwny, na takiej samej zasadzie.

    Co do samego definiowania F_CPU - kompilator (AtmelStudio 6) wyrzuca warrning jeśli tego nie umieszę. Kompilacja programu w takiej postaci jaką zaprezentowałem nie generuje żadnych warrningów, ani errorów.

    BlueDraco - Może i wygląda to komicznie, ale Twój wniosek jest błędny :D Tabele przedstawiają zmiany stanów dla wciśnięcia tylko jednego przycisku. W momencie tworzenia kombinacji wciskania naprzemiennego przycisków zaczyna się totalny chaos (tzn, że jeśli wcisnę przycisk 1, a później wcisnę przycisk 2, to ponowne wciśnięcie przycisku 1 da inny stan na wyjściach LED niż podałem to w tabeli - problem z realizacją funkcji "jak świeci LED AA i wciskam AG, to ma zgasnąć LED AA i zapalić się LED AG").

    Przyznam się, że na początku swoich rozważań zastanawiałem się nad wykorzystaniem Timera, ale miałem nadzieję, że da radę to jakoś łatwiej/szybciej obejść. Dzięki, że zwróciłeś mi na to uwagę :)

    0
  • #6 04 Sty 2016 12:22
    BlueDraco
    Specjalista - Mikrokontrolery

    Jak widać masz wykrywać naciśnięcie (zmianę stanu przycisku w przerwaniu timera i po wykryciu zmieniać stan automatu, a zapalać diody w zależności od stanu automatu. 2 linijki kodu na wykrywanie i zmianę stanu plus jedna na zapalanie diod z wektora - razem 4 linie kodu w przerwaniu timera (dla jednego przycisku, dla dwóch pewnie z 8).

    1
  • Pomocny post
    #7 04 Sty 2016 13:04
    szczywronek
    Poziom 27  

    @m_hauf - wymiana switchy tudzież "dłuższe" ich przytrzymywanie to sposoby walki z drganiami z góry skazane na porażkę ;)

    m_hauf napisał:
    ogólna zasada działania jest zaprezentowana w programie
    Tylko, że taka parada ifów nie zachęca do analizowania.

    m_hauf napisał:
    Kompilacja programu w takiej postaci jaką zaprezentowałem nie generuje żadnych warrningów, ani errorów.
    Jeśli usuniesz z programu białe znaki (pomijam kwestię komentarzy i preprocesora) to też się skompiluje bez ostrzeżeń, ale to nie znaczy że to dobry pomysł ;)

    BlueDraco napisał:
    dla dwóch pewnie z 8
    Co prawda powstało przed Twoim postem, ale... nie zmieściłem się :cry:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    [Autorem kodu odpowiedzialnego za obsługę przycisków jest kolega BlueDraco - kiedyś pokazał to rozwiązanie na forum - ja tylko podpatrzyłem ;)]

    0
  • #8 04 Sty 2016 13:11
    m_hauf
    Poziom 9  

    Właśnie zastanawiało mnie jaki był pomysł BlueDraco na upchnięcie tych wszystkich IFów w 8 linijkach kodu. Samych warunków jest 6 Sprawdzanie stanu bitu i zmienianie go na stan przeciwny można zrobić nawet w jednej linii, ale zmiana stanu bitu na przeciwny ma się nijak to If'a sprawdzającego stan na danym pinie (np.: AA włączony) i porównującego ten stan z wartością początkową (czy jeśli włączony AA to stan wysoki na LED AA) oraz z wartością na innym pinie (czy stan wysoki przed wciśnięciem AA występował na wyjściu AG czy może był tam stan niski?). Tu warunek wydaje mi się musi być bardziej rozbudowany aby generować właściwą odpowiedź na wyjściu.

    szczywronek - dzięki za wskazówki. Zaraz zobaczę jak to będzie się sprawdzało w praktyce.

    ///EDIT
    szczywronek
    Coś tam działa, ale..
    Taki stan też udało mi się już osiągnąć.
    - Po uruchomieniu programu obie diody się świecą
    - Cały czas brak spełnienia dwóch warunków:
    1. Po uruchomieniu sekwencji niemożliwe jest do uzyskania dwóch jednocześnie wygaszonych diod, ponieważ...
    2. Jeśli wciskam np.: przycisk AA i zapala się LED AA, to ponowne jego wciśnięcie (przy wygaszonym LED AG) powinno tylko wygasić LED AA, a to przełącza stan pomiędzy LED AA (wygasza), a LED AG (zapala) i tak w kółko, co powoduje problem nr 1...

    Dzięki za pomoc, popróbuję jeszcze coś z tym porobić. Dam znać o postępach.

    0
  • #9 04 Sty 2016 14:41
    szczywronek
    Poziom 27  

    Nie może być - u mnie działa :) Pozmieniałeś wszystkie PINy/PORTy zgodnie z Twoim hardware'em? Diody masz podłączone od mikrokontrolera do masy? U mnie ATtiny chodzi na 8MHz - jeżeli masz inną częstotliwość to musisz poprawić inicjalizację timera, żeby miało to ręce i nogi ;)

    0
  • #10 05 Sty 2016 09:39
    m_hauf
    Poziom 9  

    Tak, konfigurację pinów dostosowałem odpowiednio do hardweru, ale przez niedopatrzenie zostawiłem diody zwarte do + a nie do masy :) rzeczywiście wszystko chodzi jak należy na 8Mhz.

    Dzięki ogromne za pomoc :) Problem został rozwiązany!

    0