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

Klawiatura matrycowa na liniach multipleksu - jak to ogarnąć?

13 Sty 2019 23:52 1215 48
  • Poziom 6  
    Dodam część mojego schematu z innego posta:
    Klawiatura matrycowa na liniach multipleksu - jak to ogarnąć?

    *W rzeczywistości dioda jest przy każdym przycisku, nie ma rezystorów na wierszach klawiatury, są za to ściągające do masy i jest 5 rejestrów (jeśli to istotne).

    Udało mi się oprogramować multipleks 4x5 i wysyłać do niego dane po SPI. Utknąłem w miejscu klawiatury matrycowej, która korzysta z tych samych linii multipleksu co wyświetlacze. Część mojego kodu wygląda tak jak poniżej. Reakcja na przycisk jest, jednak nie wiem jak "ustabilizować" reakcję po wciśnięciu przycisku, tak żeby nie szalało równo z multipleksem i przy okazji, żeby nie blokowało programu.

    część kodu :
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Mógłby ktoś mnie naprowadzić w jaki sposób to ogarnąć? Mile widziany byłby chociaż fragment kodu bo łatwiej byłoby mi to przyswoić.
  • PCBway
  • Poziom 30  
    W przerwaniu, gdzie wysyłasz dane do rejestrów 74HC595, odczytuj stan przycisku i zapisuj do zmiennych (tablicy) zależnie od tego, którą anodę wysterowałeś. Możesz indeksować tablicę zmienną "licznik ".
    Do tego oczywiście standardowa eliminacja drżenia styków.
  • Poziom 6  
    Siedzę nad tym trochę czasu ale dalej nie wiem jak to ugryźć. Nie potrafię samemu rozpisać tego o czym powiedziałeś. Masz może jakiś przykład?
  • Poziom 20  
    Przede wszystkim masz błędny hardware na przyciskach oraz także źle je inicjujesz w sofcie.
    Musisz mieć wiersze przycisków ściągnięte do GND, wtedy naciśnięcie przycisku poda na pin HIGH. Ponieważ w AVR nie ma programowego pulldowna więc musisz dolutować rezystory.
    Instrukcja
    Kod: c
    Zaloguj się, aby zobaczyć kod
    nie ma najmniejszego sensu. Port PIN jest portem wyjściowym. (co prawda w nowszych prockach zapis do PIN jest możliwy i ma pewien sens ale nie w tym przypadku). Pozostałe makra też nie zawsze mają sens np.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Nie wiem jak Ci te przyciski działają, chyba przypadkiem.
  • PCBway
  • Poziom 6  
    Mógłbyś rozwinąć "błędny hardware na przyciskach"? Bo nie bardzo to rozumiem.
    Wiersze przycisków oczywiście są podpięte rezystorami do masy.
  • Poziom 39  
    dasej napisał:
    >>>>> wysylanie danych do LED DP3A
    _delay_us(1); // czas na przełacznie portu, bez opóźnienia są błędy w odczycie

    Dlatego lepiej jest zmienić kolejność. Najpierw odczytujemy IO, a dopiero później zmieniamy aktualnie wyświetlany segment.
  • Poziom 31  
    Jeżeli zmienimy kolejność to co wtedy odczytamy skoro szyna nie będzie aktywna.

    Klawiatura matrycowa na liniach multipleksu - jak to ogarnąć?

    Wysyłamy dane do LED utrzymując stan aktywny dla danego segmentu do czasu zakończenia pomiaru.

    C1 = czas obsługi segmentu pierwszej cyfry
    itp........

    KEY to czas obsługi klawiatury

    W tym przypadku opóźnienie można pominąć

    Fragment kodu pochodzi z obsługi klawiatury 4x4 na jednym porcie i stąd opóźnienie
    jest czas potrzeby na zmianę stanu portu ( minimum 1 takt zegarowy ).
  • Poziom 39  
    dasej napisał:
    Jeżeli zmienimy kolejność to co wtedy odczytamy skoro szyna nie będzie aktywna.

    Nie rozumiesz. Chodzi o to, żeby czytać stan klawiatury przed zmianą aktywnego segmentu. U Ciebie to działa tak:
    - zmieniasz segment
    - czekasz 1us na ustabilizowanie się nowego stanu
    - odczytujesz klawiaturę
    - wychodzisz z przerwania
    w mojej wersji to działa tak:
    - czytam klawiaturę
    - zmieniam segment
    - wychodzę z przerwania
    W następnym cyklu jako pierwsze czytam klawiaturę - czyli zamiast czekać 1us, czekam cały okres "międzyprzerwaniowy" na ustabilizowanie się napięć na klawiaturze. Pewniej, prościej, i bez delaya w przerwaniu.
  • Poziom 31  
    Pisałem że w tym przypadku można pominąć opóźnienie

    Kod: c
    Zaloguj się, aby zobaczyć kod



    a końcowo wyjdzie tak
    - zmieniasz segment
    - odczytujesz klawiaturę
    - wychodzisz z przerwania

    Tylko że Twój sposób będzie zwracał stan klawiatury z poprzedniego wywołania
    a mój z bieżącego i tu jest spora różnica


    A tak robiłem to na jednym porcie i dlatego jest potrzebne opóźnienie jednego taktu zegarowego na zmianę stanu wyjść w porcie.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    A z czego to wynika zapewne dobrze wiesz.
  • Poziom 39  
    dasej napisał:
    Tylko że Twój sposób będzie zwracał stan klawiatury z poprzedniego wywołania
    a mój z bieżącego i tu jest spora różnica

    Zupełnie bez zastanowienia to napisałeś. Po pierwsze to czytasz i tak segmentami więc tak czy siak masz nieaktualny stan klawiatury, zarówno w Twojej jak i mojej wersji. Po prostu w Twojej odczytasz stan z innego segmentu niż w mojej co jest zupełnie bez znaczenia, bo nie wiesz na którym segmencie jest aktualnie wciśnięty przycisk. Po drugie, tak na marginesie to mówimy o multipleksowaniu rzędu kilkuset odczytów na sekundę, a czytasz sygnał którego czas trwania jest rzędu setek milisekund, więc to czy odczytasz stan aktualny czy sprzed 5ms nie ma najmniejszego znaczenia.
  • Poziom 31  
    Jeśli chodzi o czas to masz rację.

    Jak mamy uint8_t Segment = 0;
    To Twoja metoda odczyta klawiaturę z Segment = 3 ;

    Summa summarum można i tak. Trzeba tylko przesunąć odczyt klawiszy względem schematu o jeden.
    Można i tak podejść do tematu. Mi coś takiego nie pasuje.
  • Poziom 6  
    Cytat:
    Piny odczytujące klawiaturę ustawiamy jako wejście,
    włączamy 'podciąg' dodatkowe rezystory w procesorze.


    Piny oczywiście mam ustawione jako wejścia, ale korzystam z zewnętrznych rezystorów ściągających do masy bo sygnał wchodzący na kolumny przycisków ma stan wysoki (anody wyświetlaczy).

    Dobrze zrozumiałem? :
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 39  
    dyerseve napisał:
    Piny oczywiście mam ustawione jako wejścia, ale korzystam z zewnętrznych rezystorów ściągających do masy bo sygnał wchodzący na kolumny przycisków ma stan wysoki

    A co to za mikrokontroler? Bo w AVR nie ma rezystorów pull-down.
  • Poziom 6  
    Cytat:
    korzystam z zewnętrznych rezystorów


    :D
  • Poziom 6  
    Wszystko jest opisane w pierwszym poście, ale dla ułatwienia dodam schemat:

    Klawiatura matrycowa na liniach multipleksu - jak to ogarnąć?

    Tak jest to rozwiązane na PCB (chodzi mi o część z przyciskami, bo wyświetlaczy jest więcej). Żeby podać stan wysoki dla anod/ linii multipleksu, to muszę na port wystawić stan niski. Czyli przy wystawieniu 0 na PORTD muszę sprawdzać czy na PORTA jest 1 - tak mi się przynajmniej wydaję.

    Jak widać nie mogę zmienić 'polaryzacji' bo będę gasił jedną kolumnę zamiast ją zapalał.
  • Poziom 31  
    Tranzystor miał jedynie podać masę na przyciski i był sterowany z zasilania katody wyświetlacz.
    W ten sposób eliminujesz rezystory (180 ) i wykorzystuje te wewnętrzne w procesorze.
    Dając mosfeta N-Chanel uzyskasz dobry poziom logiczny '0'.
  • Poziom 6  
    Chyba w ogóle nie zapoznałeś się z tematem albo pominąłeś czytanie moich postów.
  • Poziom 6  
    Czyli jednak nie czytałeś moich postów :)

    Podsumowując moje postu - układ jest zbudowany jak na ostatnim schemacie i jest w takiej postaci fizycznie na PCB.
  • Poziom 30  
    dyerseve napisał:
    Wszystko jest opisane w pierwszym poście, ale dla ułatwienia dodam schemat:
    Klawiatura matrycowa na liniach multipleksu - jak to ogarnąć?

    Strasznie to przekombinowane a biorąc pod uwagę, ze wyświetlaczy jest więcej to musi być monstrum.
    - Nie lepiej było zastosować dedykowane sterowniki?
    - Jeśli już robi się multipleksowanie a wyświetlaczy jest dużo, to należało dać od strony katod np ULN2803, anody z np A2982, którym/którymi steruje demultiplekser. Klawiatura na ekspanderach I2C/SPI ewentualnie na rejestrach równoległo-szeregowych np 74HC165.
    - Gdy jest mało GPIO w uC a odczuwa się strach przed ekspanderami I2C/SPI to 75HC595 do każdego wyświetlacza i 74HC165 do klawiatury. Część linii sterujących rejestrów może być współdzielona (zegar, zatrzask) do tego Dout + Din - razem 4 linie.
    - MAX7219 obsłuży 8 szt wyświetlaczy 7-seg. MAX można łączyć szeregowo. Co ważne, nie potrzeba rezystorów do ograniczenia prądu.

    Naprawdę jest dużo rozwiązań a to które zastosowałeś chyba najgorsze z możliwych rodem z PRL.
  • Poziom 6  
    Cytat:
    Naprawdę jest dużo rozwiązań a to które zastosowałeś chyba najgorsze z możliwych rodem z PRL.


    Takie rozwiązanie zostało mi zaproponowane przez o wiele bardziej doświadczone osoby ode mnie, a że o programowaniu nie wiedziałem kompletnie nic to uznałem, że widocznie jest to dobre rozwiązanie. Jak widać tacy właśnie są specjaliści na forach. Pewnie ci bardziej ogarnięci się po prostu nie udzielają

    Oprogramowanie klawiatury to jedyny problem tego projektu, wyświetlacze działają zgodnie z założeniami bez żadnych problemów. Łącznie jest 17 cyfr na "matrycy" 4x5, do tego omawiane przyciski w układzie 4x6
  • Poziom 30  
    dyerseve napisał:
    Jak widać tacy właśnie są specjaliści na forach. Pewnie ci bardziej ogarnięci się po prostu nie udzielają

    Niech zgadnę ArduinoPolska ewentualnie Forbot?

    W kodzie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Nie podobna mi się switch. Co się stanie jak kilka klawiszy naciśniesz równocześnie?
    Dalej, po co if (licznik==0), następnie if (licznik==1) i powtarzasz w kółko to samo? Tu predzej należało zastosować switch. Zrób coś w tym stylu:
    Kod: csharp
    Zaloguj się, aby zobaczyć kod

    Na razie nie masz rozwiązanego drżenia styków ale wszystko po kolei. Kody klawiszy możesz odczytywać np
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Trochę inaczej wygląda to, gdy wystarczy odczyt jednego "pierwszego" naciśniętego klawisza al chyba nie po to dałeś diody aby nie było możliwości odczytania kilku przycisków, chyba, że chodziło o uniknięcie problemu z zakłóceniem wyświetlacza przy naciśnięciu kilku klawiszy.

    to
    Kod: c
    Zaloguj się, aby zobaczyć kod

    zmień na np
    Kod: c
    Zaloguj się, aby zobaczyć kod

    kod w C krótszy, w ASM? Nie wiem, pewnie taki sam jak i z if.


    W kod obsługi wyświetlacza na razie nie wnikam ale da się uprościć.

    Dodano po 12 [minuty]:

    MULTIPLEX1_ON
    MULTIPLEX2_ON
    idt
    zastąp przez
    Kod: c
    Zaloguj się, aby zobaczyć kod

    czy używając macra:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 6  
    Fora to elektroda i atnel (zwany przez elektrodowców sektą atnel :D )

    Diody przy przyciskach są dla zabezpieczenia przed zwarciem pomiędzy liniami multipleksu. Ogólnie nie potrzebuję wykorzystywać kilku przycisków jednocześnie. Prawie każdy przycisk ma funkcję +/- wartości licznika od 0 do 10 co 0,5. Jedynie mógłbym wykorzystać dwa przyciski + i - do ustawienia licznika w połowie, czyli na 5

    Początkowo multipleks miałem zbudowany na switch case, ale obecnie jest na if'ach. I wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Ale jeśli switch bardziej by pasował pod przyciski to mogę przerobić z powrotem.
    Tablica mpx zawiera zdefiniowane piny multipleksu. Multipleks jest zbudowany w ten sposób, bo wysyłam dane do 5 rejestrów, a w każdym if'ie/ case'ie jest inna cyfra. Zmienna out miała być wykorzystana do biblioteki klawiatury.



    Cytat:
    W kodzie:

    if (licznik==0) {

    a = PINA & 0x3F;
    switch (a) {
    case 1 : key = '1'; break;
    case 2 : key = '2'; break;
    case 4 : key = '3'; break;
    case 8 : key = '4'; break;
    case 16 : key = '5'; break;
    case 32 : key = '6'; break;
    }

    // WYSYLKA DO SPI
    // ZALACZENIE 1 KOLUMNY
    }


    Nie podobna mi się switch.

    To jest kod z jednego z poprzednich postów.

    Jak będę miał dłuższą chwilę to przysiądę do kodu. Dzięki za zainteresowanie!
  • Poziom 30  
    dyerseve napisał:
    Początkowo multipleks miałem zbudowany na switch case, ale obecnie jest na if'ach. I wygląda tak:

    Ta sama historia co z klawiszami, wystarczy mądrze w
    Kod: c
    Zaloguj się, aby zobaczyć kod

    dodać zmienną licznik np
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Kolejna brzydka rzecz, w przerwaniu zawieszasz program na czas transmisji po SPI. Nie musisz tych danych wysyłać z prędkością 10Mb/s. Multipleksujesz powiedzmy 100Hz (co 20ms) więc czy wyślesz dane w 4us czy 40us a nawet w 400us nie robi różnicy. Możesz więc SPI ustawić na np ok 100kHz i użyć przerwań SPI do transmisji danych do rejestrów 75HC595. W przerwaniu od timera będziesz tylko inicjalizował transmisję SPI.



    PS
    Na forum Atnela to dobrych rad nie dostaniesz jak nie będziesz słał hołdów miłościwie tam panującemu M36 (teraz to chyba M45) i nie kupisz kardasiowych, niepotrzebnych kalkulatorów lub innych przetaktowanych o 20% playerów.
  • Poziom 31  
    LChucki napisał:
    dyerseve napisał:
    Początkowo multipleks miałem zbudowany na switch case, ale obecnie jest na if'ach. I wygląda tak:

    Ta sama historia co z klawiszami, wystarczy mądrze w
    Kod: c
    Zaloguj się, aby zobaczyć kod

    dodać zmienną licznik np
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I co wyjdzie
    Kod: c
    Zaloguj się, aby zobaczyć kod

    i to ma być to samo?
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Zawartość rejestru polecasz przesunąć w prawo o 2 i co w tym przypadku wyjdzie?

    LChucki napisał:
    Nie podobna mi się switch. Co się stanie jak kilka klawiszy naciśniesz równocześnie?
    Dalej, po co if (licznik==0), następnie if (licznik==1) i powtarzasz w kółko to samo? Tu predzej należało zastosować switch. Zrób coś w tym stylu:

    Co Ci się nie podoba w switch. Jak by nie było wskazane używać takiego polecenia to w jakim celu je stworzono, po to tylko by było?
    Zostanie odczytany tylko jeden. W tej klawiaturze niema skrótów klawiszowych tak jak w Windowsie.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tutaj tylko przepisałeś bity z portu do zmiennej key.
    W jakim celu użyłeś if wystarczyło zrobić taki zapis.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Wyjdzie krócej i szybciej.
  • Poziom 30  
    dasej napisał:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Zawartość rejestru polecasz przesunąć w prawo o 2 i co w tym przypadku wyjdzie?

    Wyjdzie to, że nie potrzebuje 4 razy przepisywać prawie tego samego bo zależnie od tego która anoda jest wysterowana, pobiera element tablicy bez przesunięcia lub z przesunięciem o 4, 8 lub 12.

    dasej napisał:

    LChucki napisał:
    Nie podobna mi się switch. Co się stanie jak kilka klawiszy naciśniesz równocześnie?
    Dalej, po co if (licznik==0), następnie if (licznik==1) i powtarzasz w kółko to samo? Tu predzej należało zastosować switch. Zrób coś w tym stylu:

    Co Ci się nie podoba w switch. Jak by nie było wskazane używać takiego polecenia to w jakim celu je stworzono, po to tylko by było?

    Zobacz rozwinięcia asm i czasem zobaczysz różnice pomiędzy case a if.

    dasej napisał:

    Zostanie odczytany tylko jeden. W tej klawiaturze niema skrótów klawiszowych tak jak w Windowsie.

    A niby skąd mam o tym wiedzieć?
    Nie jestem wróżbitom i nie wiem czy autor będzie odczytywał naciśnięcie kilku przycisków czy nie a diody w obwodach klawiatury świadczą, że uwzględnia taki przypadek. Jeśli nie potrzebuje odczytywać naciśnięcia więcej niż jednego klawisza to nie napisał co zrobić gdy tak się stanie. Czy zwrócić "pierwszy" naciśnięty? Może nie zwracać nic?

    dasej napisał:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tutaj tylko przepisałeś bity z portu do zmiennej key.


    Tak, ale nie mam pojęcia co ma być zwracane w key. Widziałem, kody ASCII, wtedy trzeba zastosować konstrukcję if...else więc dałem tylko przykład a jak sobie autor przekoduje odczyty to jego sprawa. Teraz, gdy wiem, że może będzie chciał odczytywać naciśnięcie dwóch przycisków razem trzeba zrobić np
    Kod: c
    Zaloguj się, aby zobaczyć kod

    zakładając, że interesują go kody ASCII a tego nie wiem.

    Dodano po 4 [minuty]:

    Wracając do
    dasej napisał:
    W tej klawiaturze niema skrótów klawiszowych tak jak w Windowsie.


    pewny jesteś?
    dyerseve napisał:
    Jedynie mógłbym wykorzystać dwa przyciski + i - do ustawienia licznika w połowie, czyli na 5
  • Poziom 30  
    dasej napisał:
    @LChucki [CYFRA3+licznik<<2] to jest mnożenie a nie dodawanie, raczej [CYFRA3+(licznik++)]

    Chyba nie wiesz o co mi chodzi. W kodzie miał coś w stylu:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    proponuję:
    Kod: c
    Zaloguj się, aby zobaczyć kod