This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2530: Sensitive Push Button

Part Number: CC2530

Hi Guys,

I´m working on to implement a sensitive button. I´m using firstly to implement it with SmartRF05EB 1.7.1 and EM inside. 

I have in my mind to implement the code according to this rule:

- Normal press just on or off

- Press and hold more than 3 seconds the first time will increase the level,

- Press and hold more than 3 seconds will decrease level,

I have some doubts about how to detect the hold time, I have started in the HandleKeys function to detect the hold time but I don´t know how to do it using for example osal_start_timer. 

Would see below, my code with LED_ON and LED_OFF, beginning to understanding the better way to implement the code, in the future I´ll using dimmer level up and down.

  if ( (keys & HAL_KEY_SW_6) == 0) 
  {
	//giLightScreenMode = LIGHT_MAINMODE;
	 HalLedSet( HAL_LED_1, HAL_LED_MODE_ON);
	 buttonPressed =1;
	 longBtnPress = 0;
	 if(buttonPressed == 1)
        {
            // test for long or short btn press
            if(longBtnPress == 1)
            {
               zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
               longBtnPress = 0;
            }else
            {
                HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );//toggle short led
            }
			   buttonPressed = 0;
               timerCounter = 0;
		}

#ifdef ZCL_LEVEL_CTRL
   // zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
#endif
  } 

Someone has an idea how to I cam implement the mechanism to detect the hold time?

BR,

