AnsweredAssumed Answered

Calculate PWM duty and period time with FTM timer

Question asked by Rudy Coppens on Sep 14, 2018
Latest reply on Sep 14, 2018 by Mark Butcher

Hardware:

- MKE14F16

 

Software:

MCUXpresso IDE 10.1.1

 

I know that this is very simple with the dual capture mode on the chip with the FTM module, but I routed unfortunately the PWM input not on a FTM channel pin... But I thought you can just use a timer and the gpio controller to do the same with a simple counter/timer. 

I did the following:

- Start a FTM counter that will start from a rising edge on the pin and set the input to a falling edge trigger

- When falling edge read counter value and store it for the duty cycle and set input trigger on rising edge

- When rising edge read counter value again and store this value for the period time

- duty cycle / period time and you will have the duty cycle in percent what I want to have. 

 

My problem is that the counter reading is not constant. the duty cycle time is always very close to the period time and I have always a duty cycle reading higher than 90% even with an input pwm signal of 10%. The counter values are always different.... 

 

The input signal is 75Hz so that would not be an issue. In the program only Read_Pump() is called every 5 seconds with another timer. 

 

void Read_Pump(void)
{
   //Set the pump port pin to interrupt rising edge
   PORT_SetPinInterruptConfig(PORTA, 7U, kPORT_InterruptRisingEdge);
   //Enable the interrupt
   EnableIRQ(PORTA_IRQn);
}


void IRQ_HANDLER_PORT_A(void)
{
   uint32_t Interrupt_Flags_A = GPIO_PortGetInterruptFlags(GPIOA);

   if((Interrupt_Flags_A >> 7U) & 1)
   {
      GPIO_PortClearInterruptFlags(GPIOA, 1U << 7U);
      //Duty Cycle is over, store timer value in duty cycle
      if(Pulse_Started)
      {

         //Calculate the PWM duty cycle in %
         Duty_Time = FTM_GetCurrentTimerCount(FTM3);
         //Set the interrupt to rising edge to find the period time
         PORT_SetPinInterruptConfig(PORTA, 7U, kPORT_InterruptRisingEdge);
         Period_Over = true; //After a rising edge the period is over
         Pulse_Started = false;
         EnableIRQ(PORTA_IRQn);
      }
      else
      {
         //start the timer and switch the interrupt flag to failing edge and make Pulse_Started True
         FTM_StartTimer(FTM3, kFTM_SystemClock); //Start the timer
         PORT_SetPinInterruptConfig(PORTA, 7U, kPORT_InterruptFallingEdge);
         Pulse_Started = true;
         EnableIRQ(PORTA_IRQn);
       }
      if(Period_Over)
      {
         Period_Time = FTM_GetCurrentTimerCount(FTM3);
         FTM_StopTimer(FTM3); //Stop the timer
         float period = (float)Period_Time;
         float duty = (float)Duty_Time;
         float percentage = duty/period; //Calculate the percentage on of the period
         percentage = percentage*100;
         Period_Over = false;
         SUS_Data.Pump_In_Duty = percentage; //Store PWM duty to local variable
         DisableIRQ(PORTA_IRQn);
        }

   }

}

Outcomes