Algorytm eliminacji drgań styków w klawiaturze 68-klawiszowej z polifoni±

Re: Obsługa klawiatury i drgania styków





Poprzedni Następny
Wiadomo¶ć
Spis tre¶ci
From: "Marek Dzwonnik" <mdz_at_nospam_message.pl>
Subject: Re: Obsługa klawiatury i drgania styków
Date: Tue, 7 May 2002 22:49:21 +0200


Użytkownik "~Filut~" <pawel_at_nospam_filuts.waw.pl> napisał w wiadomo¶ci
news:ab8rii$5ev$1_at_nospam_news.tpi.pl...
Użytkownik <mstanisz_at_nospam_poczta.onet.pl> napisał w wiadomo¶ci
news:56fe.00000e39.3cd7ea64_at_nospam_newsgate.onet.pl...
Czy kto¶ może podesłać przykład algorytmu, który wyeliminował by ten
problem

Tak, ale muszę sprawdzać 68 klawiszy (muzycznych) z założeniem, że może
być
wci¶niętych np 10 klawiszy :(

68 klawiszy i polifonia powiadasz?

To ja Ci napiszę co zazwyczaj robię ze swoimi klawiaturami - może co¶ z tego
wykorzystasz

W obsludze przerwań zegarowych, generowanych co kilka...kilkadziesiąt ms
czytam stan portów klawiatury. Potem zestawiam to co się odczytało z
historią poprzednich odczytów.

Załóżmy, że czytam tylko jeden 8-bitowy port i umieszczam (zanegowany) wynik
odczytu w zmiennej current. Następnie biorę do porównania poprzednie stany
zapamiętane w zmiennych pra1, pra2... (zazwyczaj tyle wystarczy).

(current, pra1, pra2) oznacza klawisz stabilnie wci¶nięty.
(current, pra1, pra2) oznacza klawisz stabilnie zwolniony.

W realizacji C51 wychodzi to mniej wiecej tak:

unsigned char old, stable, delta_on, delta_off, current, pra1, pra2...;
void obsluga_timera() interrupt .. // np. co 10ms
{
/* ble..ble.. to co trzeba zrobic w przerwaniu od timera */

// odczyt portu klawiatury:
// klawisz wcisniety ->
// -> '0' na linii portu
// -> '1' na danym bicie w zmiennej current
current = ~XBYTE[port];

old = stable; // zapamiętujemy dotychczasowe stany stabilne

// nowe stany stabilne
// (wszytkie operacje logiczne - bitowe! )
stable = stable | ( current & pra1 & pra2... ); // stabilne '1'
stable = stable & ( current | pra1 | pra2... ); // stabilne '0'
// zmiany stanu
delta_on = stable & ~old; // wcisniecia: ( nowe_1 and stare_0 )
delta_off = ~stable & old; // wcisniecia ( nowe_0 and stare_1 )

/*
// mozna tez kumulowac info o zmianach stanu
// - zalezy to od sposobu w jaki zdarzenia beda obslugiwane
delta_on = delta_on | (stable & ~old);
delta_off = delta_off | (~stable & old);
*/

// obsluga zdarzen
if (delta_on)
/* sprawdzamy co zostało wci¶niete i robimy co trzeba */
}
if (delta_off)
/* sprawdzamy co zostało zwolnione i działamy */
}

// aktualizujemy historie
// elegancko byloby zrobic jakies FIFO, ale do kilku zmiennych
// chamskie kopiowanie wychodzi najtaniej:
// ... pra3=pra2; // itp.
pra2 = pra1;
pra1 = current;

} // obsluga_timera()


Jeszcze parę słów komentarza:

- caly kawalek kodu cało¶c ląduje w petli ganiajacej po portach
(lub adresuajcej kolejne kolumny matrycy)

- ze zmiennych skalarnych (stable, pra1,...) robią się wektory, albo
lepiej jeden (lub dwa) wektory struktur opisujących stan portu. Ja zwykle
używam dwóch struktur:
* stałej (code) przechowującej adres portu oraz maskę istotnych bitów.
* zmiennej (data) zawierajacej stan klawiszy (stable, pra1, pra2... i
ew. delta_on, delta_off do asynchronicznej obslugi zdarzen)

częsc musi trwac krótko, np.:
- w przerwaniu tylko ustawiać bitową flagę kbd_event.
- resztę obslugi robić, w petli - w wątku podstawowym;
(ten sposob wymaga wlasnie kumulacji delta_on i delta_off) np:

