طی سالهای اخیر، حسگر لمسی در بسیاری از برنامه ها مانند تلفن های همراه، اجاق های القایی، قهوه ساز، و غیره رواج یافته است که در مقایسه با دکمه های فشار استاندارد انعطاف پذیرتر و قابل اعتماد تر است. زیرا قطعات مکانیکی در دراز مدت دیگر مورد استفاده نیست.
فناوری TSC در میکروکنترلرهای STM32 به همراه کتابخانه TSL طراح را قادر می سازد به سادگی قابلیت حسگر لمسی را به هر برنامه اضافه کند.
touch sensing در STM32 مبتنی بر انتقال شارژ است. اصل charge transfer شامل شارژ خازن سنسور Cx و انتقال بار جمع شده به خازن نمونه برداری Cs است. این سیکل تا زمانی که ولتاژ در Cs به VIH برسد تکرار می شود.
تعداد انتقال بار مورد نیاز برای رسیدن به ولتاژ آستانه، همان اندازه ظرفیت الکترود است. هنگامی که سنسور لمس می شود، ظرفیت خازن سنسور افزایش می یابد. این بدان معنی است که ولتاژ C با شمارش کمتر به VIH می رسد و مقدار اندازه گیری کاهش می یابد. هنگامی که این اندازه گیری کمتر از آستانه باشد، کتابخانه TSL (کتابخانه touch sensing ) یک لمس را گزارش می کند.
کنترلر حسگر لمسی در میکروکنترلر STM32
- در سری STM32F0، STM32F3 ،STM32L0 و STM32L4 میکروکنترلرهای STM32 موجود است.
- برای عملکرد بهینه، حداکثر 8 کانال حسگر خازنی به صورت موازی قابل دستیابی هستند که زمان پاسخ بسیار خوبی را ارائه می دهد.
- برای مدیریت حداکثر 3 کانال حسگر خازنی فقط به یک خازن نمونه برداری نیاز است. این امر باعث کاهش BOM می شود.
- برای کاهش سربار CPU کاملاً توسط سخت افزار مدیریت می شود. این ویژگی در محیط های پر نویز برای بهبود عملکرد سیستم مورد استفاده قرار گرفته است.
- به گونه ای طراحی شده است که با کتابخانه حسگر لمسی STM32Cube موجود در بسته STM32Cube مربوطه کار کند.
- این کتابخانه کلیه پردازش های مورد نیاز برای راه حل حسگر خازنی مطلوب را ارائه میدهد و از حسگرهای proximity، touchkey ، linear و rotary پشتیبانی می کند.
یک گروه I/O آنالوگ را که از چهار پین I/O تشکیل شده است، در نظر بگیریم. یکی از این I/O ها برای خازن نمونه برداری خواهد بود (حداکثر هر 3 حسگر یک خازن نمونه برداری) که معمولاً به خازن خارجی (CS) وصل می شود که خازن نمونه برداری نامیده می شود.
بنابراین در هر گروه آنالوگ I/O یک خازن نمونه برداری واحد وجود دارد. مقدار آن به حساسیت کانال بستگی دارد. هرچه مقدار آن بالاتر باشد، حساسیت بیشتر و زمان دستیابی بیشتر است و سه I/O دیگر به کانال ها اختصاص داده می شوند.
هر یک از آنها از طریق یک مقاومت سری (RS) به یک الکترود حسگر متصل می شوند. RS برای بهبود ESD استفاده می شود. در یک گروه I/O آنالوگ، فقط یک کانال به طور همزمان قابل دستیابی است. این بدان معناست که اگر سه کانال اجرا شوند، برای سه حسگر به صورت متوالی خواهد بود.
برای عملکرد بهینه، ظرفیت خازن حسگر باید تا حد ممکن پایین باشد. اغلب این مقدار خازن را در حدود ده پیکوفاراد انتخاب میکنند. لمس آن منجر به افزایش ظرفیت خازن حسگر می شود در حد چند پیکوفراد، به عنوان مثال 5 پیکوفاراد.
کتابخانه TSL
همانطور که قبلاً گفته شد، پریفرال TSC برای کار با کتابخانه touch sensing طراحی شده است. این کتابخانه C از حسگرهای proximity، touchkey، linear و rotary پشتیبانی می کند.
برخی از این ویژگی ها شامل کالیبراسیون power-on، محیط کنترل سیستم (ECS)، فیلتر debounce و سیستم تشخیص استسثناء (DxS) است.
این کتابخانه یک API ساده برای پیکربندی کانالها، سنسورها و دریافت وضعیت سنسورها ارائه می دهد. که سازگار با MISRA است و از کلیه کامپایلرهایSTM32 پشتیبانی می کند.
پیکره بندی پین ها به منظور کنترل توسط کتابخانه TSC
در این پروژه از میکروکنترلر STM32F051C8 استفاده کرده ایم که دارای شش گروه TSC می باشد. چون ما می خواهیم یک صفحه کلید ماتریسی 3x4 با آنها بسازیم بنابراین به 7 پین I/O از گروه ها نیاز داریم. از آنجا که حداکثر سه کانال برای هر خازن نمونه برداری استفاده می شود بنابراین ما سه گروه TSC را برای ساخت صفحه کلید ماتریسی نیاز داریم و برای هر گروه یک پین برای خازن نمونه برداری استفاده می شود که در نهایت می شود 10 پین (7 کانال برای حسگر لمسی و 3 پین برای خازن نمونه برداری).
نرم افزار STM32CubeIDE را باز کرده و یک پروژه جدید با میکروکنترلر STM32F051C8 بسازید. در قسمت Pinout پین ها را به شکل زیر وارد کنید. دقت کنید که ما واحد USART1 را فعال کردیم از آن برای ارسال و نمایش شماره تاچ شده در سریال مانیتور کامپیوتر استفاده خواهیم کرد.
سپس از قسمت System core وارد TSC شوید و در تنظیمات پارامترهای TSC را به شکل زیر وارد کنید.
در قسمت تنظیمات GPIO پین مربوط به خازن نمونه برداری CS باید در حالت alternate output open-drain تنظیم شود که در شکل زیر نشان داده شده است. ما در این پروژه پین های PB0, PB7, PB14 را برای خازن نمونه برداری CS انتخاب کرده ایم پس آنها در حالت alternate output open-drain تنظیم می شوند. علاوه براین، برای جلوگیری از مصنوعات، باید Schmitt trigger hysteresis غیرفعال شود.
کانال I/O باید در مد alternate output push-pull تنظیم شود. بنابراین 7 کانال دیگر که برای کلید ماتریسی استفاده می شوند در مد alternate output push-pull تنظیم می شوند که در شکل زیر مشخص است.
حالا برای استفاده از کتابخانه TSL در برنامه به قسمت Middleware رفته تیک Enable را بزنید تا فعال شود و در تب Sensor Selection نوع سنسور (proximity، touchkey ، linear و rotary) که در این پروژه ما touchkey استفاده می کنیم و پین های مربوط به آن را مانند شکل زیر وارد می کنیم.
در تب Config parameter کانفیک پارامترهای مهم برای Touchkey را دقیقا مانند شکل زیر وارد کنید. تنظیمات حسگر لمسی به پایان رسید.
در قسمت تنظیمات connectivity وارد بخش USART1 شوید و Baud Rate ارتباط سریال را 9600 وارد کنید.
در قسمت کانفیگ کلاک Clock Configuration فرکانس کلاک و قسمت های دیگر مانند شکل زیر تنظیم کنید.
در انتها تایمر 15 را به همراه وقفه فعال کرده که در ادامه خواهیم دید که کجا از آن استفاده می کنیم. تیک Internal Clock را بزنید و تقسیم کننده و مد شمارنده و دوره شمارنده را مانند شکل زیر تنظیم کنید.
و در تب NVIC Setting تیک وقفه را بزنید تا فعال شود.
حالا پروژه را ذخیره کنید و در نهایت Code Generation را کلیک کنید تا کد کانفیگ ها تولید شود.
آشنایی با کتابخانه TSL
در ادامه، درباره کد پروژه و کتابخانه TSL توضیح خواهم داد. همانطور که در ابتدا گفته شد کتابخانه TSL تاچ را گزارش می کند و ما در برنامه خود می توانیم از آن استفاده کنیم.
چطور از توابع کتابخانه TSL در برنامه خود استفاده کنیم.
یکی از کتابخانه های مهم tsl_user می باشد که شامل فایل پیکربندی کاربر برای TOUCHSENSING MiddleWare است این کتابخانه در فولدر src موجود است. تابع مهم این کتابخانه tsl_user_Exec(void) است که برای اجرای درایور STMTouch می باشد و اگر لمس را گزارش کند مقدار بازگشتی TSL_STATUS_OK را بر می گرداند بنابراین کافی است که در برنامه خود از این تابع استفاده کنیم و شرط بگذاریم که مقدار بازگشتی این تابع برابر با TSL_STATUS_OK باشد یا خلاف TSL_USER_STATUS_BUSY بود.
if(tsl_user_Exec() == TSL_STATUS_OK){
}
بعد از آن ما باید بفهمیم که کدام کانال یا پین لمس شده است. کتابخانه tsl_user یک متغیر مهم دیگر به نام []MyTKeys از نوع TSL_TouchKey_T دارد که آرایه ای از لیست پین های لمسی است (در این پروژه ما هفت پین را استفاده کرده ایم) که اطلاعات مربوط به تشخیص لمس را می توان از آن استخراج کرد.
TSL_TouchKey_T یک ساختار یا استراکچر از متعیرهای حسگر کلید لمسی است.
/** Contains definition of a TouchKey sensor.
* Variables of this structure type can be placed in RAM or ROM.
*/
typedef struct
{
TSL_TouchKeyData_T *p_Data; /**< Data (state id, counter, flags, ...) */
TSL_TouchKeyParam_T *p_Param; /**< Parameters (thresholds, debounce, ...) */
TSL_ChannelData_T *p_ChD; /**< Channel Data (Meas, Ref, Delta, ...) */
CONST TSL_State_T *p_SM; /**< State Machine */
CONST TSL_TouchKeyMethods_T *p_Methods; /**< Methods */
}
TSL_TouchKey_T;
ما مقدار *p_Data را نیاز داریم که خود از نوع TSL_TouchKeyData_T می باشد. که شامل تمام داده های مربوط به سنسور کلید لمسی است.
متغیرهای این نوع ساختار باید فقط در RAM قرار گیرند.
/** Contains all data related to TouchKey sensor.
* Variables of this structure type must be placed in RAM only.
*/
typedef struct
{
TSL_StateId_enum_T StateId; /**< Current state identifier */
TSL_tCounter_T CounterDebounce; /**< Counter for debounce and calibration management */
unsigned int CounterDTO : 6; /**< Counter for DTO management (TSL_tCounter_T) */
unsigned int Change : 1; /**< The State is different from the previous one (TSL_StateChange_enum_T) */
unsigned int DxSLock : 1; /**< The State is locked by the DxS (TSL_Bool_enum_T) */
}
TSL_TouchKeyData_T;
مقدار StateId نشان دهنده وضعیت فعلی آن پین لمسی می باشد و اگر برابر با detect_type باشد یعنی این پین لمس را تشخیص داده است بنابراین فقط کافی است که مقدار StateId هفت پین را با detect_type مقایسه کنیم اگر برابر بود یعنی همان پین لمس شده است.
if(tsl_user_Exec() == TSL_STATUS_OK){
if(MyTKeys[1].p_Data->StateId == detect_type)
//...
else if(MyTKeys[2].p_Data->StateId == detect_type)
//...
else if(MyTKeys[3].p_Data->StateId == detect_type)
//...
}
اگر قرار بود کلید لمسی معمولی بسازیم همینجا پروژه ما تمام شده بود و بعد از شروط بالا عملکرد مربوط به هر پین را می نوشتیم مثلا یک عدد روی سریال ارسال شود و یا یک LED روشن شود.
اما چون در این پروژه قرار است کلید ماتریسی لمسی 3x4 بسازیم آن را طوری طراحی کرده ایم که حداکثر هفت پین ( و نه 12 پین) میکرو را اشغال کند و این به این معنی است که هر تاچ توسط کاربر باعث لمس دو پین کنار هم خواهد شد.
بنابراین باید دو پین کنار هم، که نماینده یک شماره از کلید ماتریسی هستند را بررسی کنیم مانند نمونه کد زیر:
if(tsl_user_Exec() == TSL_STATUS_OK){
if(MyTKeys[1].p_Data->StateId == detect_type && MyTKeys[4].p_Data->StateId == detect_type)
//...
}
تا به اینجا فک کنم با نحوه کار با کتابخانه TSL آشنا شده باشید.
حالا من برای این پروژه یک کتابخانه ایجاد کردم به نام touchkey که برای مدیریت صفحه کلید ماتریسی لمسی هست. این کتابخانه یک تابع به نام touchkey_scan(void) دارد که فقط کافی است آن را در برنامه خود استفاده کنید هر زمان که کلیدی تاچ شد شماره آن کلید را در متغیر GET_KEY قرار می دهد.
توجه داشته باشید: که ابتدا باید کتابخانه touchkey.h را در برنامه خود include کنید و متغیر GET_KEY که از نوع char است را extern کنید.
/* USER CODE BEGIN Includes */
#include "touchkey.h"
.
.
/* USER CODE BEGIN PV */
extern char GET_KEY ;
در نهایت کد برنامه تست شده مانند زیر خواهد بود:
/* USER CODE BEGIN WHILE */
HAL_Delay(500);
uint8_t key;
while (1)
{
touchkey_scan();
key = GET_KEY;
if(key != ' '){
HAL_UART_Transmit(&huart1, &key, 1, 100);
key = '\n';
HAL_UART_Transmit(&huart1, &key, 1, 100);
GET_KEY = ' ';
}
// HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
نکته مهم: تابع tsl_user_Exec(void) در وقفه تایمر قرار دارد و در دوره زمانی تایمر اجرا می شود. بنابراین این تابع را در برنامه نیاز نیست استفاده کنیم و اگر لمسی را تشخیص دهد متغیر touch_status تغییر می کند.
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
touch_status = tsl_user_Exec();
UNUSED(htim);
}
آدرس کد کامل پروژه در گیت هاب:
https://github.com/mehdi-adham/STM32-touch-matrix-keypad-with-TSC-Peripheral