Ten post będzie krótkim projektem jaki wykonałem na nowych dla mnie mikrokontrolerach PSOC4. W obsłudze poprzez wbudowane biblioteki są one niezwykle proste.
Po zainstalowaniu środowiska i włączeniu czystego projektu można rozpocząć pracę z układem. Dosyć dużo informacji można znaleźć na youtubie na kanale Future Electronics. Ja tutaj przedstawię tylko kod programu oraz opis poszczególnych bloków, przynajmniej tych z których ja korzystałem.
Program
Dosyć dużym ułatwieniem jest tworzenie programu w środowisku graficznym. Można go trochę porównać do CubeMx. Z wyglądu wydaje się trochę uboższe natomiast funkcyjnie daje bardzo dużo możliwości.
Pierwszą podstawową rzeczą jest dołączenie bloku Bootloadable, u mnie w wersji 1.50. Pozwala on na zaprogramowanie mikrokontrolera poprzez interfejs UART. Dla mnie jest to jedyna opcja ponieważ posiadam układ CY8CKIT-049-42xx za 4 dolary, który jak na swoje możliwości jest niesamowicie tani i pozwala na wykonanie bardzo wielu zadań.
Jedynym jego minusem jest to, że trzeba go wpinać i wypinać z portu USB co jest odrobinę niekomfortowe. Dodatkowo może pojawić się taka sytuacja że po podłączeniu program nie będzie widział płytki. W takim przypadku nie pomogą restarty itp. Trzeba odinstalować sterowniki USB-Serial SDK 2.0. Po czym zainstalować je ponownie. U mnie tylko w taki sposób problem zanikł, przynajmniej na teraz.
Wracając do bloku Bootloadable, to w nim wystarczy tylko skonfigurować zakładkę Dependencies, gdzie wskazuje się na plik, z przykładu SCB_Bootloader (trzeba go skompilować i stworzyć z przykładowych aplikacji). Sciezka do niego to:
UART_Bootloader.cydsn\CortexM0\ARM_GCC_493\Debug\UART_Bootloader.hex
Następny w kolejności jest wyświetlacz LCD. Jego należy dodać poprzez przeciągnięcie z Cypress Component Catalog bloku Character LCD. W moim przypadku była to wersja 2.20.
Jedynym konfigurowalnym elementem jaki tu ustawiłem jest czcionka oraz zaznaczenie bloku dołączenia kodu ASCII.
Następnie blok UART (UART (SCB mode)):
No i wreszcie najważniejszy z nich czyli blok Capsense.
W przypadku płytki PCB z wyprowadzonymi elektrodami, do testów wstępnych można zastosować kawałek kabla czy drutu podłączonego przez rezystor 560 Ohm do skonfigurowanego pinu. Producenci dopuszczają rezystory o wartościach od 560 do 1kOhm. Jest to głównie zależne od firmy jakiej rozwiązanie będzie stosowane.
Jeśli jest w posiadaniu płytka z przygotowanymi polami dotykowymi to podłączenie jakie należy wykonać wygląda następująco:
Więcej przydatnych materiałów oraz informacji można znaleźć w tym dokumencie.
To testów dobrze jest podłączyć pola odpowiedzialne za masę oraz shielda. Pozwalają one znacznie bardziej polepszyć działanie dotyku.
W przypadku klawiatur pojemnościowych duże znaczenie ma część sprzętowa. Należy się upewnić, że została ona przygotowana zgodnie z tym, co zostało przygotowane w notce producenta. Pozwoli to na poprawne działanie, przynajmniej z tej strony.
Ważne jest także aby odpowiednio poprowadzić pole masy. Należy je zaprojektować w formie siatki, nie powinno być jako pole pełne. Poprawi to znacząco odczuwanie dotyku, ponieważ masa w formie pełnej zwiększy wartości pojemności.
Sam kształt pola też nie jest bez znaczenia:
W przypadku klawiatur pojemnościowych duże znaczenie ma część sprzętowa. Należy się upewnić, że została ona przygotowana zgodnie z tym, co zostało przygotowane w notce producenta. Pozwoli to na poprawne działanie, przynajmniej z tej strony.
Ważne jest także aby odpowiednio poprowadzić pole masy. Należy je zaprojektować w formie siatki, nie powinno być jako pole pełne. Poprawi to znacząco odczuwanie dotyku, ponieważ masa w formie pełnej zwiększy wartości pojemności.
Sam kształt pola też nie jest bez znaczenia:
[AN64846 - str 71.]
Jak widać na obrazku powyżej najlepiej stosować pola okrągłe, opcjonalnie jako pełne z dziurą na diodę.
Same przyciski powinny być oddzielone od palca poprzez warstwę kawałka sztucznego materiału, co znacznie poprawi wygodę użytkowania, oraz pozwoli na dokładne sprawdzenie jakości programu.
PSOC:
Poniżej przejdę przez opis programu jaki przygotowałem do odczytania dotyku z klawiatury pojemnościowej z użyciem bibliotek jakie zostały udostępnione przez producenta.
W programie zdefiniowałem 8 przycisków pojemnościowych oraz jeden czujnik zbliżeniowy.
Wszystkie bloki dodane zostają:
Po dodaniu bloków należy zdefiniować odpowiednio każdy z nich.
Blok USART:
W bloku Capsense dodane zostało 8 przycisków oraz jeden czujnik zbliżeniowy.
Przykładowe opisane dane dla przycisków:
W głównej części, czyli w pierwszym oknie od prawej u góry zdefiniowany został rodzaj filtru oraz aktywny system ochrony dla wody znajdującej się na przyciskach. Pozwoli to na niewywoływanie przypadkowych kliknięć dla płynu znajdującego się na przycisku.
Podłączenie wszystkich linii:
Blok PWM dla diody:
Blok PWM dla buzzera:
Po przygotowaniu projektu w części graficznej należy wejść w opcje Build -> Generate Aplication. Co spowoduje przygotowanie projektu, dołączenie bibliotek itp.
Po tym w części głównej można dodać elementy w części głównej. Dzięki temu, że wykorzystywano bibliotekę część programowa jaką należy dodać jest bardzo krótka.
- /* ========================================
- *
- * Copyright YOUR COMPANY, THE YEAR
- * All Rights Reserved
- * UNPUBLISHED, LICENSED SOFTWARE.
- *
- * CONFIDENTIAL AND PROPRIETARY INFORMATION
- * WHICH IS THE PROPERTY OF your company.
- *
- * ========================================
- */
- #include "project.h"
- #include "stdio.h"
- void CapSense_DisplayState(void);
- int main(void)
- {
- char buffer[10];
- uint16_t value = 0;
- CyGlobalIntEnable; /* Enable global interrupts. */
- LCD_Char_1_Start();
- LCD_Char_1_Position(0u, 0u);
- LCD_Char_1_ClearDisplay();
- UART_Start();
- UART_UartPutString("Hello World\n\r");
- UART_UartPutString("dziala dziala\n\r");
- CapSense_1_Start();
- CapSense_1_EnableWidget(CapSense_1_PROXIMITYSENSOR0__PROX);
- UART_UartPutString("CapSense start\n\r");
- CapSense_1_InitializeAllBaselines();
- UART_UartPutString("InitializeAllBaselines\n\r");
- CapSense_1_ScanEnabledWidgets();
- PWM_1_Start();
- PWM_2_Start();
- UART_UartPutString("PWM_1_Start\n\r");
- /* Place your initialization/startup code here (e.g. MyInst_Start()) */
- for(;;)
- {
- CapSense_1_ScanEnabledWidgets();
- while(CapSense_1_IsBusy() != 0) { }
- CapSense_DisplayState();
- CapSense_1_UpdateEnabledBaselines();
- /* Place your application code here. */
- }
- }
- void CapSense_DisplayState(void)
- {
- static uint8_t previous_state;
- LCD_Char_1_Position(0u, 0u);
- if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON0__BTN))
- {
- PWM_1_WriteCompare(20);
- LCD_Char_1_PrintString("Button_1");
- UART_UartPutString("Przycisk_1\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON1__BTN))
- {
- PWM_1_WriteCompare(40);
- LCD_Char_1_PrintString("Button_2");
- UART_UartPutString("Przycisk_2\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON2__BTN))
- {
- PWM_1_WriteCompare(60);
- LCD_Char_1_PrintString("Button_3");
- UART_UartPutString("Przycisk_3\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON3__BTN))
- {
- PWM_1_WriteCompare(80);
- LCD_Char_1_PrintString("Button_4");
- UART_UartPutString("Przycisk_4\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON4__BTN))
- {
- PWM_1_WriteCompare(80);
- LCD_Char_1_PrintString("Button_5");
- UART_UartPutString("Przycisk_5\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON5__BTN))
- {
- PWM_1_WriteCompare(80);
- LCD_Char_1_PrintString("Button_6");
- UART_UartPutString("Przycisk_6\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON6__BTN))
- {
- PWM_1_WriteCompare(80);
- LCD_Char_1_PrintString("Button_7");
- UART_UartPutString("Przycisk_7\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON7__BTN))
- {
- PWM_1_WriteCompare(80);
- LCD_Char_1_PrintString("Button_8");
- UART_UartPutString("Przycisk_8\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else if(CapSense_1_CheckIsWidgetActive(CapSense_1_PROXIMITYSENSOR0__PROX))
- {
- PWM_1_WriteCompare(80);
- LCD_Char_1_PrintString("Proximity");
- UART_UartPutString("Proximity\n\r");
- PWM_2_WriteCompare(1700);
- CyDelay(100);
- PWM_2_WriteCompare(0);
- }
- else
- {
- PWM_1_WriteCompare(0);
- PWM_2_WriteCompare(0);
- LCD_Char_1_ClearDisplay();
- }
- }
Program składa się z dwóch elementów na początku inicjalizowane są wszystkie bloki włącznie z wykrywaniem dotyku oraz włączeniem przerwań. W pętli głównej sprawdzany jest czy wykryto dotyk, jeśli tak to następuje wejście do funkcji CapsenseDisplayState, która w zależności od klawisza sygnalizuje dotyk poprzez zapalenie diody, wypisanie tekstu na ekranie HD44780, wypisanie danych poprzez usart oraz sygnałem dźwiękowym buzzera.
W kolejnych postach postaram się przedstawić w jaki sposób przygotować wykrywanie dotyku, bez konieczności korzystania z biblioteki, tylko samemu zaimplementować odpowiednie algorytmy.
Pliki z projektem można znaleźć na dysku Google pod tym linkiem.