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.

[Rozwiązano] Wprowadzanie liczby i przycisk akceptuj, AVR C

KampoPampo 22 Lip 2018 18:44 1161 33
  • #1 22 Lip 2018 18:44
    KampoPampo
    Poziom 3  

    Witam i o zdrowie pytam!

    Piszę post z nadzieją, że otrzymam jakąś radę. Mam mały problem z napisaniem kodu, który chciałbym żeby działał w następujący sposób: z klawiatury matrycowej wpisuje liczbę 2 cyfrowa, którą następnie poprzez naciśnięcie przycisku np. # zaakceptuje i zapisze ją w pamięci mikrokontrolera i następnie przyrównam ją do wartości czujnika. Czy macie jakąś wskazówkę od czego zacząć? Mam trochę napisanego kodu, klawiatura matrycowa chodzi bez zarzutu, ale wykorzystać w ten sposób jej nie potrafię tak jak opisuję.

    Jak widać w main() przypisałem pom = 0, ale nie wiem czy o to chodziło. Do tego jeszcze musiałem zdefiniować dwie zmienne dzies i jed, które też widać. Nie dodałem, że mam klawiature 4x4 wiec numery klawiszy są różne od wartości na klawiaturze (klaw == 4 to przycisk A).

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tutaj zaczynają się schody bo po wcisnieciu odpowiedniego klawisza na klawiaturze wchodze w procedurę, która będzie odpowiedzialna za podlewanie zależne od wilgotności. Jednak będąc juz w tej procedurze, próbując wpisać liczbę nic się nie zmienia. Jedynie przed wejściem w "Wilgotność" proces reaguje na wpisywanie cyfr lub reaguje wtedy, gdy zatwierdzam to klawiszem # (co też nie daję mi pewności czy jest dobrze napisane. (poniżej)

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wiecie może co robie źle, bo niestety ale skończyły mi się pomysły. Próbowałem z petlami do while ale niestety nie ma reakcji na przyciski.

    Z góry dziękuję.

    0 29
  • #2 22 Lip 2018 20:46
    gaskoin
    Poziom 38  

    Trochę chaotycznie opisałeś problem. Przeczytaj swojego posta i go przeredaguj proszę. Masz kod wiszący w powietrzu i słabo sformatowany, nie wiadomo do końca jaki masz konkretnie problem. Wywnioskowałem, że wprowadzanie i zatwierdzanie liczb jest problematyczne.

    Zrób to na raty a nie wszystko na raz. Natrzaskałeś 500 warunków i nie wiadomo czemu nie działa. Na początek skup się na poprawnym odczycie z klawiatury a potem na pompkach.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    na początek ostatni if może wyglądać tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #3 22 Lip 2018 21:38
    KampoPampo
    Poziom 3  

    Kod sterujący klawiaturą działa bez zarzutu. Streszczając wszystko, głównie chodzi mi o sposób na zatwierdzenie wprowadzonej liczby, coś w stylu przycisku enter, oraz o samo wprowadzanie cyfr jako liczba 2 lub 3 cyfrowa. Klawiatura ma 16 przycisków, a to co mi podpowiedziałeś jest na prawdę interesujące.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czy dobrze rozumiem twoje rozwiązanie? Każda cyfra mniejsza niż wartość key będzie mnożona razy 10, ale co z cyfrą jedności? Można tak rozwiązać problem z resztą przycisku czy trzeba się ograniczać do zakresu 5<key<8 lub 8<key<12 itd? Jestem kompletnym laikiem i na prawdę może się to wydawać dziwne lub głupie, ale dużo rzeczy nie rozumiem.

    Dziękuje i pozdrawiam.

    0
  • #4 23 Lip 2018 00:10
    gaskoin
    Poziom 38  

    Odpowiem ogólnie bo nie rozumiem Twojego kodu i nie chce mi się go rozumieć jak nie jesteś w stanie go nawet sformatować. Rozwiązanie zakłada sztywną ilość liczb, stąd znany z góry mnożnik.

    Jak chcesz liczbę dwucyfrową: ustawiasz mnożnik na 10.
    Jak chcesz liczbę trzycyfrową: ustawiasz mnożnik na 100.
    Itd.

    Co naciśnięcie przycisku dzielisz mnożnik przez 10 żeby kolejna liczba "była w innym miejscu". Przykład (dla liczb 3 cyfrowej):

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jak nie znasz ilości cyfr to trzeba do tego podejść inaczej.

    0
  • #5 23 Lip 2018 09:02
    ex-or
    Poziom 18  

    Tworzysz maszynę stanów z dwoma stanami, nazwijmy je Idle i Input.
    Idle to stan początkowy. Naciśnięcie dowolnego przycisku numerycznego powoduje przejście do stanu Input. Przejście zapisuje do zmiennej roboczej wartość wciśniętego przycisku.
    Stan Input ma dwa przejścia:
    a. Naciśnięcie klawisza liczby mnoży zmienną roboczą x10 i dodaje wartość klawisza. Maszyna pozostaje w stanie Input.
    b. Naciśnięcie klawisza # powoduje udostępnienie odczytanej liczby (np. ustawienie flagi Ready) oraz przejście do stanu Idle.
    I tyle jeśli chodzi o obsługę klawiatury, wątek "klawiatura" robi tylko tyle i nic więcej.
    Inny wątek w momencie ustawienia flagi Redy robi z odczytaną liczbą co tam ma zrobić i gasi flagę.
    Tak to się mniej więcej robi.

    0
  • #6 23 Lip 2018 09:38
    BlueDraco
    Specjalista - Mikrokontrolery

    Gaskoin: w Twoim kodzie brakuje niezbędnej fazy początkowej: "zgadujesz, ile klawiszy naciśnie użytkownik i ustawiasz zmienną mnożnik na tej podstawie".

    Oczywiście kol. ex-or podał rozsądne rozwiązanie.

    0
  • #7 23 Lip 2018 10:23
    gaskoin
    Poziom 38  

    Myślałem, że jest znana bo w pierwszej wiadomości mowa jest o liczbie dwucyfrowej.

    0
  • #8 23 Lip 2018 10:53
    BlueDraco
    Specjalista - Mikrokontrolery

    I wtedy jednocyfrowa jest błędna - nie można wpisać "5", musi być "05". Jak widzisz wersja bez zgadywania liczby cyfr przed wprowadzeniem nie jest wygodna dla użytkownika. ;)

    0
  • Pomocny post
    #9 24 Lip 2018 08:58
    3149400
    Użytkownik usunął konto  
  • Pomocny post
    #10 24 Lip 2018 09:34
    gaskoin
    Poziom 38  

    Można też tak, ale jest z buforem jest kilka problemów. Na końcu masz tablicę {5, 6 , 7} i jeżeli potrzebujesz zamienić to na wartość 567 to jest to trochę kłopotliwe (potęgowanie 10, liczenie elementów, ew atoi albo sprintf).

    Prościej zrobić to tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Albo przerobić to na maszynę stanów jak wspominał kolega @ex-or

    BlueDraco napisał:
    Jak widzisz wersja bez zgadywania liczby cyfr przed wprowadzeniem nie jest wygodna dla użytkownika. ;)


    Zawsze można podać z klawiatury ile będzie cyfr :P

    0
  • #11 24 Lip 2018 09:45
    BlueDraco
    Specjalista - Mikrokontrolery

    nowyARM: niezręczne i bylejakie, ale działa; raczej z gatunku "jak tego robić nie należy".
    Rozwiązanie z automatem, bez bufora, jest w tym przypadku dobre. Zresztą każdy przyzwoity program, w tym np. kompilator, czyta wejście na tej właśnie zasadzie.

    0
  • #12 24 Lip 2018 09:53
    3149400
    Użytkownik usunął konto  
  • #13 24 Lip 2018 10:00
    gaskoin
    Poziom 38  

    nowyARM napisał:
    BlueDraco napisał:
    niezręczne i bylejakie, ale działa;

    I krótko, kilka linijek czego nie można powiedzieć o rozwiązaniu @gaskoin.


    Przecież moje rozwiązanie jest krótsze. Jakbym wrzucił tylko właściwy wycinek tak jak Ty to było tyle:

    gaskoin napisał:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #14 24 Lip 2018 10:20
    3149400
    Użytkownik usunął konto  
  • #15 24 Lip 2018 10:43
    gaskoin
    Poziom 38  

    Zajrzyj jeszcze raz na przykład, bo mam wrażenie, że się uniosłeś się dumą i nie postarałeś się go nawet zrozumieć.

    check_result to obsługa gotowego liczbowego wyniku, która zależy od tego co chcesz zrobić. Nie jest to część algorytmu. U Ciebie z resztą nie ma tego w ogóle.
    read_key to tylko implementacja odczytu z klawiatury. Nieistotne dla algorytmu. U Ciebie jest to pominięte.

    Jak pominąłem to, co Ty, to zostało istotne 6 linijek.

    Masz z resztą w komentarzach, że te funkcje to tylko port na PC, szkoda, że ich nie przeczytałeś.

    nowyARM napisał:
    A co złego jest w sscanf (napisałeś sprintf ale sądzę, że to pomyłka).


    Jest powolne, u mnie print jest zbędny i służy tylko do tego, żeby na PC wyświetlić sobie wynik.

    nowyARM napisał:
    Co do potęgowania


    Potęgowanie to nie to samo co mnożenie.

    nowyARM napisał:
    i innych dzieleń:


    To był przykład przebiegu programu. W rzeczywistości to przecież 2 linijki kodu. Przeczytaj wątek od początku, jeżeli masz zamiar prowadzić taką agresywną dyskusję.

    0
  • #16 24 Lip 2018 11:29
    3149400
    Użytkownik usunął konto  
  • #17 25 Lip 2018 21:05
    BlueDraco
    Specjalista - Mikrokontrolery

    nowy: dobrze napisany program musi sensownie reagować na bezsensowne operacje użytkownika. Łatwo to osiągnąć pisząc automat, duuużo trudniej choinką złożoną ze sscanf() i if(). Rozmiar kodu binarnego w przypadku użycia sscanf sporo większy. Przy automacie nie trzeba żadnego bufora.

    0
  • #18 25 Lip 2018 21:29
    grko
    Poziom 33  

    @BlueDraco Problem jest taki, że ten automat za każdym razem trzeba pisać na nowo. Chyba, że używasz jakiegoś automatycznego rozwiązania ( http://www.colm.net/open-source/ragel/ ). W sumie średnio mnie interesuje w dzisiejszych czasach to, że sscanf dużo zajmuje albo jest wolny. Do momentu jak nie będę musiał wywoływać tej funkcji tysiące razy na sekundę albo skończy mi się miejsce w pamięci flash to nadal wolę używać funkcji, które są __standardem__ niż wymyślać 10 raz koło na nowo.

    0
  • #19 25 Lip 2018 21:49
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie wydaje mi się, że pisanie do każdego projektu nowej choinki if() i sscanf() (bo mamy np. różne klawiatury) różni się praccochłonnością od modyfikacji raz napisanego szkieletu automatu, a sama baza automatu nie ulega zmianie w każdym projekcie. Ja takiego automatu do skanowania wejścia używam w wielu projektach, chociaż poszczególne projekty biorą to wejście z zupełnie różnych interfejsów i różnią się wieloma szczegółami. Uważam, że choinka if() byłaby dużo bardziej pracochłonna i trudniejsza do zdebugowania.
    Weźmy też np. taki problem, jak czytanie z wejścia liczba zapisanych w różnych systemach, np. w konwencji języka C - dziesiętnych, szesnastkowych, ósemkowych i binarnych; w automacie można to zrobić b. łatwo, i przejrzyście, a jak wygląda choinka if() i sscanf w tym przypadku?
    Oczywiście da się to zrobić choinką - mniej czytelnie, z większym i znacznie wolniejszym kodem, tylko po co?
    No i dlaczego kompilatory nie używają choinek if(), a lekserów pracujących właśnie jak automaty?

    0
  • #20 25 Lip 2018 22:01
    ex-or
    Poziom 18  

    BlueDraco napisał:
    Przy automacie nie trzeba żadnego bufora.

    Ta. Nawet kiedy założymy możliwość kasowania ostatnio wprowadzonego znaku, bo wystarczy podzielić zmienną roboczą przez 10 (czy przez 16 jeśli wprowadzamy liczby szesnastkowe).

    0
  • #21 25 Lip 2018 22:01
    grko
    Poziom 33  

    BlueDraco napisał:
    Nie wydaje mi się, że pisanie do każdego projektu nowej choinki if() i sscanf() (bo mamy np. różne klawiatury) różni się praccochłonnością od modyfikacji raz napisanego szkieletu automatu, a sama baza automatu nie ulega zmianie w każdym projekcie. Ja takiego automatu do skanowania wejścia używam w wielu projektach, chociaż poszczególne projekty biorą to wejście z zupełnie różnych interfejsów i różnią się wieloma szczegółami. Uważam, że choinka if() byłaby dużo bardziej pracochłonna i trudniejsza do zdebugowania.
    Weźmy też np. taki problem, jak czytanie z wejścia liczba zapisanych w różnych systemach, np. w konwencji języka C - dziesiętnych, szesnastkowych, ósemkowych i binarnych; w automacie można to zrobić b. łatwo, i przejrzyście, a jak wygląda choinka if() i sscanf w tym przypadku?
    Oczywiście da się to zrobić choinką - mniej czytelnie, z większym i znacznie wolniejszym kodem, tylko po co?
    No i dlaczego kompilatory nie używają choinek if(), a lekserów pracujących właśnie jak automaty?


    No spoko. rozumiem. Dlatego podałem Ci linka z narzędziem, które pozwoli Ci nie wynajdywać za każdym razem automatu na nowo tylko Ci wygeneruje parser. Nie wiem jak Ty ale ja już średnio odczuwam radość z pisania tego samego 10x w różnych projektach.

    A do skanowania jednej liczby w formacie dziesiętnym to sscanf w zupełności wystarczy. Albo lżejsze atol albo strtol.

    0
  • #22 26 Lip 2018 10:11
    3149400
    Użytkownik usunął konto  
  • #23 26 Lip 2018 12:26
    gaskoin
    Poziom 38  

    Ten temat to już offtopic, z resztą autor chyba go porzucił :) @nowyARM Ten wątek jest totalnie bez sensu rozciągnięty, trzeba było wrzucić swoje rozwiązanie i zignorować zaczepkę kolegi @BlueDraco

    nowyARM napisał:
    Zauważyłem też, nie niektórzy forumowicze, zmieniają przekonania zależnie jaka prawdę chcą udowodnić. Raz nie warto przejmować się wielkością kodu i prędkością działania innym razem, jak to wprowadzanie raz na godzinę danych, to bardzo ważna sprawa. Kod ma być krótki i szybki. Pytam więc ponownie, dlaczego nie napisać go w ASM?


    No właśnie jedyną osobą, która chce komuś coś udowadniać w tym wątku od początku jesteś Ty. Mam wrażenie, że za wszelką cenę chcesz wszystkim powiedzieć, że w Twoje rozwiązanie jest the best. Twoje rozwiązanie jest zarówno the best jak i jest do niczego.

    Otóż wszystko zależy od kontekstu i wymagań. Zauważ, że na początku podałem zupełnie inne rozwiązanie, bo nie wiedziałem jakie jest wymaganie i kontekst. Potem jak go zrozumiałem, to rozwiązanie odwróciło się o 180 stopni. Stwierdziłem też, że sscanf jest duży i wolny. W kontekście atmegi8 może, ale nie musi, mieć znaczenia. W kontekście xmega128 nie ma żadnego znaczenia.

    Nie piszę w ASM bo po pierwsze kiepsko mi to idzie, a po drugie jest mniej czytelne niż C. Za mniej czytelne uważam też rozwiązanie z buforem, ale to tylko moje zdanie. W niektórych przypadkach nie da się zrobić tego inaczej niż "po Twojemu". Czasami nie da się rozwiązać problemu ani "po mojemu", ani "po Twojemu", tylko trzeba wprowadzać FSM. Także trzeba zrozumieć kontekst, bo w tym wątku go nie ma i rzucamy się o abstrakcyjne problemy.

    0
  • #24 28 Lip 2018 20:37
    KampoPampo
    Poziom 3  

    Niestety nie zapomniałem o temacie, ale nie miałem czasu, żeby wrócić do tematu i dlatego mogłem wywołać niepewność w szanownych kolegach. Dziękuję za tak obszerną i zagorzałą dyskusję, dała mi dużo do myślenia, ale......

    Zastosowałem rozwiązanie @gaskoin i wszystko działa jak należy. Wpisuje z klawiatury i zatwierdzam i mam wynik. Próbuje teraz rozwiązać sprawe z zapisem maksymalnie 3 cyfr, ale jak na razie nie ma efektu.

    Dziękuję ślicznie za wszystkie odpowiedzi, pomogły mi bardzo i otworzyły mi drogę na kolejne etapy mojej pracy.

    0
  • #25 05 Lis 2018 18:58
    KampoPampo
    Poziom 3  

    Nie wiem czy ktoś jeszcze z was zagląda na ten temat ale spróbuję.

    Chce dodać opcje, która będzie uruchamiać / wyłączać pompke przy odpowiednich warunkach.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wpisuje liczbe i od razu włącza mi się pompka (nawet nie zatwierdzę i działa ciągle, nawet jak wracam do głównego menu), a moim celem jest zeby pompka działała zależnie od wilgotności. Kod do pomiaru ADC działa poprawnie, jednak tu mam kłopot.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Potraficie mi coś doradzić, bo niestety męczę sie nad tym troche.

    0
  • #26 06 Lis 2018 08:43
    BlueDraco
    Specjalista - Mikrokontrolery

    Pokazałeś dwa FRAGMENTY kodu, w tym jeden nieczytelnie sformatowany i z dwoma błędami (Po co sprawdzasz czy <, jeśli już wcześniej wiesz, że <=? - Słowo kluczowe else się kłania no i brak histerezy). Duży błąd leży w kodzie, którego nie pokazałeś. Najpierw jednak sformatuj go tak, żeby dawał się czytać, czyli np. tak, jak ten drugi, większy fragment.

    0
  • #27 06 Lis 2018 20:37
    KampoPampo
    Poziom 3  

    Kod: c
    Zaloguj się, aby zobaczyć kod


    W tym przypadku jest tak jak opisałem wcześniej, że jak przechodzę do tej pozycji menu, wpisuje liczbe i zatwierdzam to pompka się włącza niezależnie od wskazania czujnika i działa non stop. Próbowałem to jakoś rozwiązać, ale bez skutku.

    0
  • #28 15 Lis 2018 15:19
    KampoPampo
    Poziom 3  

    Próbowałem dodać jakieś usprawnienia, ale problem cały czas jest ten sam, gdyż po zatwierdzeniu jakiejkolwiek wartości z klawiatury (od 1 do 100) pompka włącza się i działa cały czas nie reagując na Zmiany wartości wilgotności. Chciałbym wiedzieć o co chodzi, ale nie wiem. Jest ktoś w stanie podrzucić jakąś wskazówkę, bo na razie nie daje rady tego rozwiązać. Bardzo dziękuję za wcześniejsze odpowiedzi.

    0
  • Pomocny post
    #29 15 Lis 2018 17:24
    BlueDraco
    Specjalista - Mikrokontrolery

    Wskazówka pierwsza: sformatuj kod tak, by dawał się czytać.

    0
  • Pomocny post
    #30 15 Lis 2018 17:49
    mpier
    Poziom 17  

    Witam. Ja mam dwie. Przeczytaj jeszcze raz cały temat a późnej wymyśl algorytm (po polsku), zanim zaczniesz pisać program w C. Postaraj się podzielić pomysł na części.

    0