# Psoc6Project **Repository Path**: dgjames/psoc6project ## Basic Information - **Project Name**: Psoc6Project - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-15 - **Last Updated**: 2025-08-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 智能触摸与手势系统 Infineon Psoc6-evaluationkit-062S2 ![alt text](doc/photo/image-10.png) ## 1. 电容触摸界面 利用 Psoc6-evaluationkit-062S2 的 CapSense 模块设计一个交互式触摸面板。 * 可以通过触摸面板调 整PWM的频率使蜂鸣器播放不同的音调(需要映射do (1), re (2), mi (3), fa (4) 音符)+ 调整 PWM 信号的占空比控制 LED 指示灯。 ### 1.1 Capsense触控 在Slider例程上修改,根据触摸位置(x)判断音符、手势 ``` c slider_touch_info = Cy_CapSense_GetTouchInfo(CY_CAPSENSE_LINEARSLIDER0_WDGT_ID, &cy_capsense_context); slider_touch_status = slider_touch_info->numPosition; slider_pos = slider_touch_info->ptrPosition->x; int x=slider_pos; if (RT_NULL != slider_touch_status) { int senor_id=detect_sensor_id(); char *gesture=detect_gesture(x); int now_note_id=detect_note(x); screen_show_info(now_note_id,senor_id,gesture); rt_event_send(&buzzer_event, EVENT_TOUCH); message_json(senor_id, gesture); } ``` 获取sensor id,逐个判断是否激活,返回id `Cy_CapSense_IsSensorActive(CY_CAPSENSE_LINEARSLIDER0_WDGT_ID,i,&cy_capsense_context)` ``` c int detect_sensor_id() { for(int i=0;i<4;i++) { if(Cy_CapSense_IsSensorActive\(CY_CAPSENSE_LINEARSLIDER0_WDGT_ID,i,&cy_capsense_context)) { return i; } } } ``` 10ms扫描一次 ``` c void loop(void) { /* put your main code here, to run repeatedly: */ rt_sem_take(trans_done_semphr, RT_WAITING_FOREVER); /* Process all widgets */ Cy_CapSense_ProcessAllWidgets(&cy_capsense_context); /* Process touch input */ process_touch(); /* Establishes synchronized operation between the CapSense * middleware and the CapSense Tuner tool. */ Cy_CapSense_RunTuner(&cy_capsense_context); /* Initiate next scan */ Cy_CapSense_ScanAllWidgets(&cy_capsense_context); rt_thread_mdelay(10); } ``` ### 1.2 音调播放 ![alt text](doc/photo/image-6.jpg) 改变pwm设置播放音调,求出周期,设置20%的占空比 ``` c int notes[] = {1, 262, 294, 330, 349, 392, 440, 494}; struct rt_event buzzer_event; //int pre_note=0; void set_notes(int i) { uint32_t period_ns = 1000000000 / notes[i]; // ns uint32_t pulse_ns = period_ns * 0.2; // 20% rt_pwm_set(buzzer_pwm, PWM_DEV_CHANNEL, period_ns, pulse_ns); rt_pwm_enable(buzzer_pwm, PWM_DEV_CHANNEL); } ``` 没触摸0.2s后停止播放 ```c void buzzer_entry(void *parament) { rt_uint32_t e; while (1) { if(rt_event_recv(&buzzer_event, EVENT_TOUCH,RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, 0,&e)!=RT_EOK) { rt_pwm_disable(buzzer_pwm, PWM_DEV_CHANNEL); } rt_thread_mdelay(200); } } ``` ### 1.3 屏幕显示 ![alt text](doc/photo/image-5.jpg) * 触摸响应时间必须≤100ms,并且触发的命令须显示在 OLED 屏幕上(分辨率≥128x64 像素),并清晰标识触摸区域和操作。 使用ssd1306软件包,分别显示了音符,触摸区域id,手势 ``` c void screen_show_info(int note,int id,char *gesture) { rt_mutex_take(screen_mutex, RT_WAITING_FOREVER); ssd1306_SetCursor(2, 15); ssd1306_WriteString(note_str[note], Font_7x10, White); ssd1306_SetCursor(20, 15); ssd1306_WriteChar(id+'0', Font_7x10, White); ssd1306_SetCursor(2, 30); ssd1306_WriteString(gesture, Font_7x10, White); ssd1306_UpdateScreen(); rt_mutex_release(screen_mutex); } ``` 显示时间 ``` c void screen_show_time(char *time) { rt_mutex_take(screen_mutex, RT_WAITING_FOREVER); ssd1306_SetCursor(2, 0); ssd1306_WriteString(time, Font_6x8, White); ssd1306_UpdateScreen(); rt_mutex_release(screen_mutex); } ``` ### 1.4 LED随滑动控制 * 可以通过触摸面板调整PWM的占空比控制 LED 指示灯的亮度。 使用pwm ``` c rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, 1 * 1000 * 1000, GET_DUTY_CYCLE(brightness)); } ``` * 可以更改其它引脚 ![alt text](doc/photo/image.png) ![alt text](doc/photo/image-1.png) ![alt text](doc/photo/6df74bfba8e75806712d0efea5f2d5bc.png) ## 2. 手势识别 * 使用 CapSense 模块实现 2 种不同手势的识别(向左滑动、向右滑动)。 由于本开发板上的是slider线性滑条,在CapSense组件中,只有触摸板widget支持手势功能。所以通过记录最近3次触摸位置(x),简单判断是否为手势 ``` c char *detect_gesture(int num) { static int val[3] = {0}; val[0] = val[1]; val[1] = val[2]; val[2] = num; rt_kprintf("val: %d %d %d\n", val[0], val[1], val[2]); char *gesture = ""; if (ORDER(val[0], val[1], val[2])) { rt_kprintf("left\n"); gesture = "left "; } else if (ORDER(val[2], val[1], val[0])) { rt_kprintf("right\n"); gesture = "right"; } else { gesture = " "; } return gesture; } ``` ## 3. 网络同步 * 通过网络模块使用MQTT协议同步NTP时间并显示到OLED上(格式:YYYY-MM-DD HH:MM:SS)。并将触摸和手势数据(包括:触摸区域 ID、手势类型)传输到服务器端显示。 ### 3.1 rw007 ![alt text](doc/photo/image-2.png) ![alt text](doc/photo/image-3.png) ### 3.2 mqtt ![alt text](doc/photo/image-4.png) * 使用pahomqtt软件包, 使用参考样例的mqtt_start函数 设置好topic等宏 ``` c #define MQTT_URI "tcp://broker.emqx.io:1883" #define MQTT_SUBTOPIC "abc/sub" #define MQTT_PUBTOPIC "abc/pub" #define MQTT_WILLMSG "Goodbye!" #define MQTT_USERNAME "name" #define MQTT_PASSWORD "password" ``` * 可以等待网络连接后再连接mqtt ``` c int check_network(void) { struct netdev *netdev = netdev_get_by_family(AF_INET); return (netdev && netdev_is_link_up(netdev) /* && netdev_is_internet_up(netdev) */); } ``` * 用RyanJson软件包生成json数据,mqtt发送到相应的topic ``` cpp char *message_json(int touch_area_id, char *gesture_type) { RyanJson_t root; root = RyanJsonCreateObject(); RyanJsonAddIntToObject(root, "Touch area ID", touch_area_id); RyanJsonAddStringToObject(root, "Gesture type",gesture_type ); rt_uint32_t len; tmp_json = RyanJsonPrint(root, 650, RyanJsonTrue, &len); int ret = paho_mqtt_publish(&client, QOS1, MQTT_PUBTOPIC, tmp_json); rt_kprintf("json:%s\n",tmp_json); RyanJsonDelete(root); return tmp_json; } ``` ### 3.3 ntp 在netutils软件包中使能ntp 每秒更新时间 ``` c static void time_thread_entry(void *parameter) { struct tm *tm; while (1) { // 获取当前时间 time_t now =time(NULL); tm = localtime(&now); // 使用UTC时间 strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", tm); screen_show_time(time_buf); // 线程睡眠1秒钟 rt_thread_mdelay(1000); } } ``` ## 4. RTduino使用 ### 4.1. RT-Thread多任务集成 ●利用 Psoc6 的 RTduino 支持(RT-Thread 的 Arduino 兼容生态系统)来实现实时触摸和手势处理 ![alt text](doc/photo/image-8.png) ### 4.2 使用.c文件中的函数 ``` c applications/arduino_main.cpp: : undefined reference to `' ``` 在`arduino_main.cpp`中调用其它文件的函数时,提示说未定义,要 在对应头文件中添加`extern "C"` ``` c #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif ``` ## 另 ### 5.1 线程使用 1. buzzer线程,用于停止播放音调 2. time线程,用于更新屏幕显示时间 3. rtduino loop,用于触摸识别,与数据处理显示 4. mqtt线程,用于等待网络连接和启动mqtt客户端 ### 5.2 软件包使用 ![alt text](doc/photo/image-7.png)