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

Dwa programy uruchamiane z dwóch przycisków

25 Wrz 2017 19:58 1500 30
  • BotlandBotland
  • Poziom 21  
    Witam
    Dodaj zmienną,która będzie pamiętała, który przycisk był wciśnięty. Zamiast przyciskami wywoływać programy zapamiętuj wartość zmiennej, a wywołanie programów rób po przez zmienną pamiętającą jaki był wciśnięty przycisk.
    Pozdrawiam.
  • Poziom 13  
    Jak możesz napisać taki kod nie rozumiejąc zmiennych? :D

    Co np. to według Ciebie jest?
    Kod: c
    Zaloguj się, aby zobaczyć kod

  • Poziom 28  
    Możesz to zrobić np. tak :

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Przy tym kodzie żaden program nie ruszy, dopóki nie naciśniesz odpowiedniego przycisku. Zwróć jedynie uwagę na to, że wykorzystujesz funkcje delay() i to z dużymi czasami ( 1000ms czyli jedna sekunda ). Podczas tego opóźnienia układ nie będzie reagował na przyciski ! Spójrz na przykłady do arduino : Blink without delay. Ponadto - jak masz podłączone przyciski? Zwierają piny 2 i 3 do masy ( GND ) ? Jeśli tak, to czy masz zewnętrze rezystory podciągające te piny do zasilania ( VCC ) ? Jeśli nie, to musisz zmienić :
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • BotlandBotland
  • Poziom 15  
    Próbowałem różnych wariantów, podpatrując inne programy i dodając ich części do mojego ale to zawsze wychodziło na to samo.
    Program tylko raz się uruchamiał po naciśnięciu danego przycisku.

    Dodano po 3 [minuty]:

    Rezystory podciągające mam.
    Używam ATtiny13A z programatorem.
    Arduino uno leże sobie spokojnie w szawce.
  • Pomocny post

    Poziom 28  
    Tak, bo nie zapamiętywałeś stanu przycisku. A najlepiej zrobić to zmienną pomocniczą, tzw. flagą której stan zmieniasz np. przyciskami a które sterują wykonywaniem funkcji ( "podprogramów " ).
    Niestety jeśli w kodzie będziesz miał nadal te delay(1000) , to zauważysz, że przyciski nie zawsze reagują na przyciśniecie - dlatego, że podczas każdego "delay(1000)" mikrokontroler "nie robi nic" przez sekundę ( to duże uproszczenie ale na potrzeby tego prostego programu można przyjąc że tak jest ). Więc nie bedzie nawet reagował na przyciski.

    Lepiej wprowadzić sobie jakiś prosty licznik czasu, który po zliczeniu np do sekundy, będzie zwiększał dodatkowo wprowadzoną zmienną o 1. Wtedy kolejne diody zapalasz gdy ta zmienna osiąga 1, 2, 3 , 4 itp.....
    Tym sposobem nie blokujesz mikrokontrolera i wszystko dziala jak potrzeba. We wspomnianym przykładzie z IDE Arduino zobaczysz jak można to zrobić.
  • Poziom 15  
    Rzeczywiście czas reakcji jest dość duży i postaram się to jakoś poprawić .
    Na razie trochę poprawiłem program aby było to dla mnie bardziej zrozumiałe.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 35 [minuty]:

    Kombinowałem z tym Blink without delay ale przy kompilacji mam błąd:

    Dwa programy uruchamiane z dwóch przycisków

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 30 [minuty]:

    Dość ciężko jest zrozumieć program bez tłumaczenia ale to powinno podsunąć innym pomysł na jego zrozumienie.
    Wykorzystałem tłumacza Google.

    [code]
    Kod: c
    Zaloguj się, aby zobaczyć kod

  • Poziom 28  
    Błąd pojawiał się, gdyż trochę namieszałeś z nawiasami klamrowymi zamykającymi : } :) Ponadto funkcje warunkowe if wyrzuciłeś z pętli głównej loop() a muszą tam zostać by program mógł działać poprawnie. Ponadto uporządkowałem trochę zmienne i piny - do tej pory korzystałeś z pinów 0 i 1 dla swoich diod led i tak tez zostawiłem w programie. Zmienna ledPin z przykładu nie jest potrzebna.
    Idziesz w dobrą stronę - jeszcze tylko wykombinować jak wyrzucić delay(30) z podprogramu 2 i bedzie elegancko :)
    Jeszcze dwie rady - w wolnym czasie poczytaj o typach zmiennych w Arduino i zobacz, jakie wartości maksymalne każdy z typów może przyjmować. W prostych przykładach nie ma to aż takiego znaczenia, ale dobrą praktyką jest, by zawsze wykorzystywać jak najmniejsze możliwe typy dla danej zmiennej by oszczędzać pamięć RAM ( i nie tylko ) . Dla przykładu :
    W środowisku Arduino, typ int może przyjmowac wartość liczbową z zakresu -32,768 do 32,767 . By przypisać numery pinów, potrzebujemy liczb z zakresu 0 do 54 ( Arduino Mega ). Więc wystarczy tu typ byte, mogący przyjąć wartość 0 do 255 . Warto też w przypadku przypisywania numerów pinów, korzystać z dyrektywy const - mówi ona, że deklarujemy stałą ( czyli "liczbę", która podczas działania programu nie będzie się zmieniać, której nic nie jest w stanie zmienić - np. pin mikrokontrolera ).
    Rada kolejna - po napisaniu kodu, kliknij w pasku narzędzi : NARZĘDZIA a potem Automatyczne formatowanie. Uporządkuje to wcięcia z kodzie, ułatwiające choćby szukanie ewentualnych błędów.

    A tu poprawiony kod ( z poprawionymi błędami które zrobiłem w komentarzach dotyczących ustawiania flag ) :
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 15  
    A tak na dobranoc jeszcze dodałem przycisk 3 i program 3:
    Ustawiłem zmienne a tu znowu błąd :
    Program 3 nie został zadeklarowany w tym zakresie

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 12 [minuty]:

    A ja siedziałem nad tym prostym kodem całą sobotę i niedziele kombinując jak to zrobić przeszukałem wiele programów i poradników i tylko tamto mi wyszło jako tak.
    Nawet inne fora siedzą cicho a temat opisałem tak samo.
    Chwała ci elektrodo.

  • Poziom 28  
    Nie posłuchał kolega mojej rady o poprawnym formatowaniu kodu i skorzystaniu z narzędzia automatycznego formatowania i przeoczył brak " } " zamykającego funkcję program2() ;)

  • Poziom 28  
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Policz wszystkie { oraz } - ich liczba powinna się równać ;)
    Jeśli w Arduino IDE umieścisz kursor obok nawiasu klamrowego czy okrągłego, program zaznaczy Ci odpowiadający mu nawias zamykający/otwierający. Zobaczysz wtedy, że brakuje nawiasu klamrowego zamykającego funkcję program2()

    Dodano po 5 [minuty]:

    Bogdan 6 napisał:
    Teraz widze czyli kazdy pod program konczymy }}


    Nie. Każda funkcja czy pętla zawiera się w { oraz } :
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 15  
    No i teraz wiem dlaczego zawsze mi coś nie wychodziło to przez te klamry .
    Nazwa tych klamer to oraz ?

    Dodano po 9 [minuty]:

    A tak z dawnego tematu nie rozwiązanego problemu z enkoderem.
    https://www.elektroda.pl/rtvforum/topic3367888.html#16644027
    Może kolego coś wie co jest źle.
    Dodam że po wgraniu z arduino ide 1.6.9 działa bez zmian, a po wgraniu z arduino 1.8.4 enkoder działa tylko na wolnym obrocie a na szybkom leci przez całą skale.
    Enkodery mam zmontowane na płytkach drukowanych.
  • Poziom 8  
    Szanowni Koledzy,
    mam problem z kodem - programuję prosty rotomat dla zegarka mechanicznego. Idea jest następująca:
    - mamy 3 przyciski wyboru programu oraz 3 diody sygnalizujące wybrany aktualnie program,
    - mamy wyświetlacz LCD 1602 wyświetlający nazwę wybranego przez nas programu,
    - mamy serwo, które obraca się z różnymi prędkościami lub jest w stanie spoczynku,
    program w zamyśle miał programować elementy w taki sposób, aby po włączeniu system był w stanie spoczynku.
    Stan ten miał trwać do momentu wyboru programu przyciskiem. Program miał działać tak długo aż nie zostałby zmieniony uruchomieniem innego za pomocą przycisku.
    Przewertowałem sporo stron z kodami i zdecydowałem się na funkcję boolean i stworzenie kilku warunków logicznych.
    Efekt jest taki, że po starcie zasilania rotomat jest w trybie spoczynku przez ok 5 sekund, a potem automatycznie przechodzi do trybu turbo i już w nim zostaje. Sterowanie przyciskami w ogóle nie robi na nim wrażenia. Sprawdziłem już rzeczy oczywiste typu podłączenie elementów na płytce stykowej - wszystkie przeszkody zostały wyeliminowane. W Arduino jestem świeżakiem więc spodziewam się, że w kodzie jest jakiś podstawowy błąd, którego jednak moje amatorskie oko nie widzi. Proszę pokornie o wskazanie błędu. Serdecznie dziękuję i pozdrawiam!

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 18  
    Koldarius napisał:
    ...
    pinMode(przyciskC, INPUT_PULLUP); // przycisk C
    ...
    if (digitalRead(przyciskC))

    Coś tu widzisz?
  • Poziom 8  
    Osz w mordę jeża - == LOW tego brakuje
    Serdecznie Ci dziękuję - nie zauważyłbym tego do końca świata.
    Teraz tylko jeszcze prosiłbym o podpowiedź w kwestii funkcji break. Bo teraz układ ładnie czeka w stanie spoczynku do momentu aż nie wybiorę przycisku, ale jak już wybiorę to wykonuje ten program do śmierci i dalej mnie nie słucha.

    Edit: problem braku reakcji na przyciski rozwiązany - wystarczy napisać to tak
    [code]
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Ale pętlę mogę przełączyć niestety tylko trzymając przycisk tak długo aż nie trafię na zerową pozycję serwa, a chciałbym natychmiastowego przełączenia - macie może Panowie jakąś sugestię? Będę wdzięczny za pomoc!
  • Poziom 8  
    Dzięki za sugestię jaclew - uprości to kod. Jedno sekundowy delay - hmm myślałem, że będzie pełnił funkcję stabilizującą. Wstawiłem z automatu bo w wielu przypadkach kodów np. z kursu Forbot tak robią. Myślisz, że to jest przyczyna? Lepiej je zlikwidować?
    Jak osiągnąć natychmiastowe przełączenie programu?
  • Poziom 21  
    Koldarius napisał:
    Jak osiągnąć natychmiastowe przełączenie programu?

    a) nie używać w kodzie funkcji delay()
    b) odczytywać przyciski w przerwaniu

    P.S.
    ja bym zamiast deklarowania trzech zmiennych boolean, zadeklarował jedną i nadawął jej wartości od 1 do 3 a potem wybierał podprogram konstrukcją switch - case.
    Bo nie przewidujesz chyba sytuacji, że więcej niż jedna ze zmiennych będzie w stanie TRUE?
  • Poziom 36  
    Koldarius napisał:

    Edit: problem braku reakcji na przyciski rozwiązany - wystarczy napisać to tak
    [code]
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Ale pętlę mogę przełączyć niestety tylko trzymając przycisk tak długo aż nie trafię na zerową pozycję serwa, a chciałbym natychmiastowego przełączenia - macie może Panowie jakąś sugestię? Będę wdzięczny za pomoc!

    Trochę to nie jasno...
    Czy to znaczy że masz trudności w swobodnym przełączaniu trybu z jednego programu do drugiego?
    Jeżeli w tym problem to zastosuj w każdym z podprogramów funkcję 'while' do czasu ważności flagi, która go wywołała,
    W funkcji tej (pod koniec) sprawdzaj stany pozostałych przycisków i ewentualnie kasuj tą flagę, oraz daj 'break' aby wyjśc z podprogramu.
    Rozpoznany przycisk ustawi swoją flagę i uruchomi odpowiedni podprogram.
    Przykładowy podprogram na blinking diode.
    Kod: c
    Zaloguj się, aby zobaczyć kod


    e marcus
  • Poziom 8  
    Dzięki emarcus!
    Czuje, że jestem bliżej poprawnego działania układu - niestety program wciąż każe czekać do ruchu powrotnego serwa. Przed tym ruchem nie można zmienić programu - w tym czasie nie jest też zapamiętywana zmiana flagi, o której mówiłeś.
    Funkcji attachinterrupt próbowałem, ale z miernym skutkiem.
    Kasowanie funkcji delay przy program1, program2 i program3 kończyło się destabilizacją działania mechanizmu i totalnym chaosem.
    Mój kod wygląda obecnie tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 17  
    Konstrukcję z poleceniem WHILE zastosowałeś tylko dla podprogramu program1()
    A w pozostałych dwóch nie dałeś tej pętli. Dlaczego?
    Koldarius napisał:
    w tym czasie nie jest też zapamiętywana zmiana flagi, o której mówiłeś.

    bo jest czeski błąd z postu #22 @emarcus w tym fragmencie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    gdzie powinno być przypisanie a nie porównanie zmiennej prog1 do wartości false.

    Czy stosujesz sprzętową minimalizację drgań styków przycisków?
    Bo jeżeli nie to dalsze pisanie takiego programu nie ma większego sensu wg mnie.
  • Poziom 36  
    jaclew napisał:
    Konstrukcję z poleceniem WHILE zastosowałeś tylko dla podprogramu program1()
    A w pozostałych dwóch nie dałeś tej pętli. Dlaczego?
    Koldarius napisał:
    w tym czasie nie jest też zapamiętywana zmiana flagi, o której mówiłeś.

    bo jest czeski błąd z postu #22 @emarcus w tym fragmencie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    gdzie powinno być przypisanie a nie porównanie zmiennej prog1 do wartości false.

    Czy stosujesz sprzętową minimalizację drgań styków przycisków?
    Bo jeżeli nie to dalsze pisanie takiego programu nie ma większego sensu wg mnie.


    To nie jest 'czeski błąd' - to jest istonie zwyczajny błąd(!). Dziękuję za korektę!
    Czeski bład jest wtedy gdy wystąpi przestawienie miejscami dwóch cyfr/(liter), charaterystyczne zjawisko u dislektyków (27 vs 72).
    Natomiast nie ma potrzeby eliminacji drgań styków 'debounce' wtym konkretnym przykładzie;
    - wynikiem funkcji sprawdzania 'buttonów' jest jednoznaczna, arbitralna odpowiedź na stan niski (LOW) - w tym wypadku winna byc : "prog1 =false;"
    Jeżeli wynikiem/(odpowiedzią) byłaby incrementacja zmiennej lub zmiana istniejącego stanu logicznego na przeciwny (toggle) to debounce byłby konieczny.
    Czy jest różnica wynikowa od; ile razy wypowiemy: ZERO..., ZERO.. (?) - nie będzie 200 (2 i dwa zera!).

    e marcus
  • Poziom 8  
    jaclew - masz rację moje niedopatrzenie. Niemniej wprowadzenie zmian wszędzie gdzie potrzeba nie zmienia sytuacji. Tak samo zmiana na "prog1 = false" - z programu 1 jestem w stanie wyjść w każdym momencie, programy 2 i 3 wymagają aby serwo kręciło się w prawo (?), podczas obrotu w lewo wciskanie przycisków nie przynosi absolutnie żadnego wyniku (wciśnięcia nie są też zapamiętywane).
    Funkcji debounce nie stosowałem gdyż w przykładach mechanizmów, o które się opierałem nikt tego nie robił.
  • Poziom 36  
    Koldarius napisał:
    Niemniej wprowadzenie zmian wszędzie gdzie potrzeba nie zmienia sytuacji. Tak samo zmiana na "prog1 = false" - z programu 1 jestem w stanie wyjść w każdym momencie, programy 2 i 3 wymagają aby serwo kręciło się w prawo (?), podczas obrotu w lewo wciskanie przycisków nie przynosi absolutnie żadnego wyniku (wciśnięcia nie są też zapamiętywane).


    Podprogamy 2 i 3 zachowuj się zgodnie z tym co wpisałęś w ich treści:
    Analizując głębij co tam 'robisz'..:

    Są tam umieszczone dwie kolejne po sobie pętle "for..", trwające w czasie;
    nie masz żadnych zastrzeżeń lub ograniczeń wpierwszej pętli która wykona się niezależnie od pozycji przycisków, dopiero po ukończonej drugiej pętli odpytujesz stany przycisków (A i B) 'poling'.
    Metoda ta pracuje w ten sposób, że jeżeli podczas odpytywania szukany warunek wystąpi, to funkcja ta zostanie uruchomiona. Inaczej mówiąc :
    'jeżeli ci się uda trafic w ten moment, to jest szansa że funkcja będzie uruchomiona.
    Jezeli zechcesz przerwac wykonywanie w dowolnym momencie programu, to obsługa przycisków musiałaby powodowac interrupt kierujący dalszą pracę processora do wykonania specyficznych zadań (wspominasz o zapamietuwaniu położeń serva) nie tylko opuszczenie tego podprogramu...

    Podany wcześniej przykład obrazował tylko metodę dla prostych nie komplikowanych podprogramów.

    e marcus
  • Poziom 8  
    Jako totalny amator chciałem już porzucić próby poprawienia tego kodu i uznać, że nie mam jeszcze wiedzy na zrobienie tego. Ale spróbowałem usunąć wszystkie delaye i spróbować opanować cały ten ambaras funkcją millis zgodnie z kolejnymi znalezionymi w necie pomysłami. I teraz wszystko da się przełączać w dowolnym momencie. Tylko serwo działa beznadziejnie. Czuje, że to tylko kwestia odpowiedniego zdefiniowania warunków ruchu w lewo i prawo na zasadzie
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czuję, że popisałem trochę bzdur kombinując funkcje if z for. Jaka jest Panów opinia?
  • Poziom 18  
    Nie widzę związku oczywistego między twoim problemem a wątkiem w którym piszemy. Może powinieneś własny założyć.

    Jak myślisz, ile będzie trwało wykonanie całej pętli for od pos 0 do 180? Ułamek sekundy? Cały ten program3, o ile w ogóle jest konieczny mógłby wyglądać tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    W pierwszej wersji oblicz_nową_pozycję() zwróci coś typu pozycja + krok (1, -1, zależy od prędkości i kierunku). Jutro napiszesz płynne rozpędzanie i hamowanie jeśli potrzebne.
  • Poziom 8  
    dziękuję wszystkim za pomoc i przepraszam za zrobienie offtopa w temacie. Poniżej kod, który działa już w 99% dobrze i zgodnie z zamysłem.
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jedyny problem jest taki, że ekran napisy na ekranie zaczynają wariować na programie 2 i 3, a samo serwo robi losową ilość ruchów. Myślę, że z czasem jednak to jakoś opanuję.
    Serdecznie dziękuję i pozdrawiam!