Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Using timer interrupt and flash storage in nRF51

Hi,

I am using ble_app_uart sample code. In that I want to run a timer based on the commands received in BLE. i.e., if command received is 'one' , LED1 should ON for one hour and the timing values should be written into flash storage. If any power reset is there, particular LED should run for remaining time. The timer counter value should be updated for every one hour into flash.

How it can be done. any sample code is there for similar kind?

Parents
  • Hello, 

    Typically you need to first define a timer to run at a given interval, for instance every 100seconds. Then in the timeout handler (every 100 seconds) you can increment a counter, and once the counter has reached 36 (*100seconds) you can stop the timer and turn off the LED. To define, create and start a timer you will need to use:

     

    APP_TIMER_DEF(your_timer_id);
    
    app_timer_create(&your_timer_id,...,your_timeout_handler);
    
    app_timer_start(your_timer_id,..);
    
    static void your_timeout_handler(void * p_context)
    {
    
    // increment counter;
    
    // turn off LED and stop timer when counter reach a value.
    
    }

    I don't think it is such a good idea to write timing data into flash at every interval, it may potentially wear out flash if you do this for instance every 100 seconds (864times a day). You should try to instead avoid power on reset to occur this frequently. 

  • Thanks for your reply. I need to write the count value in the flash because it's going to be a use case so it is important also.

    Also, whenever I am disconnecting the BLE connection timer gets reset, so the LED also goes OFF. Usually I will send command to BLE device from mobile phone and will be disconnecting the BLE connection with the mobile phone.Is there any way to fix this?

  • I suggest you first look into making LED work, and then second step can be flash.

    Regarding LED, there is no link or dependencies between app_timer() and BLE events. The BLE stack is using it's own timer(s).

  • Yes correct. There is no dependency with app_timer() and BLE events.

    I want to change the timeout value as soon as got the command through BLE. i.e, First command received is "one" so LED should glow for one hour, in between only I am sending second command as "three" which should run for 3 hour. It should actually take the recent command and process it. so the LED should glow for 3 hours as per the recent command(Total of 3 hours).

    How to do this?

    Also BLE is getting disconnect when second command is sent while first command is running

  • How about having two global variables, one which is the max time value (e.g. in hours) and one which is an counter counting minutes (e.g. 60seconds timeout). Then the application can always update either of the two global variables on demand to extend or shorten the time.

Reply Children
  • See my code below.

    uint32_t timeout = 0,count=0;
    
    APP_TIMER_DEF(m_led_a_timer_id);
    
    // Timeout handler for the  timer
    static void timer_a_handler(void * p_context)
    {
    
    		nrf_gpio_pin_clear(3);
    
    }
    
    
    // Create timers
    static void create_timers()
    {   
        uint32_t err_code;
    
        // Create timers
        err_code = app_timer_create(&m_led_a_timer_id,
                                    APP_TIMER_MODE_SINGLE_SHOT,
                                    timer_a_handler);
        APP_ERROR_CHECK(err_code);
    	
    	err_code = app_timer_start(m_led_a_timer_id, APP_TIMER_TICKS(timeout, APP_TIMER_PRESCALER), NULL);
       APP_ERROR_CHECK(err_code);
    }
    
    
    static void check_rcv_data(uint8_t * rcv_p_data)
    {
    	  uint32_t time_ms = 5000; //Time(in miliseconds) between consecutive compare events.
        uint32_t time_ticks;
        uint32_t err_code = NRF_SUCCESS;
         
    
    		if(strstr((char *)rcv_p_data, "Dev"))
    		{
    //			printf("dev\n\r");
    		update_device_name(rcv_p_data);
    		}
    		
    		else if((strcmp((char *)rcv_p_data, "one") == 0))
    		{
    			nrf_gpio_pin_set(3);
    			timeout+=60000;
    		  count++;
    			create_timers();
    	}
    	
    	else if((strcmp((char *)rcv_p_data, "two") == 0))
    		{
    			nrf_gpio_pin_set(3);
    			timeout+=120000;
    			count++;
    			create_timers();
            
        }
    	
    	else if((strcmp((char *)rcv_p_data, "three") == 0))
    		{
    			nrf_gpio_pin_set(3);
    			timeout+=180000;
    			count++;
    			create_timers();
    	}
    	
    	else if((strcmp((char *)rcv_p_data, "four") == 0))
    		{
    			nrf_gpio_pin_set(3);
    			timeout+=240000;
    			count++;
    			create_timers();
    	}
    	
    	else if((strcmp((char *)rcv_p_data, "five") == 0))
    		{
    			nrf_gpio_pin_set(3);
    			timeout+=300000;
    			count++;
    			create_timers();
    	}
    	
    		else 
    		{
    			invalid_cmd();
    		}
    	}
    
    static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)
    {
    	
    		uint32_t i;
        for (i = 0; i < length; i++)
        {
         
        }
    		p_data[i] = '\0';
    
    		
    		printf("%s",p_data);
    		
    		check_rcv_data(p_data);
    
    }

  • I was thinking more like this:

    uint32_t 1_minute_counter = 0, max_timeout = 60;
    
    APP_TIMER_DEF(m_led_a_timer_id);
    
    // 1 minute handler for the timer
    static void timer_a_handler(void * p_context)
    {
    	1_minute_counter++;
    
    	if(1_minute_counter >= max_timeout)
    	{
    		nrf_gpio_pin_clear(3);
    	}
    }
    
    // Start timer
    static void create_timers()
    {   
    	uint32_t err_code;
    
    	err_code = app_timer_create(&m_led_a_timer_id,APP_TIMER_MODE_INTERVAL,timer_a_handler);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = app_timer_start(m_led_a_timer_id, APP_TIMER_TICKS(60_seconds_timeout, APP_TIMER_PRESCALER), NULL);
    	APP_ERROR_CHECK(err_code);
    }
    
    // The application can now clear 1_minute_counter or change max_timeout to adjust when pin should be cleared.
    

Related