TS02N touch button driver for graffiti intelligent kettle software

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.
functionexplain
boilingTouch 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 keyTouch 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:

Keywords: C

Added by DrJonesAC2 on Tue, 08 Feb 2022 10:16:14 +0200