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

Infrared send driver time length is not correct sometimes, why ?

I use example ble_app_uart, SoftDevice sdk 6.2.1, when receive data from bluetooth, then drive IO pin 18 to send infrared wave. received data is Infrared raw formate, which means IO output pin send wave time length (micro second), the odd data is 'mark' time length, the even data is 'space' time length. receive data is:

Blockquote

8976 4556 600 1696 612 1688 608 540
604 544 608 540 604 544 600 1700
608 1688 608 544 600 544 608 540
604 1696 600 1700 600 548 604 544
600 1700 608 544 608 540 604 544
612

Blockquote

I call sendRaw function below to send infrared wave,The forty one data length is 612 us,however, I capture the wave time length by logic analyzer, result is 1380 us, other data is correct,why this happed, and how to fix it ? Or is there any other infrared send driver ? Thank you ! image description

below is the driver using time 1 and timer 2(time 1 to generate carrier, timer 2 to control time length)

     static   void timer_delay(volatile uint32_t usecond){
    	 //delay for usecond
    
        NRF_TIMER2->TASKS_CLEAR = 1;
        NRF_TIMER2->PRESCALER =7;                  
        NRF_TIMER2->MODE      = TIMER_MODE_MODE_Timer;
        NRF_TIMER2->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
    	NRF_TIMER2->CC[0]     = (usecond>>3);
        NRF_TIMER2->TASKS_START=1;
    		
        while(NRF_TIMER2->EVENTS_COMPARE[0] == 0)
    	  {
    	   //wait 
    	  }	
    	  NRF_TIMER2->EVENTS_COMPARE[0]=0;
    
    	  NRF_TIMER2->TASKS_SHUTDOWN=1;
    }
    
   static  void Mark(uint32_t time){

      // send carrier

        nrf_gpio_cfg_output(GPIO_OUTPUT_PIN_NUMBER);
    	nrf_gpiote_task_config(3, GPIO_OUTPUT_PIN_NUMBER, \
                               NRF_GPIOTE_POLARITY_TOGGLE, GPIOTE_CONFIG_OUTINIT_Low);
       
    	  // Clear TIMER1
        NRF_TIMER1->TASKS_CLEAR = 1;
        NRF_TIMER1->PRESCALER =4;
        NRF_TIMER1->CC[0]     =26;    
        NRF_TIMER1->CC[1]     = 9; 
        NRF_TIMER1->MODE      = TIMER_MODE_MODE_Timer;
        NRF_TIMER1->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
        NRF_TIMER1->SHORTS    = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled <<    TIMER_SHORTS_COMPARE0_CLEAR_Pos);
    	NRF_TIMER1->TASKS_START = 1;
    	timer_delay(time);
    	
    	  NRF_TIMER1->TASKS_SHUTDOWN = 1;
    	  NRF_GPIOTE->CONFIG[3] = (GPIOTE_CONFIG_MODE_Disabled   << GPIOTE_CONFIG_MODE_Pos);
       	NRF_GPIO->OUTCLR = (1UL << GPIO_OUTPUT_PIN_NUMBER);
    }
    
      


      static void sendRaw(volatile uint16_t buf[], int len, int hz)
    {
       // send driver
    
      for (int i = 0; i < len; i++) {
        if (i &1) {
            timer_delay(buf[i]);
        } 
        else {
            Mark(buf[i]);
        }
      }
    }

    void gpiote_init_Midea(){ 
        // init gpiote 
    		nrf_gpio_cfg_output(GPIO_OUTPUT_PIN_NUMBER);
    
    		nrf_gpiote_task_config(3, GPIO_OUTPUT_PIN_NUMBER, \
                               NRF_GPIOTE_POLARITY_TOGGLE, GPIOTE_CONFIG_OUTINIT_Low);
    		
    }

    void ppi_init_Midea(){
         //init ppi
		ppi_enable_channel(4,&(NRF_TIMER1->EVENTS_COMPARE[0]),&(NRF_GPIOTE->TASKS_OUT[3]));
		ppi_enable_channel(5,&(NRF_TIMER1->EVENTS_COMPARE[1]),&(NRF_GPIOTE->TASKS_OUT[3]));
	}

        static void ppi_enable_channel(uint32_t ch_num, volatile uint32_t *event_ptr, volatile uint32_t *task_ptr)
    {
       uint32_t err_code;
       uint32_t error;
      err_code =  sd_ppi_channel_assign(ch_num, event_ptr, task_ptr);
    	 if( err_code != NRF_SUCCESS ){
    					error = err_code;
    				}
      err_code =  sd_ppi_channel_enable_set(1 << ch_num);
    				if( err_code != NRF_SUCCESS ){
    					error = err_code;
    				}				
    }
Parents
  • Hi

    The problem is that you are being interrupted by the BLE stack in your while loop (when waiting for the TIMER2 event). In general it is not a good idea to base the system on while loops like this, it would be better to use the PPI to have TIMER2 turn on and off the carrier (TIMER1) in the background, so that BLE interrupts will not affect you.

    I decided to make a small example of my own to demonstrate this:
    ble_app_uart_IR.zip

    I chose to use a slightly different approach. Instead of using TIMER2 as a timer, I use it as a counter, and count the number of pulses from the carrier before turning it on and off.

    The API is comparable to yours I believe. You just provide the library a list of 16-bit values, each storing the number of microseconds the carrier should be on and off. To implement specific IR protocols you have to fill in the buffer correctly.

    The example is based off of ble_app_uart, and will output an IR version of the first UART byte sent to the nRF51 on P0.04
    The GPIO used is configured when calling the init function. All other parameters are configured in the ir_lib.h file (such as the frequency of the carrier).

    Best regards
    Torbjørn

Reply
  • Hi

    The problem is that you are being interrupted by the BLE stack in your while loop (when waiting for the TIMER2 event). In general it is not a good idea to base the system on while loops like this, it would be better to use the PPI to have TIMER2 turn on and off the carrier (TIMER1) in the background, so that BLE interrupts will not affect you.

    I decided to make a small example of my own to demonstrate this:
    ble_app_uart_IR.zip

    I chose to use a slightly different approach. Instead of using TIMER2 as a timer, I use it as a counter, and count the number of pulses from the carrier before turning it on and off.

    The API is comparable to yours I believe. You just provide the library a list of 16-bit values, each storing the number of microseconds the carrier should be on and off. To implement specific IR protocols you have to fill in the buffer correctly.

    The example is based off of ble_app_uart, and will output an IR version of the first UART byte sent to the nRF51 on P0.04
    The GPIO used is configured when calling the init function. All other parameters are configured in the ir_lib.h file (such as the frequency of the carrier).

    Best regards
    Torbjørn

Children
Related