Center aligned PWM speed not what was expected Teensy 3.2

Status
Not open for further replies.

nrdb

New member
Hi
Using a Teensy 3.2, I need a center-alligned PWM signal @ about 100kHz.
So I am working with the FTM0 registers directly. In consulting the docs, I have managed to setup the registers to what I thought was the correct configuration.

But my speed calculations seems to be wrong. As the calculated speed is different from what appears to be the actual speed.

I measured the actual speed by polling the CNT register and counting how many times the count direction switched from counting down to up, in 100mS.

I think this is probably due to the System Clk not being the same as the CPU clk.

Why the difference between the calculated speed and the apparent speed?
Can I make the clk for FTM0 faster?
Can I run the FTM0 from the CPU clk?

Any help appreciated.


PHP:
#include <kinetis.h>
int led = 13;
uint32_t led_timeout;
uint32_t print_timeout;

void setup() {
  pinMode(led, OUTPUT);
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial);
  Serial.println("Register Tester");
  print_timeout = millis() + 1000;
  led_timeout = millis() + 500;
  pwm_setup();
}

void pwm_setup(void)
{
/*
 * The Center-Aligned mode is selected when:
 * - QUADEN = 0
 * - DECAPEN = 0
 * - COMBINE = 0, and
 * - CPWMS = 1
 * The CPWM pulse width (duty cycle) is determined by 2 × (CnV − CNTIN) and the
 * period is determined by 2 × (MOD − CNTIN). MOD must be kept in the range 
 * of 0x0001 to 0x7FFF because values outside this range can produce
 * ambiguous results.
 * In the CPWM mode, the FTM counter counts up until it reaches MOD and then counts
 * down until it reaches CNTIN.
 */
  Serial.print ("F_CPU = "); Serial.println(F_CPU);
  FTM0_SC = 0;
  FTM0_CNTIN = 0;                         // minimum count
  FTM0_CNT = 0;                           // current count
  FTM0_MOD = F_CPU / 2 / 100000;          // maximum count
  Serial.print ("MOD "); Serial.println(FTM0_MOD, HEX);
  FTM0_SC = FTM_SC_CPWMS | FTM_SC_CLKS(1) | FTM_SC_PS(0);                // set the "Center-Aligned", system clk, x1
  //FTM0_SC = FTM_SC_CPWMS | FTM_SC_CLKS(1) | FTM_SC_PS(1);                // set the "Center-Aligned", system clk, x2
  //FTM0_SC = FTM_SC_CPWMS | FTM_SC_CLKS(1) | FTM_SC_PS(7);                // set the "Center-Aligned", system clk, x64
  uint32_t cycles = 2 * (FTM0_MOD - FTM0_CNTIN);
  Serial.print ("Pulse width = ");
  Serial.print (cycles);
  Serial.print (" cycles = ");
  Serial.print (F_CPU / cycles);
  Serial.println (" Hz");
}

#define SAMPLE_PERIOD 100
void pwm_speed(void) 
{
  uint32_t start = millis();
  uint32_t end = start + SAMPLE_PERIOD;
  uint32_t current;
  uint32_t last;
  uint32_t count = 0;
  uint8_t down;
  
  last = FTM0_CNT;
  down = (last > FTM0_CNT);           // current count direction
  while (end >= millis()) {
    current = FTM0_CNT;
    if ((last < current) && down) {   // we are now counting up
      count += 1;
    }
    down = (last > current);
    last = current;
  }
  Serial.print ("count = "); 
  Serial.print(count); 
  Serial.print ("    speed = ");
  Serial.println(count * (1000 / SAMPLE_PERIOD));
}

void loop() 
{
  if (led_timeout <= millis()) {
    if (digitalRead(led)) {
      digitalWrite(led, LOW);
      led_timeout = millis() + 900;
    }
    else {
      digitalWrite(led, HIGH);
      led_timeout = millis() + 100;
    }
  }
  if (print_timeout <= millis()) {
    print_timeout = millis() + 1000;

    pwm_speed ();
  }
}
 
Status
Not open for further replies.
Back
Top