preface
The main content of this paper is to realize the touch key drive of the kettle, and the touch key chip adopts TS02N.
1, Key function setting of intelligent kettle
- The key functions of the intelligent kettle are set as follows. Before realizing the functions, we must first realize the drive of the key acquisition chip.
function | explain |
---|---|
boiling | Touch key 1. Trigger mode: touch gently. Default boiling. Touch the key to control the boiling key, press the start button, and then press the close button app control: boiling |
Insulation key | Touch key 1. Trigger mode: touch gently Tap to enter the 55 degree insulation mode under the default tap water mode, press on, and then press off Long press 5s to enter the distribution network mode No operation, no operation for app, and the default mode is cool and white |
2, Scheme formulation of key acquisition
1. Hardware circuit diagram
- The key acquisition circuit is as follows:
-
Instructions for use TS02N
input P1\P2: low level trigger
OUT1 outputs low level after P1 is triggered
After P2 is triggered, OUT2 outputs low level
Communication pin setting:
OUT1 | P7 Boiling key OUT2 | P8 Insulation key
2. Embedded scheme setting
In order to expand the program in the later stage, the key control is realized by means of callback function registration.
1.When the key is pressed, the key indicator light is on, when the key is released, the key indicator light is off; Press the key once and the buzzer will ring once 2.You can use the registration function to register the used directly IO Port, and the callback function triggered by pressing the registration key 3.You can set the long press time and configure the callback function triggered by long press
3, Function realization
1. Code implementation
- Add programs and ts02n on the basis of previous development_ key. C file and its header file. At present, the file structure of the whole project is as follows:
├── src | ├── tuya_drive | | └── b3950 | | └── b3950.c //Temperature sensor drive correlation | | └── gpio_control | | └── gpio_control.c //gpio control related | | └── ts02n_key | | └── ts02n_key.c //Key drive | | └── timer | | └── timer.c //Timer correlation | ├── tuya_device.c //Application layer entry file | └── kettle_app.c //Main application documents of intelligent kettle | ├── include //Header file directory | ├── tuya_drive_h | | └── b3950_h | | └── b3950.h | | └── gpio_control_h | | └── gpio_control.h | | └── ts02n_key_h | | └── ts02n_key.h //Key drive | | └── timer_h | | └── timer.h //Timer correlation | ├── tuya_device.h | └── kettle_app.h | └── output //Compiled products
ts02n_ key. The functions in C are implemented as follows: the main content is to realize the scanning function and initialize according to the incoming configuration parameters
/*When using, you only need to pass ts02n_ key_ Init (ts02n_key_def s * user_key_def) function is registered. After registration, a timed scanning task will be automatically started to collect key information. After the key is triggered, the registered callback function will also be called automatically*/ typedef VOID(* KEY_CALLBACK)(); typedef struct { // user define unsigned int key_pin1; //ts02n CH1 PIN unsigned int key_pin2; //ts02n CH2 PIN KEY_CALLBACK key1_cb; //normal press key1 callback function KEY_CALLBACK key2_cb; //normal press key2 callback function KEY_CALLBACK key1_long_press_cb; //normal press key1 callback function KEY_CALLBACK key2_long_press_cb; //normal press key2 callback function KEY_CALLBACK key1_Low_level_cb; //Key1 low level process callback function KEY_CALLBACK key2_Low_level_cb; //Key2 low level process callback function unsigned int long_time_set; //long press key time set unsigned int scan_time; //Scan cycle set unit: ms }TS02N_KEY_DEF_S; typedef struct { unsigned int down_time; //Record the time when the key is pressed unsigned char status; }KEY_PRESS_STATUS_S; typedef struct { TS02N_KEY_DEF_S* ts02n_def_s;//User registration related information, callback function, pin port, etc KEY_PRESS_STATUS_S key_status; }TS02N_KEY_MANAGE_S; /* Private function prototypes -----------------------------------------------*/ static int key_scan(); static void key_timer_cb(); /* Private variables ---------------------------------------------------------*/ static TIMER_ID key_timer; static TS02N_KEY_MANAGE_S *key_mag = NULL; enum KEY_STAT_E{ KEY1_UP = 0, KEY1_DOWN, KEY1_FINISH, KEY2_UP, KEY2_DOWN, KEY2_FINISH, }; enum KEY_PRESS_STAT{ KEY1_NORMAL_PRESS = 0, KEY2_NORMAL_PRESS, KEY1_LONG_PRESS, KEY2_LONG_PRESS, NO_KEY_PRESS, }; /* Private functions ---------------------------------------------------------*/ /** * @Function: ts02n_key_init * @Description: key init * @Input: none * @Output: none * @Return: none * @Others: */ int ts02n_key_init(TS02N_KEY_DEF_S* user_key_def) { int op_ret = 0; key_mag = (TS02N_KEY_MANAGE_S *)Malloc(SIZEOF(TS02N_KEY_MANAGE_S)); memset(key_mag, 0, SIZEOF(TS02N_KEY_MANAGE_S)); //No callback function is registered key init err if((user_key_def->key1_cb == NULL) && (user_key_def->key2_cb == NULL) && \ (user_key_def->key1_long_press_cb == NULL) && (user_key_def->key2_long_press_cb == NULL)){ return KEY_INIT_ERR; } //key pin init tuya_pin_init(user_key_def->key_pin1, TUYA_PIN_MODE_IN_PU); tuya_pin_init(user_key_def->key_pin2, TUYA_PIN_MODE_IN_PU); //get user define key_mag->ts02n_def_s = user_key_def; //creat key scan handle timer op_ret = sys_add_timer(key_timer_cb,NULL,&key_timer); if(op_ret != KEY_INIT_OK) { return KEY_INIT_ERR; PR_ERR("add timer err"); } op_ret = sys_start_timer(key_timer,key_mag->ts02n_def_s->scan_time,TIMER_CYCLE); if(op_ret != KEY_INIT_OK) { return KEY_INIT_ERR; PR_ERR("start timer err"); } } /** * @Function: key_timer_cb * @Description: Timing key scan processing function * @Input: none * @Output: none * @Return: none * @Others: */ static void key_timer_cb() { int ret = -1; //get key press status ret = key_scan(); switch (ret) { case KEY1_NORMAL_PRESS: { key_mag->ts02n_def_s->key1_cb(); } break; case KEY1_LONG_PRESS: { key_mag->ts02n_def_s->key1_long_press_cb(); } break; case KEY2_NORMAL_PRESS: { key_mag->ts02n_def_s->key2_cb(); } break; case KEY2_LONG_PRESS: { key_mag->ts02n_def_s->key2_long_press_cb(); } break; default: break; } } /** * @Function: key_scan * @Description: key scan handle function * @Input: none * @Output: none * @Return: none * @Others: */ static int key_scan() { if((tuya_pin_read(key_mag->ts02n_def_s->key_pin1) == 0) && (tuya_pin_read(key_mag->ts02n_def_s->key_pin2) == 0 )) { return NO_KEY_PRESS; } if(tuya_pin_read(key_mag->ts02n_def_s->key_pin1) == 0 ) { key_mag->ts02n_def_s->key1_Low_level_cb(); key_mag->key_status.status = KEY1_DOWN; key_mag->key_status.down_time += key_mag->ts02n_def_s->scan_time; if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) { key_mag->key_status.status = KEY1_FINISH; } }else { if(key_mag->key_status.status == KEY1_DOWN) { key_mag->key_status.status = KEY1_FINISH; } } if(tuya_pin_read(key_mag->ts02n_def_s->key_pin2) == 0 ) { key_mag->ts02n_def_s->key2_Low_level_cb(); key_mag->key_status.status = KEY2_DOWN; key_mag->key_status.down_time += key_mag->ts02n_def_s->scan_time; if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) { key_mag->key_status.status = KEY2_FINISH; } }else { if(key_mag->key_status.status == KEY2_DOWN) { key_mag->key_status.status = KEY2_FINISH; } } switch (key_mag->key_status.status) { case (KEY1_FINISH): { if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) { PR_DEBUG("key_pin1 long press"); key_mag->key_status.down_time = 0; key_mag->key_status.status = KEY1_UP; return KEY1_LONG_PRESS; }else { key_mag->key_status.status = KEY1_UP; key_mag->key_status.down_time = 0; PR_DEBUG("key_pin1 press"); return KEY1_NORMAL_PRESS; } } break; case (KEY2_FINISH): { if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) { PR_DEBUG("key_pin2 long press"); key_mag->key_status.down_time = 0; key_mag->key_status.status = KEY2_UP; return KEY2_LONG_PRESS; }else { key_mag->key_status.status = KEY2_UP; key_mag->key_status.down_time = 0; PR_DEBUG("key_pin2 press"); return KEY2_NORMAL_PRESS; } } break; default: return NO_KEY_PRESS; break; } }
- kettle_app.c file, and register callback functions. Some of the functions that set the state of the kettle can be ignored first, which will be described later
TS02N_KEY_DEF_S kettle_key_def_s = { .key_pin1 = TY_GPIOA_8, .key_pin2 = TY_GPIOA_7, .key1_cb = key1_cb_fun, .key2_cb = key2_cb_fun, .key1_long_press_cb = NULL, .key2_long_press_cb = key2_long_press_cb_fun, .key1_Low_level_cb = key1_Low_level_cb_fun, .key2_Low_level_cb = key2_Low_level_cb_fun, .long_time_set = 5000, .scan_time = 100, }; VOID_T kettle_init() { b3950_init(); thread_init(); kettle_gpio_init(); ts02n_key_init(&kettle_key_def_s);//Register keys and initialize } //Triggered after the boiling key is pressed and released void key1_cb_fun() { //Button press prompt led1_set(OFF); buzzer_flag = 1; //Button press prompt if(get_kettle_work_status() == boil) { //if current status is boil, close boiling set_kettle_work_status(nature); set_dp_boil_value(FALSE); report_one_dp_status(DP_BOIL); }else { set_kettle_work_status(boil); set_dp_boil_value(TRUE); report_one_dp_status(DP_BOIL); } } //Triggered after the holding key is pressed and released void key2_cb_fun() { //Button press prompt led2_set(OFF); buzzer_flag = 1; //Button press prompt if(get_kettle_work_status() == keep_warm_mode1) {//if current status is keep_warm_mode1,turn off insulation function set_kettle_work_status(nature); set_dp_keep_warm_switch(0); report_one_dp_status(DP_KEEP_WARM); }else { set_kettle_work_status(keep_warm_mode1); //tap water warm mode :1.boil -> 2.keep warm set_kettle_keep_warm_temper(Default_Warm_Temperature); set_dp_keep_warm_switch(1); report_one_dp_status(DP_KEEP_WARM); report_one_dp_status(DP_TEMP_SET); } } //Press and hold the heat preservation key for 5s to trigger the power distribution mode void key2_long_press_cb_fun() { led2_set(OFF); tuya_iot_wf_gw_unactive(); buzzer_flag = 1; } //Triggered when the key is pressed void key1_Low_level_cb_fun() { PR_DEBUG("key1_Low_level_cb"); led1_set(ON); if(buzzer_flag) { timer_init();//The buzzer rings once buzzer_flag = 0; } } //Triggered when the key is pressed void key2_Low_level_cb_fun() { led2_set(ON); PR_DEBUG("key2_Low_level_cb"); if(buzzer_flag) { timer_init();//The buzzer rings once buzzer_flag = 0; } }
- At this time, the key driving function of the intelligent kettle has been realized. See the subsequent articles for the realization of other functions.
technical support
You can get graffiti support in the following ways:
- Developer Center: https://developer.tuya.com
- Help center: https://support.tuya.com/help
- Technical support work order center: https://service.console.tuya.com