poniedziałek, 13 marca 2017

[1] PSOC4 - CY8CKIT-049-42xx - Uart, Capsense, LCD2x16

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:

[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.

  1. /* ========================================
  2.  *
  3.  * Copyright YOUR COMPANY, THE YEAR
  4.  * All Rights Reserved
  5.  * UNPUBLISHED, LICENSED SOFTWARE.
  6.  *
  7.  * CONFIDENTIAL AND PROPRIETARY INFORMATION
  8.  * WHICH IS THE PROPERTY OF your company.
  9.  *
  10.  * ========================================
  11. */
  12. #include "project.h"
  13. #include "stdio.h"
  14. void CapSense_DisplayState(void);
  15. int main(void)
  16. {
  17.     char buffer[10];
  18.     uint16_t value = 0;
  19.     CyGlobalIntEnable; /* Enable global interrupts. */
  20.    
  21.     LCD_Char_1_Start();
  22.     LCD_Char_1_Position(0u, 0u);
  23.    
  24.     LCD_Char_1_ClearDisplay();
  25.    
  26.     UART_Start();
  27.     UART_UartPutString("Hello World\n\r");
  28.     UART_UartPutString("dziala dziala\n\r");
  29.    
  30.     CapSense_1_Start();
  31.     CapSense_1_EnableWidget(CapSense_1_PROXIMITYSENSOR0__PROX);
  32.     UART_UartPutString("CapSense start\n\r");
  33.    
  34.     CapSense_1_InitializeAllBaselines();
  35.     UART_UartPutString("InitializeAllBaselines\n\r");
  36.     CapSense_1_ScanEnabledWidgets();
  37.    
  38.     PWM_1_Start();
  39.     PWM_2_Start();
  40.    
  41.     UART_UartPutString("PWM_1_Start\n\r");
  42.    
  43.     /* Place your initialization/startup code here (e.g. MyInst_Start()) */
  44.     for(;;)
  45.     {
  46.         CapSense_1_ScanEnabledWidgets();
  47.        
  48.         while(CapSense_1_IsBusy() != 0) { }
  49.        
  50.         CapSense_DisplayState();
  51.         CapSense_1_UpdateEnabledBaselines();
  52.         /* Place your application code here. */
  53.     }
  54. }
  55. void CapSense_DisplayState(void)
  56. {
  57.     static uint8_t previous_state;
  58.    
  59.     LCD_Char_1_Position(0u, 0u);
  60.    
  61.     if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON0__BTN))
  62.     {
  63.        PWM_1_WriteCompare(20);
  64.        LCD_Char_1_PrintString("Button_1");
  65.        UART_UartPutString("Przycisk_1\n\r");
  66.    
  67.        PWM_2_WriteCompare(1700);
  68.        CyDelay(100);
  69.        PWM_2_WriteCompare(0);
  70.     }
  71.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON1__BTN))
  72.     {
  73.        PWM_1_WriteCompare(40);
  74.        LCD_Char_1_PrintString("Button_2");
  75.        UART_UartPutString("Przycisk_2\n\r");
  76.    
  77.        PWM_2_WriteCompare(1700);
  78.        CyDelay(100);
  79.        PWM_2_WriteCompare(0);
  80.     }
  81.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON2__BTN))
  82.     {
  83.        PWM_1_WriteCompare(60);
  84.        LCD_Char_1_PrintString("Button_3");
  85.        UART_UartPutString("Przycisk_3\n\r");
  86.        
  87.        PWM_2_WriteCompare(1700);
  88.        CyDelay(100);
  89.        PWM_2_WriteCompare(0);
  90.    
  91.     }
  92.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON3__BTN))
  93.     {
  94.        PWM_1_WriteCompare(80);
  95.        LCD_Char_1_PrintString("Button_4");
  96.        UART_UartPutString("Przycisk_4\n\r");
  97.        
  98.        PWM_2_WriteCompare(1700);
  99.        CyDelay(100);
  100.        PWM_2_WriteCompare(0);
  101.     }
  102.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON4__BTN))
  103.     {
  104.        PWM_1_WriteCompare(80);
  105.        LCD_Char_1_PrintString("Button_5");
  106.        UART_UartPutString("Przycisk_5\n\r");
  107.        
  108.        PWM_2_WriteCompare(1700);
  109.        CyDelay(100);
  110.        PWM_2_WriteCompare(0);
  111.     }
  112.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON5__BTN))
  113.     {
  114.        PWM_1_WriteCompare(80);
  115.        LCD_Char_1_PrintString("Button_6");
  116.        UART_UartPutString("Przycisk_6\n\r");
  117.        
  118.        PWM_2_WriteCompare(1700);
  119.        CyDelay(100);
  120.        PWM_2_WriteCompare(0);
  121.     }
  122.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON6__BTN))
  123.     {
  124.        PWM_1_WriteCompare(80);
  125.        LCD_Char_1_PrintString("Button_7");
  126.        UART_UartPutString("Przycisk_7\n\r");
  127.        
  128.        PWM_2_WriteCompare(1700);
  129.        CyDelay(100);
  130.        PWM_2_WriteCompare(0);
  131.     }
  132.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_BUTTON7__BTN))
  133.     {
  134.        PWM_1_WriteCompare(80);
  135.        LCD_Char_1_PrintString("Button_8");
  136.        UART_UartPutString("Przycisk_8\n\r");
  137.        
  138.        PWM_2_WriteCompare(1700);
  139.        CyDelay(100);
  140.        PWM_2_WriteCompare(0);
  141.     }
  142.     else if(CapSense_1_CheckIsWidgetActive(CapSense_1_PROXIMITYSENSOR0__PROX))
  143.     {
  144.        PWM_1_WriteCompare(80);
  145.        LCD_Char_1_PrintString("Proximity");
  146.        UART_UartPutString("Proximity\n\r");
  147.        
  148.        PWM_2_WriteCompare(1700);
  149.        CyDelay(100);
  150.        PWM_2_WriteCompare(0);  
  151.     }
  152.     else
  153.     {
  154.        PWM_1_WriteCompare(0);
  155.        PWM_2_WriteCompare(0);
  156.        LCD_Char_1_ClearDisplay();
  157.     }
  158. }

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.