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

How to decode pwm?

Hello everybody,

I am using sdk14.2, s132 with Nrf52832. I want to define the pin of the NRF52 as the input and decode the incoming pwm signal. For example, I have a signal at 100 Hz and the duty cycle is as follows; {70%, 80%, 90%, 60%, 50%, 40%, 30%}. After I connect this signal to PIN 2, I want to keep the duty cycle into an array, and I want to keep the frequency into a variable. I have found an example that reads frequency from previously asked question. But in this question, the duty cycle is not read, only the frequency is read. 

I plotted a pwm signal for an example;

PWM

I want to assign frequency and duty cycle to these variables.

uint32_t frequency;
uint8_t duty_cycle[7];

When I give this signal, result  should be like this;

frequency =100,

duty_cycle = {70,80,90,60,50,40,30}.


Do you have any suggestions?

  • Hello,

    Can you please check out this post? It is a post I handled today, but the answer would be pretty much the same in this case. You should see how it measures the time between a rise and fall on an input gpio.

     

    If anything is unclear, or it doesn't work, please let me know.

     

    Best regards,

    Edvin

  • The program code is as follows;

    static void timer_init_2()
    {
    	NRF_TIMER1->TASKS_STOP = 1;
    	NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
    	NRF_TIMER1->PRESCALER = 8; //8;	// Fhck / 2^8 
    	NRF_TIMER1->CC[0] =  62500;	// 62500 - 1s
    	
    	NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);	
    	
    	NRF_TIMER1->TASKS_CLEAR = 1;
    	NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
    	
    	NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    }
    
    static void counter_init()
    {
    	NRF_TIMER2->TASKS_STOP = 1;	
    	NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter;
    	NRF_TIMER2->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
    	NRF_TIMER2->TASKS_CLEAR = 1;
    	NRF_TIMER2->EVENTS_COMPARE[0] = 0;
    }
    
    static void gpiote_init(uint32_t pin)
    {
    	NRF_GPIOTE->CONFIG[0] 	= 	0x01 << 0; 								// MODE: Event
    	NRF_GPIOTE->CONFIG[0] 	|= 	pin << 8;								// Pin number
    	NRF_GPIOTE->CONFIG[0] 	|= 	NRF_GPIOTE_POLARITY_LOTOHI	<< 16;		// Event rising edge 	
    }
    
    static void ppi_timer_stop_counter_init()
    {
    	NRF_PPI->CHEN |= 1 << 0;
    	*(&(NRF_PPI->CH0_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
    	*(&(NRF_PPI->CH0_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_STOP;
    	NRF_PPI->CHENSET |= 1 << 0;
    }
    
    static void ppi_gpiote_counter_init()
    {
    	NRF_PPI->CHEN |= 1 << 1;
    	*(&(NRF_PPI->CH1_EEP)) = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
    	*(&(NRF_PPI->CH1_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_COUNT;
    	NRF_PPI->CHENSET |= 1 << 1;
    }
    
    void TIMER1_IRQHandler(void) 
    {
    	if (NRF_TIMER1->EVENTS_COMPARE[0] != 0)
    	{
    		NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    		NRF_TIMER2->TASKS_CAPTURE[0] = 1;
    				
    		NRF_LOG_INFO("cc: %dHz", NRF_TIMER2->CC[0]);
    		
          	
    		NRF_TIMER1->TASKS_CLEAR = 1;
    		NRF_TIMER2->TASKS_CLEAR = 1;	
    						
    		NRF_TIMER2->TASKS_START = 1;			
        }
    }
    
    
    int main(void)
    {
        .
        .
        .
        
        // Start scanning for peripherals and initiate connection
        // with devices that advertise KALE UUID.
    			NRF_LOG_INFO("KEYFOB example started.");
    		
    		 // Soft Device initialization..
    			nrf_gpio_cfg_output(30);
    			NVIC_EnableIRQ(TIMER1_IRQn);
    			NVIC_SetPriority(TIMER1_IRQn, 7);	
    
    			nrf_gpio_cfg_input(FREQ_MEASURE_PIN, NRF_GPIO_PIN_NOPULL);
    
    			counter_init();
    			timer_init_2();
    			gpiote_init(FREQ_MEASURE_PIN);
    			ppi_gpiote_counter_init();
    			ppi_timer_stop_counter_init();
    
    			NRF_TIMER1->TASKS_START = 1;
    			NRF_TIMER2->TASKS_START = 1;
    			
    	for(;;)
    	{
            if (NRF_LOG_PROCESS() == false)
            {
                nrf_pwr_mgmt_run();
            }
        }
    }
    
    

    Here, the frequency value is obtained from the number of rising edges. To calculate the duty cycle it is necessary to count the falling edge as you know. I will calculate the duty cycle from the "(rising - falling)/Period" equation. I could not figure out how to count both rising and falling. 

  • I assumed the Period was known.if it is 100Hz, you can use this value as the period. If you need to measure the period, you must also capture the CC on the rising edge, to see how many timer ticks there are in a period.

    You can "short" several tasks to one event.

     

    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];

    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER3->TASKS_CAPTURE[0];

    NRF_PPI->CH[0].FORK = (uint32_t)&NRF_TIMER3->TASKS_STOP;

     

    this snippet will both capture the timer and stop the timer.

    Then you will have to use different events for rising and falling to capture both of them. On the rising, you will have to capture and clear the timer.

     

    Best regards,

    Edvin

Related