Ten tekst powstał na zamówienie Niebezpiecznik.pl. Nie został jednak tam opublikowany, a ja zostałem „zghostowany” (?!). Może to znaczy, że ten tekst jest tak zły, że nie warty dalszej uwagi, ale ja się nad nim napracowałem, więc publikuję go tutaj. Jest i dobra okazja 21 urodziny tego bloga.
To teraz coś z zupełnie innej beczki – owocowo warzywna klawiatura midi:
a działa to tak:
Pomysł
Pomysł nie jest ani oryginalny, ani nowy. Już lata temu widziałem na YouTube jak ktoś gra na jakichś owocach i bardzo mi się to wtedy spodobało. Kiedyś nawet chciałem sobie kupić takie urządzenie do zabawy, ale zobaczyłem ceny i zrezygnowałem.
Gdy zacząłem sam się bawić w konstruowanie grającej elektroniki (własny syntezator modułowy) pomysł powrócił, jako „coś, co kiedyś zrobię”. Ostateczną motywację dał mi kolega z Warsztatu Miejskiego który akurat robił zupełnie inny projekt z czujnikami dotykowymi (kupnymi). Zapadła decyzja: robię to teraz, a nie „kiedyś”.
Najpierw prototyp, żeby sprawdzić, czy to w ogóle będzie działać tak, jak sobie wyobrażam, że może działać. Oczywiście poczytałem o czujnikach pojemnościowych, ale nie chciałem używać albo kopiować jakiegoś istniejącego projektu.
Zasada działania
Każde dwa przewodniki oddzielone jakimś izolatorem tworzą kondensator. Większa powierzchnia przewodnika – większa pojemność kondensatora. Dwa piny wyprowadzone z płytki drukowanej to już kondensator, ale o pojemności tak małej, że w większości przypadków pomijalnej. Jednak, gdy człowiek dotknie takiego pinu, to staje się częścią obwodu, zwiększając znacznie powierzchnię przewodzącą. Pojemność istotnie rośnie.
Kondensator może się ładować albo rozładowywać. Czas ładowania i rozładowywania jest proporcjonalny do pojemności kondensatora i do oporu elektrycznego drogi którą ładunki wpływają lub wypływają. Tak więc można zmierzyć pojemność licząc czas w którym się ładuje albo rozładowuje.
W tym przypadku nie muszę dokładnie mierzyć pojemności, wystarczy, że układ rozpozna, że pojemność wejścia istotnie się zwiększyła.
Wykorzystuję tu jedno wyprowadzenie (GPIO – uniwersalne wejście/wyjście) mikrokontrolera najpierw do naładowania naszego kondensatora, a potem do zmierzenia czasu w którym się rozładuje. Wysyłam na to wyjście ‚1’, czyli napięcie 3.3 V i zaraz po tym przełączam wyprowadzenie w tryb wejścia (żeby odczytywać jego stan) o wysokiej impedancji (rezystancji – żeby samo nie rozładowywało kondensatora).
Wyprowadzenie mikrokontrolera jest połączone rezystorem 10 MΩ do masy układu, dzięki czemu nasz kondensator rozładowuje się wystarczająco powoli, żeby można było to zmierzyć. mikrokontroler po prostu czeka aż z ‚1’ na tym wejściu zrobi się ‚0’, a czas po którym nastąpiła zmiana zależy od tego czy dotykamy wejścia, czy nie.
W praktyce wejście układu nie jest podłączone bezpośrednio do pinu mikrokontrolera, po drodze jest jeszcze rezystor i kondensator.
Kondensator izoluje wejście jednocześnie zabezpieczając mikrokontroler i zapewniając prawidłowe działanie nawet, gdy wejście zewrze się z masą. Z punktu widzenia mikrokontrolera dla naszego algorytmu ten dodatkowy kondensator jakby nie istnieje – jest połączony szeregowo z mierzoną pojemnością i ma sporo większą wartość niż mierzona, więc wypadkowa pojemność jest i tak zbliżona do tej, którą chcemy zmierzyć (szeregowe połączenia kondensatorów tak mają).
Dodatkowy rezystor zabezpiecza układ przed wyładowaniami elektrostatycznymi – ogranicza prąd który może przepłynąć przy nagłym skoku napięcia.
Projekt
Prototyp był prosty, ale w głowie już miałem wizję całego projektu:
- Jako serce układu płytka z mikrokontrolerem Raspberry Pi Pico. Bo tani, bo
znam, bo lubię. - 16 czujników, bo to okrągła liczba i mieści się cała chromatyczna oktawa (12
dźwięków). Jakby ograniczyć się do skali diatonicznej, to zmieszczą się dwie
oktawy. - Adresowalne diody LED (WS2812B) pokazujące stan klawiszy – prościej, a przez
to pewnie i taniej niż jakbym miał 16 LEDów sterować bezpośrednio (w samym Pi
Pico by pinów brakło). Do tego kolorki „gratis”. - Tradycyjne wyjście MIDI (gniazdo DIN-5) oraz MIDI przez USB. Żeby dało się
podłączyć i mój „pół-analogowy” syntezator modułowy, i chociażby smartfona. - Przycisk do kalibracji, potencjometr do ustawiania czułości.
- No i dodatkowe wejście zasilające, bo czemu by nie?
Schemat i projekt płytki drukowanej przygotowałem w programie KiCAD.
Płytkę zaprojektowałem dość specyficznie (miejscami niekoniecznie zgodnie z przyjętymi praktykami), bo z myślą o metodzie w jakiej ją wykonam. Jednak i tak dość ambitnie – dwustronną, na drobne elementy SMD.
Wykonanie
Płytki drukowanej nie zamawiałem w Chinach (typowe rozwiązanie w dzisiejszych czasach), ani nie trawiłem (tradycyjna metoda). Użyłem mini frezarki CNC, którą mamy w Warsztatacie Miejskim w Gliwicach do wycięcia w miedzi izolacji między ścieżkami na płytce.
Pliki Gerber z KiCAD przerobiłem na gcode (język maszyn CNC) przy pomocy pcb2gcode, potem jeszcze przerobiłem moim skryptem, żeby wygodniej się w bCNC tego używało.
Nie udało się za pierwszym razem. Szło dobrze, ale częściowo za płytko, żeby przeciąć warstwę miedzi – to dlatego, że płytka nie była idealnie równa. Gdy próbowałem to poprawić, to tylko pogorszyłem sprawę i zniszczyłem płytkę oraz złamałem frez.
Za drugim razem wykorzystałem opcję auto-poziomowania w programie bCNC i starałem się być nieco
ostrożniejszy. I się udało. Dopiero pod koniec robienia drugiej strony maszyna nieco zaczęła świrować, ale tym razem niczego to nie zepsuło.
Frezarka też precyzyjnie wywierciła mi otwory. No może trochę za płytko, ale
to już błąd operatora.
Gdy płytka była gotowa i zrobiłem przelotki z mosiężnych nitów, przyszedł czas
na lutowanie. Malutkie elementy SMD to wyzwanie. Brak soldermaski (nie umiem
jej zrobić domowymi metodami) dodatkowo utrudniał. Mimo to poszło mi całkiem
sprawnie. Po paru drobnych poprawkach układ był gotowy. I zadziałał!
Oprogramowanie
Firmware urządzenia napisałem w Rust wykorzystując świetny asynchroniczny framework Embassy.
Nie Python, bo chociaż znam go najlepiej, to nie wydaje mi się najlepszym narzędziem do takiego zastosowania. I pewnie byłby po prostu za wolny.
Naturalny wyborem byłoby C – to standard w zastosowaniach wbudowanych i właśnie w C dostarczane jest oficjalne SDK do Raspberry Pi Pico. Jednak w C strasznie łatwo o głupie błędy, które potem trudno wyłapać i poprawić. A w ogóle dobrze się nauczyć czegoś nowego.
Narzędzia Rust okazały się też wiele wygodniejsze w użyciu niż oficjalne SDK.
Program po włączeniu zasilania świeci diodami na kolorowo, a następnie rozpoczyna proces kalibracji. Mierzy czasy rozładowywania każdego z pinów. Użytkownik powinien dotknąć przynajmniej jednego „klawisza”, a najlepiej kilku. Program wtedy zbierze informacje o minimalnych i maksymalnych zarejestrowanych czasach. Na tym etapie wykrywane są też anomalie (zbyt długi czas rozładowania,
jak w przypadku gry wejście jest zwarte do masy). Przyciśnięcie przycisku kończy kalibrację.
W wyniku kalibracji ustalony jest próg załączenia, który można dodatkowo regulować potencjometrem. Teraz program po prostu wysyła co chwilę „1” na odpowiednie wyjścia kontrolera, czeka ustalony czas (ten próg załączenia), i sprawdza które wejścia zmieniły się w tym czasie z „1” na „0”. Wejścia które
nie zmieniły stanu (nie zdążyły się rozładować) zostają uznane za „wciśnięte klawisze”, a zmiana stanu „klawisza” powoduje wysłanie komunikatu MIDI: „note on”, albo „note off” – przez port szeregowy i przez USB.
Kod źródłowy, jak i projekt w KiCAD dostępne są na GitHub: https://github.com/Jajcus/midi_touch_keyboard
Co dalej?
Spróbuję zbudować jeszcze do tego obudowę (w Warsztacie Miejskim mamy też drukarkę 3D) i dodać nowe funkcje w oprogramowaniu (transpozycja i przełączanie w tryb diatoniczny). A potem projekt pójdzie na półkę, gdzie inne urządzenia, które kiedyś zbudowałem i nigdy więcej nie użyłem.