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);
}
}
}
Hi Rudy
See page 9 of the following http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF to see how any peripheral timer on the KE14 can be used to achieve extremely high PWM measurement accuracy (even for high frequency signals) using port DMA.
Regards
Mark
Kinetis: http://www.utasker.com/kinetis.html
Kinetis KE:
- http://www.utasker.com/kinetis/FRDM-KE02Z.html
- http://www.utasker.com/kinetis/FRDM-KE02Z40M.html
- http://www.utasker.com/kinetis/FRDM-KE04Z.html
- http://www.utasker.com/kinetis/FRDM-KE06Z.html
- http://www.utasker.com/kinetis/FRDM-KE15Z.html