Teensy – Obsługa dotyku

obrazekDziś temat będzie prosty i krótki. Przeglądając pinout płytek Teensy możemy natknąć się na piny podpisane „Touch”. W jaki sposób one działają i jak je wykorzystać w praktyce? Tego dowiemy się podczas lektury tego artykułu.

Na początek trochę teroii…

Aby obsłużyć dotyk będziemy potrzebowali pary pinów (send oraz receive). Pin send podłączamy do kawałka miedzianego laminatu, taśmy miedzianej lub innego przewodnika poprzez rezystor o dużej wartości (w opisie biblioteki jest mowa o rezystorach w zakresie 100 kΩ – 50 MΩ). Im większego rezystora użyjemy tym z większej odległości nasz czujnik zacznie wykrywać obecność ręki. Pin receive podłączamy natomiast do naszego przewodnika przez rezystor małej wartości np. 1 kΩ. Równie dobrze możemy podłączyć nasz dotykowy odbiornik z pominięciem tego rezystora, ale ryzykujemy wtedy uszkodzenie Teensy w przypadku gdybyśmy byli naelektryzowani i przeskoczyłaby iskra. Dodatkowo możemy zabezpieczyć się przyklejając na powierzchnię przewodnika, który będziemy dotykać kawałek taśmy izolacyjnej (wtedy już żadne iskry nam nie groźne). Oba piny (send i receive) podłączamy do GPIO, oznaczonego jako „Touch”. Pinouty płytek Teensy możemy znaleźć tutaj.

Zasada działania jest prosta. Pin send zaczyna nadawać stan X. W tym samym momencie klasa CapacitiveSensor zaczyna mierzyć czas. Kiedy na pin receive dotrze stan X kończy się mierzenie czasu i zwracana jest wartość. Im większy czas został zmierzony tym większa pojemność płytki dotykowej.

Każdą płytkę musimy podłączyć do osobnego pinu działającego jako receive, natomiast pin send może być współdzielony przez wszystkie płytki dotykowe.

UWAGA! Jeżeli zasilamy Teensy z laptopa, który pracuje na baterii to musimy uziemić masę układu. Najprościej będzie podłączyć pin GND do grzejnika lub laptopa do zasilacza.

Co będzie potrzebne?

  • Teensy,
  • duży rezystor np. 4,7 mΩ,
  • mały rezystor np. 2,2 kΩ,
  • kawałek miedzianego laminatu lub czegoś podobnego

Podłączenie oraz kod źródłowy

W poniższym przykładzie użyłem pinów 16 i 15 kolejno jako send i receive. Użyte rezystory to 4,7 MΩ i 1,1 kΩ. Kod jest bardzo prosty i krótki więc wkleję go tutaj:

#include <CapacitiveSensor.h>

CapacitiveSensor touch = CapacitiveSensor(16,15);
const int ledPin = 13;
long result;

void setup() {
 pinMode(ledPin, OUTPUT);
 Serial.begin(9600);
}

void loop() {
 result = touch.capacitiveSensor(20);
 if(result > 30000) {
 digitalWrite(ledPin, HIGH);
 } else {
 digitalWrite(ledPin, LOW);
 }

 Serial.println(result);
 delay(10);
}

Na początku tworzymy obiekt klasy CapacitiveSensor. Pierwszy parametr konstruktora to numer pinu send, drugi to receive. Metoda capacitiveSensor przyjmuje jeden parametr – ilość próbek (im więcej tym dokładniejszy, lecz wolniejszy pomiar). Zwraca ona liczbę typu long. Jeśli zwróci -1 oznacza to, że wystąpił błąd pomiaru.

Po wgraniu kodu możemy przystąpić do analizy tego, co się dzieje.

Testy

Odpalmy Monitor portu szeregowego (Ctrl / Command + Shift + L), aby wyniki prezentowały się na łatwym do czytania wykresie.

Brak dotyku
Brak dotyku
Wykrycie dotyku
Wykrycie dotyku

 

Wykres result(t)
Wykres result(t)

Jak widać wykres jest dość stabilny i z łatwością można rozróżnić gdzie jest dotyk, a gdzie go nie ma, stąd też warunek w moim kodzie załączający LED’a na płytce. Wybrałem próg 30 tys., ponieważ jest mniej więcej po środku skali dzięki czemu eliminujemy przypadkowe zakłócenia. Oczywiście jeżeli nakleiłbym warstwę taśmy izolacyjnej na moją miedzianą płytkę to wartości dla stanu wysokiego poleciałyby mocno w dół. Stąd też jeżeli chcemy mieć przełącznik działający w różnych warunkach musimy napisać funkcję kalibrującą, która będzie ustawiała optymalny próg między stanem niskim a wysokim lub opracować jakiś uniwersalny algorytm (np. porównujący wynik aktualny ze średnią z ostatnich pomiarów i wykrywający odchylenia).

A co z funkcją touchRead?

W tym artykule postanowiłem skupić się bardziej na klasie CapacitiveSensor niż na funkcji touchRead z jednego prostego powodu. Funkcja touchRead daje dużo mniej dokładne wyniki. Oto wykres wygenerowany przy użyciu owej funkcji:

Wykres result(t) przy użyciu funkcji touchRead()
Wykres result(t) przy użyciu funkcji touchRead()

Widać, że wykres ten jest bardzo poszarpany jeśli dotkniemy płytki. Należy zwrócić także uwagę na skalę osi Y. Przy takiej skali nieco trudniej postawić kreskę oddzielającą stan niski od wysokiego i dużo łatwiej o zakłócenia. Na korzyść funkcji touchRead przemawia fakt, że potrzebujemy dla niej tylko pinu receive, który podajemy jako jej parametr.