This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

There seems to be a problem in controlling led sequentially using a timer.

Hello.

I'm working on sdk v17 and I'm trying to control the LEDs in order using a timer.
Before using the timer, we made it easy using delays. Apps work when they receive certain data

static void nus_data_handler(ble_nus_evt_t * p_evt)
{
    uint8_t string_buffer[BLE_NUS_MAX_DATA_LEN+1];

    if (p_evt->type == BLE_NUS_EVT_RX_DATA)
    {
        memcpy(string_buffer, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
        string_buffer[p_evt->params.rx_data.length] = 0;
        .
        .
        .
        else if(strcmp("2", string_buffer) == 0) 
        {
           NRF_LOG_INFO("Left LED Moning");
           printf("Left MOVE!\n");

           nrf_gpio_pin_clear(LED_1); //LED Off 
           nrf_gpio_pin_clear(LED_2);
           nrf_gpio_pin_clear(LED_3); 
            
           for(int i=0; i<5; i++) //5times
           {
              //NRF_LOG_INFO("Left LED Moving");
              //printf("Left MOVE!\n");
              nrf_gpio_pin_set(LED_1); //LED ON 1,2,3
              nrf_delay_ms(500);
              nrf_gpio_pin_set(LED_2);
              nrf_delay_ms(500);
              nrf_gpio_pin_set(LED_3);
              nrf_delay_ms(500);

              nrf_gpio_pin_clear(LED_1); //LED Off
              nrf_gpio_pin_clear(LED_2);
              nrf_gpio_pin_clear(LED_3);
              nrf_delay_ms(300);

              /*nrf_gpio_pin_set(LED_1);
              LeftLED_timers_start(); //without delay
              nrf_gpio_pin_set(LED_2);
              LeftLED_timers_start(); 
              nrf_gpio_pin_set(LED_3);
              LeftLED_timers_start(); 

              nrf_gpio_pin_clear(LED_1); //LED Off
              nrf_gpio_pin_clear(LED_2);
              nrf_gpio_pin_clear(LED_3);
              LeftLED_timers_start();*/
           }
        } 
        else if(strcmp("3", string_buffer) == 0) 
        {
           nrf_gpio_pin_clear(LED_1); //LED Off 
           nrf_gpio_pin_clear(LED_2);
           nrf_gpio_pin_clear(LED_3); 
            
           for(int i=0; i<5; i++) //5times
           {
              NRF_LOG_INFO("Right LED Moving");
              printf("Right MOVE!\n");
              nrf_gpio_pin_set(LED_3); //LED ON 3,2,1
              nrf_delay_ms(500);
              nrf_gpio_pin_set(LED_2);
              nrf_delay_ms(500);
              nrf_gpio_pin_set(LED_1);
              nrf_delay_ms(500);

              nrf_gpio_pin_clear(LED_1); //LED Off
              nrf_gpio_pin_clear(LED_2);
              nrf_gpio_pin_clear(LED_3);
              nrf_delay_ms(300);
           }

        }

    }
}        

And I made a timer and used it without delay.
APP_TIMER_DEF(m_LeftLED_timer_id); //Left LED Timer, singleshot timer


static void LeftLED_timer_handler(void * p_context)
{
    //Use only for delay
}

static void timers_init(void)
{
    ret_code_t err_code;

    // Initialize timer module.
    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
    .
    .
    // Create Left LED timers.
    err_code = app_timer_create(&m_LeftLED_timer_id,
                                APP_TIMER_MODE_SINGLE_SHOT, //SINGLE_SHOT or REPEATED //single shot timer
                                LeftLED_timer_handler);   
    APP_ERROR_CHECK(err_code);     
}

static void LeftLED_timers_start(void)
{
    ret_code_t err_code;

    // Start application timers.
    err_code = app_timer_start(m_LeftLED_timer_id, APP_TIMER_TICKS(500), NULL); //0.5sec delay
    APP_ERROR_CHECK(err_code);
    //printf("Left_Led Start\n");
}

static void nus_data_handler(ble_nus_evt_t * p_evt)
{
        .
        .
        .
        else if(strcmp("2", string_buffer) == 0) 
        {
          for(int i=0; i<5; i++) //5times
          {
              nrf_gpio_pin_set(LED_1);
              LeftLED_timers_start(); //delay
              nrf_gpio_pin_set(LED_2);
              LeftLED_timers_start(); 
              nrf_gpio_pin_set(LED_3);
              LeftLED_timers_start(); 

              nrf_gpio_pin_clear(LED_1); //LED Off
              nrf_gpio_pin_clear(LED_2);
              nrf_gpio_pin_clear(LED_3);
              LeftLED_timers_start();
           }
        }    
}
However, this will stop everything if the app sends data to use that feature.
Can you tell me what I did wrong?

Thank you very much.
Parents
  • Hi,

    Looking at the first implementations with only delays, that seems straight-forward. Looking at the second implementation I see that you have replaced the delays with calls to LeftLED_timers_start(), where you essentially just start the app timer instance. You do not wait for anything, so it should just continue immediately after. Obviously that is not want you want, but you should not get other issues (like "stop everything"), as calling app_timer start for an allready running timer is allowed. Have you debugged to see what is happening? Are any errors returned from any function calls or similar? If you are still stuck, please share a bit more of your code so that we can better understand what is going on.

    I also want to mention that while I do not see any waiting in your second code (waiting for the timer to timeout), you should remember interrupt priorities. The NUS handler will normally have the same interrupt priority as the lowest SoftDevice priority, and therefore you need to have a higher priority for the app timer for this to work if you intend to use delays in there. A better solution is to move this LED code out of the interrupt, and handle it in main/thread context, as long lasting interrupts is never a good idea.

Reply
  • Hi,

    Looking at the first implementations with only delays, that seems straight-forward. Looking at the second implementation I see that you have replaced the delays with calls to LeftLED_timers_start(), where you essentially just start the app timer instance. You do not wait for anything, so it should just continue immediately after. Obviously that is not want you want, but you should not get other issues (like "stop everything"), as calling app_timer start for an allready running timer is allowed. Have you debugged to see what is happening? Are any errors returned from any function calls or similar? If you are still stuck, please share a bit more of your code so that we can better understand what is going on.

    I also want to mention that while I do not see any waiting in your second code (waiting for the timer to timeout), you should remember interrupt priorities. The NUS handler will normally have the same interrupt priority as the lowest SoftDevice priority, and therefore you need to have a higher priority for the app timer for this to work if you intend to use delays in there. A better solution is to move this LED code out of the interrupt, and handle it in main/thread context, as long lasting interrupts is never a good idea.

Children
No Data
Related