// watek podstawowy
while (1)
{
if (kbd_event)
{
kbd_event = 0;
DISABLE_INT;
delta_on_kopia = delta_on;
delta_on = 0;
delta_off_kopia = delta_off;
delta_off = 0;
ENABLE INT;

/*
czytamy kolejne bity z delta_on_kopia i delta_off_kopia
podejmujemy dzialania zwiazane z obsluga zdarzen
/*
}

} // if
} // while

- obsluga w ten sposób ma o tyle zaletę, opóźnienie reakcji na każdy
klawisz jest identyczne i stałe.
- do czytania u-switchy calkowicie wystarczy np. T=10ms i dwa poziomy
historii pra1, pra2
- przyjecie T=15ms i 3 poziomow historii da 60ms opoznienia i powinno
wystaczyc do pozbycia sie trzaskow z klawiszy foliowych
- opóznienie 60ms powinno byc akceptowalne dla grajka

--
Marek Dzwonnik mdz_at_nospam_message.pl
GG: #2061027 (zwykle jako 'dostępny-niewidoczny')




Poprzedni Następny
Wiadomo¶ć
Spis tre¶ci
From: "Marek Kaprynski" <marekk_at_nospam_comms.eee.strath.ac.uk>
Subject: Re: Obsługa klawiatury i drgania styków
Date: Wed, 8 May 2002 10:16:06 +0100



Marek Dzwonnik <mdz_at_nospam_message.pl> wrote in message
news:3cd83d32_at_nospam_news.home.net.pl...

To ja Ci napiszę co zazwyczaj robię ze swoimi klawiaturami - może co¶ z
tego
wykorzystasz

W obsludze przerwań zegarowych, generowanych co kilka...kilkadziesiąt ms
czytam stan portów klawiatury. Potem zestawiam to co się odczytało z
historią poprzednich odczytów.

Ja zrobilem to troche inaczej, jakkolwiek tez w tym kierunku :-)
Odczyt klawiszy realizuje przerwanie (ktore zreszta wykorzystuje tez do
wyswietlania) - jesli nastapilo wcisniecie klawisza, jest to zapamietywane i
rozpoczyna sie zwiekszanie zmiennej, ktora przez zadany czas (liczbe wywolan
przerwania) musi pozostac w niezmienionym stanie. Jesli to sie uda klawisz
jest uznawany za wcisniety.
Jesli w miedzy czasie styki sie rozwarly, licznik jest kasowany (juz bez
jakiegokolwiek czekania). W sumie to podobna technika, z tym ze dlugosc
"pamieci historii" okreslam poczatkowa wartoscia licznika.

Pozdrawiam

Marek



Poprzedni Następny
Wiadomo¶ć
Spis tre¶ci
From: "Marek Dzwonnik" <mdz_at_nospam_message.pl>
Subject: Re: Obsługa klawiatury i drgania styków
Date: Wed, 8 May 2002 13:14:34 +0200


Użytkownik "Marek Kaprynski" <marekk_at_nospam_comms.eee.strath.ac.uk> napisał w
wiadomo¶ci news:abaqd3$oc1$1_at_nospam_dennis.cc.strath.ac.uk...
Ja zrobilem to troche inaczej, jakkolwiek tez w tym kierunku :-)
Odczyt klawiszy realizuje przerwanie (ktore zreszta wykorzystuje tez do
wyswietlania) - jesli nastapilo wcisniecie klawisza, jest to zapamietywane
i
rozpoczyna sie zwiekszanie zmiennej, ktora przez zadany czas (liczbe
wywolan
przerwania) musi pozostac w niezmienionym stanie. Jesli to sie uda klawisz
jest uznawany za wcisniety.
Jesli w miedzy czasie styki sie rozwarly, licznik jest kasowany (juz bez
jakiegokolwiek czekania). W sumie to podobna technika, z tym ze dlugosc
"pamieci historii" okreslam poczatkowa wartoscia licznika.

Z tym, że takie rozwiązanie wymaga albo osobnego licznika dla każego
klawisza (pytanie dotyczyło 68 szt., z czego do 10 jednocze¶nie), albo
pewnej puli liczników przydzielanych dynamicznie - co trochę komplikuje
sprawę. Kiedy¶ stosowałem jeszcze inne rozwiązanie. Kolejne bity odczytywane
z linii portu wsuwałem do rejestru przesuwnego. A następnie badałem, czy na
N młodszych bitach występują same zera lub same jedynki. Ale niestety
wychodziło to raczej nieefektywnie.

Rozwiązanie, które stosuję obecnie, ma dla mnie następujące zalety:
czasu dla paru innych rzeczy (m.in. programowe liczniki czasu).


matrycy) i daje informację zarówno o zmianach (+) jak i (-).

porcie klawisze wiszą tylko na kilku liniach, nalożenie maski pozwala na
szybkie wyeliminowanie reakcji na zmiany stanu pozostałych linii

!=0 lub delta_off!=0 ), a dopiero następnie rozpoznawać bit po bicie co
zostało wci¶niete. Zdarzenia 'kbd' są stosunkowo rzadkie, dzieki czemu
eliminiuje się sporo pustego przeglądania.

rozbudowanego mechanizmu komuniaktów.

(stable.bit). Dzięki temu łatwo zrobić obsługę kombinacji typu
Shift-cos_tam.

strukturach w pamięci programu (code). Tzn. adresy portow, maski, kody i
adresatow komunikatow (zdarzen) przypisanych do danego klawisza itp. Daje to
b. dużą elastyczno¶ć, dzięki czemu np. w swoich zastosowaniach mogę
traktować w ten sam sposób zarówno przyciski jak i inne czujniki
(indukcyjne, optyczne).

MDz





Poprzedni Następny
Wiadomo¶ć
Spis tre¶ci
From: "~Filut~" <pawel_at_nospam_filuts.waw.pl>
Subject: Re: Obsługa klawiatury i drgania styków
Date: Wed, 8 May 2002 17:36:56 +0200


Użytkownik "Marek Dzwonnik" <mdz_at_nospam_message.pl> napisał w wiadomo¶ci
news:3cd907f9_at_nospam_news.home.net.pl...
Użytkownik "Marek Kaprynski" <marekk_at_nospam_comms.eee.strath.ac.uk> napisał w
wiadomo¶ci news:abaqd3$oc1$1_at_nospam_dennis.cc.strath.ac.uk...
Ja zrobilem to troche inaczej, jakkolwiek tez w tym kierunku :-)
Odczyt klawiszy realizuje przerwanie (ktore zreszta wykorzystuje tez do
wyswietlania) - jesli nastapilo wcisniecie klawisza, jest to
zapamietywane
i
rozpoczyna sie zwiekszanie zmiennej, ktora przez zadany czas (liczbe
wywolan
przerwania) musi pozostac w niezmienionym stanie. Jesli to sie uda
klawisz
jest uznawany za wcisniety.
Jesli w miedzy czasie styki sie rozwarly, licznik jest kasowany (juz bez
jakiegokolwiek czekania). W sumie to podobna technika, z tym ze dlugosc
"pamieci historii" okreslam poczatkowa wartoscia licznika.

Z tym, że takie rozwiązanie wymaga albo osobnego licznika dla każego
klawisza (pytanie dotyczyło 68 szt., z czego do 10 jednocze¶nie), albo
pewnej puli liczników przydzielanych dynamicznie - co trochę komplikuje
sprawę. Kiedy¶ stosowałem jeszcze inne rozwiązanie. Kolejne bity
odczytywane
z linii portu wsuwałem do rejestru przesuwnego. A następnie badałem, czy
na
N młodszych bitach występują same zera lub same jedynki. Ale niestety
wychodziło to raczej nieefektywnie.


Wła¶nie skończyłem pisać program z użyciem bufora cyklicznego (szkoda, że
nie ma w PIC`u tak jak w DSP Motoroli (56000) specjalnych rejestrów) i
opisanego przez ciebie algorytmu. Na 16 klawiszach działa ! (efek
wyeliminowany).
Jutro podepnę resztę - zobaczymy. Coraz mniej mam pamięci programu :(
W najgorszym przypadku dam opóźnienia (~6-10 ms).
Mój instrument będzie dla "spokojnego" muzyka ;)

Pozdrawiam






Poprzedni Następny
Wiadomo¶ć
Spis tre¶ci
From: "Marek Kaprynski" <marekk_at_nospam_comms.eee.strath.ac.uk>
Subject: Re: Obsługa klawiatury i drgania styków
Date: Wed, 8 May 2002 18:08:52 +0100



Marek Dzwonnik <mdz_at_nospam_message.pl> wrote in message
news:3cd907f9_at_nospam_news.home.net.pl...
Użytkownik "Marek Kaprynski" <marekk_at_nospam_comms.eee.strath.ac.uk> napisał w
wiadomo¶ci news:abaqd3$oc1$1_at_nospam_dennis.cc.strath.ac.uk...
Ja zrobilem to troche inaczej, jakkolwiek tez w tym kierunku :-)
Odczyt klawiszy realizuje przerwanie (ktore zreszta wykorzystuje tez do
wyswietlania) - jesli nastapilo wcisniecie klawisza, jest to
zapamietywane
i
rozpoczyna sie zwiekszanie zmiennej, ktora przez zadany czas (liczbe
wywolan
przerwania) musi pozostac w niezmienionym stanie
[...]
Z tym, że takie rozwiązanie wymaga albo osobnego licznika dla każego
klawisza (pytanie dotyczyło 68 szt., z czego do 10 jednocze¶nie),
Zgadza sie... ja mam aktualnie dwa klawisze, wiec to nie problem :-)
albo pewnej puli liczników przydzielanych dynamicznie - co trochę
komplikuje
sprawę.
Ano... w asemblerze PIC'a tego sie nie podejme :-)))

Kiedy¶ stosowałem jeszcze inne rozwiązanie. Kolejne bity odczytywane
z linii portu wsuwałem do rejestru przesuwnego. A następnie badałem, czy
na
N młodszych bitach występują same zera lub same jedynki. Ale niestety
wychodziło to raczej nieefektywnie.

Rozwiązanie, które stosuję obecnie, ma dla mnie następujące zalety:
- przerwanie 10ms odpowiednie dla klawiatury, jest jednocze¶nie podstawą
czasu dla paru innych rzeczy (m.in. programowe liczniki czasu).
U mnie tez sie doczepiam do przerwania sterujacego wyswietlaniem kolejnych
cyfr na wysw. 7-seg.

- na historię jednego klawisza przypadają zaledwie 3..4 bity.
No wlasnie tu lezy roznica - u mnie to jest 8 bitow...
- wstępna obróbka 8 klawiszy odbywa się równolegle (np. całej kolumny
matrycy)
Duza zaleta - szczegolnie przy wiekszych klawiaturach...

inne czujniki
(indukcyjne, optyczne).
A propos czujnikow - potrzebuje zrobic czujnik zblizeniowy, na poczatku
pomyslalem o podczerwieni (fotodioda (mi sie trafila PIN) i dioda IR). Tylko
ma to jedna wade dla mnie - do dzialania czujnika potrzebna jest aktywnosc
procesora, a ja myslalem coby go uspic i obudzic przerwaniem... a aktywnego
procesora potrzebuje by caly czas nie swiecic diodka. Pomyslalem tak - jak
przerwanie ma sprawdzic czy czujnik jest aktywny to zapala diodke, sprawdza
stan wejscia, gasi diodke i wychodzi. Powinno byc to dosc energooszczedne...
ale z usypiania trzeba w tym przypadku zrezygnowac. A swoja droga to tego
PIN'a chyba sfajczylem :-(((
Moze ma ktos gotowe rozwiazanie takiego czujnika ?

Pozdrawiam

Marek



Poprzedni Następny
Wiadomo¶ć
Spis tre¶ci
From: "Marek Dzwonnik" <mdz_at_nospam_message.pl>
Subject: Re: Obsługa klawiatury i drgania styków
Date: Wed, 8 May 2002 19:45:59 +0200


Użytkownik "Marek Kaprynski" <marekk_at_nospam_comms.eee.strath.ac.uk> napisał w
wiadomo¶ci news:abbm3i$2ek$1_at_nospam_dennis.cc.strath.ac.uk...

A propos czujnikow - potrzebuje zrobic czujnik zblizeniowy, na poczatku
pomyslalem o podczerwieni (fotodioda (mi sie trafila PIN) i dioda IR).
Tylko
ma to jedna wade dla mnie - do dzialania czujnika potrzebna jest aktywnosc
procesora, a ja myslalem coby go uspic i obudzic przerwaniem... a
aktywnego
procesora potrzebuje by caly czas nie swiecic diodka. Pomyslalem tak - jak
przerwanie ma sprawdzic czy czujnik jest aktywny to zapala diodke,
sprawdza
stan wejscia, gasi diodke i wychodzi. Powinno byc to dosc
energooszczedne...
ale z usypiania trzeba w tym przypadku zrezygnowac. A swoja droga to tego
PIN'a chyba sfajczylem :-(((
Moze ma ktos gotowe rozwiazanie takiego czujnika ?


Do tej pory miałem do czynienia tylko z prostymi czujnikami optycznymi
(transmisyjne nad->odb, odbiciowe - od obiektu, refleksyjne - od
odbły¶nika).
Z tym, że czynnie używałem tylko czujników odbiciowych. (np. takich:
www.sels.com.pl -> SCOO-1000 ). Dobry wynalazek, gdy trzeba wykryć z
powtarzalno¶cią np. 10mm pojawienie się jakiego¶ obiektu w odległo¶ci
kilkudziesięciu cm od czujnika. W zasadzie traktowałem je jak czarną
skrzynkę z gotową zahermetyzowaną optyką i elektroniką w ¶rodku oraz
wyj¶ciem on/off na zewnątrz. Z tym, że nie miałem żadnej potrzeby
oszczędnego gospodarowania energią (maszyna i tak bierze do 40kW :-). ZTCP
taki czujnik bierze ok. 20mA i w zasadzie można by kluczować mu zasilanie.
ale nie wiem czy ma to sens w Twoim przypadku.

--
Marek Dzwonnik mdz_at_nospam_message.pl
GG: #2061027 (zwykle jako 'dostępny-niewidoczny')