Alex

  • When you detect  button pressed in HandleKeys function, you can start a timer event comes every 100 ms to check if the button is hold. If you detect the button is hold in the timer event, you restart the event to check hold again. If not, you can count how many timer event is triggered to know how long the button is pressed and hold.

  • Hi Mr. Yikai, 

    You can see below my code, I have a problem to detect long pressure, in my strcuture, I cant increment the counter and consequently, my longBtnPress flag is not hit!

    if ( (keys & HAL_KEY_SW_6) == 0) 
      {
    	//giLightScreenMode = LIGHT_MAINMODE;
    		osal_start_timerEx( zclTTa0003_TaskID, TTa0003_LEVEL_CTRL_EVT, 100 );
    		timerCounter = timerCounter + 1;
    		longBtnPress = 0;
    		  	 
    	 //HalLedSet( HAL_LED_1, HAL_LED_MODE_ON);
    	 buttonPressed =1;
    	if(buttonPressed == 1)
            {
                // test for long or short btn press
                if(longBtnPress == 1)
                {
                   zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
                   longBtnPress = 0;
                }else
                {
                   // HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );//toggle short led
                }
    			   buttonPressed = 0;
                   //timerCounter = 0;
    		}
    		
    		 if (timerCounter > 2)
    		{
    				longBtnPress = 1;
    		}else{
    				timerCounter = 0;
    		}
    
    #ifdef ZCL_LEVEL_CTRL
       // zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
    #endif
      } 
      // update the display, including the light
      zclTTa0003_LcdDisplayUpdate();
    }

    Please, would you give me an idea to fix it?

    BR,

    Alex

  • If those codes are inside your application handlekey callback? If so, why it’s “if ( (keys & HAL_KEY_SW_6) == 0)”?

  • Hi Mr. Yikai,

    I totally agree with you, I have used a wrong way to guarantee that the bitwise conditional operation when I used it "keys & HAL_KEY_SW_6) == 0", to use a correct form keys & HAL_KEY_SW_6 in my App code inside the handle key callback, I have changed HAL_KEY_SW_6 value in hal_key.h form 0x20 to 0x14, after it the condiction will be mat. (key = 0x04 & HAL_KEY_SW_6 = 0x14). But in relation to the rest of the code, I believe that I have written something wrong, the longBtnPress = 1 is not hit! 

    As you can see part of my handle key function:

      if ( keys & HAL_KEY_SW_6) 
      {
    	//giLightScreenMode = LIGHT_MAINMODE;
    		osal_start_timerEx( zclTTa0003_TaskID, TTa0003_LEVEL_CTRL_EVT, 100 );
    		buttonPressed =1;
    			 //HalLedSet( HAL_LED_1, HAL_LED_MODE_ON);
    	
    	if(buttonPressed == 1)
            {
                // test for long or short btn press
                if(longBtnPress == 1)
                {
                   zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
                   longBtnPress = 0;
    			   timerCounter = 0;
    			   keys &= ~keys;
                }else
                {
                   // HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );//toggle short led
    			   buttonPressed = 0;
    			   keys &= ~keys;
                }
    
                   
    		}
    		
    		 if (timerCounter > 2)
    		{
    				longBtnPress = 1;
    		}else{
    				timerCounter = timerCounter + 1;
    				longBtnPress = 0;
    		}
    
    #ifdef ZCL_LEVEL_CTRL
       // zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
    #endif
      } 
      // update the display, including the light
      zclTTa0003_LcdDisplayUpdate();

    Please, Could you give me an idea?

    BR,

    Alex

     

  • Do you start a timer event comes every 100 ms to check if the button is hold after your handlekey detects SW6 is triggered?

  • Hi Mr. Yikai,

    Sorry for my mistake, I had gone the wrong way before!

    As you can see below I have check every 100 ms if the button is held after handle key detects SW6, but I believe that I have problem with OSALTIMER, always the "zclTTa0003_OnOff = zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON" is hit, even when the button is held for a long time. I have changed the OSAL timer to check from 100 at 100000 and nothing was changed!

    Note: In the OSAL Timer function say that the OSAL timeout value is in milliseconds. as described below:

    My code:

     if ( keys & HAL_KEY_SW_6) 
      {
    	//giLightScreenMode = LIGHT_MAINMODE;
    		osal_start_timerEx( zclTTa0003_TaskID, TTa0003_LEVEL_CTRL_EVT, 100);
    		 if ( keys & HAL_KEY_SW_6) {
    	
    				zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
    				//timerCounter = timerCounter + 1;
    			
    		 } else {
    			//zclTTa0003_OnOff =	zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON;
    		 
    		 }
    		
      } 
      // update the display, including the light
      zclTTa0003_LcdDisplayUpdate();
    }

    Please, would you give an idea?

    BR,

    Alex

  • Hi Mr. Yikai, 

    I did more some tests and I observed that the SW_5 has a concurrent value and when I have pressed Push Button 1 SW_5 (BasicResetCB) and SW_6 was hit at the same time.  I have changed SW_5 value in hal_key.h. 

    //#define HAL_KEY_SW_5 0x04  // Joystick center original value.
    #define HAL_KEY_SW_5 0x03  // Joystick center
    //#define HAL_KEY_SW_6 0x20  // Button S1 if available

    Right now, only SW_6 is hit. But during the debug mode I also observed that always the 2nd key check, that´s is called after the OSAL timeout,  is hit, even when there is a short pressure.

    My APP code:

    if ( keys & HAL_KEY_SW_6) // 1st key check
      {
    	//giLightScreenMode = LIGHT_MAINMODE;
    	 
    		 osal_start_timerEx( zclTTa0003_TaskID, TTa0003_LEVEL_CTRL_EVT, 100);
    		 if ( keys & HAL_KEY_SW_6) { // 2nd key check
    zclTTa0003_OnOff = zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON; //keys &= ~keys; //timerCounter = timerCounter + 1; } else { //zclTTa0003_OnOff = zclTTa0003_OnOff ? LIGHT_OFF : LIGHT_ON; } } // update the display, including the light //zclTTa0003_LcdDisplayUpdate(); }

    Maybe I need to reset key after the OSAL timeout, I tried to include keys &= ~keys; but this caused the exit of the loop.

    Please, can you help me?

    BR,

    Alex

  • Hi Mr. Yikai,

    Please do not consider my last 2 threads, I´m working on to define the OSAL Event to detect Btn hold press and Btn short press. 

    What you suggest to me, I can delete the two last threads or keep it?

    BR,

    Alex

  • You can keep them but show me your latest progress.

  • Ok, Mr. Yikai! Thanks!

    I´ll show you my last progress, I evolved a lot!

    I as told you I have created a specific event, I have called as BtnHOLD_EVT, to try to make a correct a Btn treatment. As you can see below:

    at zcl_TTa0003.h, I have inserted in the App events:

    #define TTa0003_BtnHOLD_EVT		         0x0060 

    at zcl_TTa0003.c, I have inserted:

     if ( events & TTa0003_BtnHOLD_EVT )
      {
         if ( HAL_PUSH_BUTTON1())  // Btn long press
        {
          BtnHoldCnt++;
          
          if(BtnHoldCnt >=1)
          {
    		HalLedSet ( HAL_LED_3, HAL_LED_MODE_OFF );  
            
          }
          else
            osal_start_timerEx( zclTTa0003_TaskID, TTa0003_BtnHOLD_EVT, 100);
        }
         else  // Btn short press
        {
         HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
        }
        return ( events ^ TTa0003_BtnHOLD_EVT );
      }

    and in the handle key call back:

    if ( keys & HAL_KEY_SW_6) 
      {
    	  BtnHoldCnt =0;
    	  //HalLedSet ( HAL_LED_3, HAL_LED_MODE_BLINK );
          osal_start_timerEx( zclTTa0003_TaskID, TTa0003_BtnHOLD_EVT, 100);
    		
      } 

    But I was observing that always after the end of event treatment, hold (Btn long press) or short (Btn short press) conditional procedure the program return to handle key callback, this is causing a program loop!

    I think that I need to include at the end of events & TTa0003_BtnHOLD_EVT function something to stop it. Maybe clear an interrupt flag!

    Could you give an Idea?

    BR,

    Alex

  • The event definition is a bit flag mask like 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020,.... so TTa0003_BtnHOLD_EVT cannot be defined as 0x0006.
  • Mr. Yk,

    I already set the TTa0003_BtnHOLD_EVT as you told me to become it bit maskable, as you can see below:

    #define TTa0003_BtnHOLD_EVT		         0x0080 

    But, my program has strange behavior, after handle key started the OSAL timer and the BtnHOLD_EVT event has been finalized the event handle key still called and start the procedure again. In my example, the LED_3 will be turned on in the short process and turned off in the holding press, but this LED never been turn off, motived by cyclical procedure (loop) handle key -> BtnHOLD_EVT (hold or short) -> handle key. 

    Please, Could you give me an idea?

    BR,

    Alex

     

  • Hi Mr Yk!

    I´ll try to explain for you better whats is happening with my code:

    I observed that:

    1 - the interruption only occurs when I have to hold and release the S1 button. When it occurs, my call back (SW6) function will be called 

    2 - After it, my code interprets two states:

    a) if S1 is pressed again and hold (the condition HAL_PUSH_BUTTON1 has been reached) and the LED3 will turn off. 

    b) if S1 is pressed again and release the condiction that occurred in option a is not reached and the LED 3 will turn on.

    in both condition above (a or b) my function call back will be called again, at the end of event treatment, and then If the LED3 is off, according to the status a (pressed and hold) the LED3 will turn on again. In practice, LED3 starts off, in the 1st pression and release turn on and after it still turns on, even pressing S1 several times. As I described above.

    Please, can you give an idea of how to fix it in my code?

    BR,

    Alex

  • Hi Mr Yk.

    I´m very happy, I had success after change a little bit my code, now my code can check well short and long pressure, as you can see below:

      if ( events & TTa0003_BtnHOLD_EVT )
      {
         if ( HAL_PUSH_BUTTON1())//Btn long press
        {
         // BtnHoldCnt++;
          
    			if(BtnHoldCnt >=10)
    			{ 
    				BtnHoldCnt=0;
    				HalLedSet (HAL_LED_3, HAL_LED_MODE_ON);  
            
    			} else {
    				BtnHoldCnt++;
    				HalLedSet ( HAL_LED_3, HAL_LED_MODE_OFF);
    				osal_start_timerEx( zclTTa0003_TaskID, TTa0003_BtnHOLD_EVT, 100);}
    		
        } else // Btn short press
    		{ret=osal_start_timerEx( zclTTa0003_TaskID, TTa0003_BtnHOLD_EVT, 100);} // return to handle key
        
    	return ( events ^ TTa0003_BtnHOLD_EVT );
      }

    The next step I need to study how to:

    >  Check the direction to detect long pressure to increase and decrease,

    >  Associate the Level dimmer variable to increase and decrease dimmer level ( i used LED3 Turn on and turn off temporally, just to validate the code),

    >  Send dimmer level feedback from device to the gateway.

    I´ll let you my progress soon!

    Mr Yk I would like to say thanks a lot!

    BR,

    Alex