Hello everybody,
i am currently working on a project which includes driving a MOSFET driver chip at a frequency of 40 kHz with 2 complementary signals.
So pin 1 should be LOW when pin 2 is HIGH and pin 1 should be HIGH when pin 2 is LOW.
Because of the high frequency in wanted to do this in hardware using the PWM module of Teensy.
Unfortunately I could not find any resources on how to accomplish this using FlexPwm.
After some digging I found FlexPwm driver examples in the MCUXpresso SDK from NXP. After some more digging I was able to get this running on the Teensy.
Because it took me a good amount of time, I wanted to share my findings and maybe help somebody with the same issue.
I added the following function to pwm.c file in cores/teensy4.
This function should allow to invert the polarity of any FlexPwm pin on Teensy 4. (see pin definitions in pwm.c to find out which pins are FlexPwm pins)
Also see https://github.com/jannst/cores/commit/ee23db74963caabe8fc84caee9458a24a559038e
As a proof of concept I wrote the following sketch.
You need to clone my fork of the cores repository and checkout the add_pwm_polarity_inversion branch to get this working.
You should then be able to change the duty cycle of all outputs with keys "S" and "D". With the keys "F", "G", "H", "J" you can invert the polarity of the different outputs.
As I am pretty much a beginner to Teensy and Microcontrollers in general, I am very curious what you think about this solution and if there is an easier way to do this.
Greetings,
Jannik
i am currently working on a project which includes driving a MOSFET driver chip at a frequency of 40 kHz with 2 complementary signals.
So pin 1 should be LOW when pin 2 is HIGH and pin 1 should be HIGH when pin 2 is LOW.
Because of the high frequency in wanted to do this in hardware using the PWM module of Teensy.
Unfortunately I could not find any resources on how to accomplish this using FlexPwm.
After some digging I found FlexPwm driver examples in the MCUXpresso SDK from NXP. After some more digging I was able to get this running on the Teensy.
Because it took me a good amount of time, I wanted to share my findings and maybe help somebody with the same issue.
I added the following function to pwm.c file in cores/teensy4.
This function should allow to invert the polarity of any FlexPwm pin on Teensy 4. (see pin definitions in pwm.c to find out which pins are FlexPwm pins)
Also see https://github.com/jannst/cores/commit/ee23db74963caabe8fc84caee9458a24a559038e
Code:
void flexPwmInvertPolarity(uint8_t pin, bool inversePolarity)
{
const struct pwm_pin_info_struct *info;
if (pin >= CORE_NUM_DIGITAL) return;
info = pwm_pin_info + pin;
//return if not a FlexPWM pin
if (info->type != 1) return;
// FlexPWM pin
IMXRT_FLEXPWM_t *flexpwm;
switch ((info->module >> 4) & 3) {
case 0: flexpwm = &IMXRT_FLEXPWM1; break;
case 1: flexpwm = &IMXRT_FLEXPWM2; break;
case 2: flexpwm = &IMXRT_FLEXPWM3; break;
default: flexpwm = &IMXRT_FLEXPWM4;
}
unsigned int submodule = info->module & 0x03;
uint8_t channel = info->channel;
uint8_t polarityShift = 0;
//find out offset for the channel
//TODO: move magic numbers to declarations
switch (channel) {
case 0: // X
polarityShift = 8U; //PWM_OCTRL_POLX_SHIFT
break;
case 1: // A
polarityShift = 10U; //PWM_OCTRL_POLA_SHIFT
break;
case 2: // B
polarityShift = 9U; //PWM_OCTRL_POLB_SHIFT
}
//if polarityShift was not initialized skip
if(!polarityShift) return;
//update polarity
if(inversePolarity) {
flexpwm->SM[submodule].OCTRL |= ((uint16_t)1U << (uint16_t)polarityShift);
} else {
flexpwm->SM[submodule].OCTRL &= ~((uint16_t)1U << (uint16_t)polarityShift);
}
}
As a proof of concept I wrote the following sketch.
You need to clone my fork of the cores repository and checkout the add_pwm_polarity_inversion branch to get this working.
You should then be able to change the duty cycle of all outputs with keys "S" and "D". With the keys "F", "G", "H", "J" you can invert the polarity of the different outputs.
Code:
#include "Arduino.h"
#include <stdbool.h>
#define FlexPWM1_1_X 0
#define FlexPWM1_0_X 1
#define FlexPWM4_2_A 2
#define FlexPWM4_2_B 3
bool invertFlexPWM1_1_X = false;
bool invertFlexPWM1_0_X = false;
bool invertFlexPWM4_2_A = false;
bool invertFlexPWM4_2_B = false;
int duty = 128; // 50%
void setup()
{
Serial.begin(9600);
analogWriteFrequency(FlexPWM1_1_X, 40000);
analogWriteFrequency(FlexPWM1_0_X, 40000);
analogWriteFrequency(FlexPWM4_2_A, 40000);
//no need to setup frequency for FlexPWM4_2_B as it is on the same timer ans same submodule as FlexPWM4_2_A
analogWrite(FlexPWM1_1_X, duty);
analogWrite(FlexPWM1_0_X, duty);
analogWrite(FlexPWM4_2_A, duty);
analogWrite(FlexPWM4_2_B, duty);
}
void loop()
{
if (Serial.available()) {
char incoming = Serial.read();
if(incoming == 'a') {
duty--;
Serial.printf("duty=%d\n", duty);
analogWrite(FlexPWM1_1_X, duty);
analogWrite(FlexPWM1_0_X, duty);
analogWrite(FlexPWM4_2_A, duty);
analogWrite(FlexPWM4_2_B, duty);
}else if(incoming == 'd') {
duty++;
Serial.printf("duty=%d\n", duty);
analogWrite(FlexPWM1_1_X, duty);
analogWrite(FlexPWM1_0_X, duty);
analogWrite(FlexPWM4_2_A, duty);
analogWrite(FlexPWM4_2_B, duty);
}else if(incoming == 'f') {
invertFlexPWM1_1_X = !invertFlexPWM1_1_X;
flexPwmInvertPolarity(FlexPWM1_1_X, invertFlexPWM1_1_X);
Serial.printf("invertd FlexPWM1_1_X (pin %d): %d\n", FlexPWM1_1_X, invertFlexPWM1_1_X);
}else if(incoming == 'g') {
invertFlexPWM1_0_X = !invertFlexPWM1_0_X;
flexPwmInvertPolarity(FlexPWM1_0_X, invertFlexPWM1_0_X);
Serial.printf("invertd FlexPWM1_0_X (pin %d): %d\n", FlexPWM1_0_X, invertFlexPWM1_0_X);
}else if(incoming == 'h') {
invertFlexPWM4_2_A = !invertFlexPWM4_2_A;
flexPwmInvertPolarity(FlexPWM4_2_A, invertFlexPWM4_2_A);
Serial.printf("invertd FlexPWM4_2_A (pin %d): %d\n", FlexPWM4_2_A, invertFlexPWM4_2_A);
}else if(incoming == 'j') {
invertFlexPWM4_2_B = !invertFlexPWM4_2_B;
flexPwmInvertPolarity(FlexPWM4_2_B, invertFlexPWM4_2_B);
Serial.printf("invertd FlexPWM4_2_B (pin %d): %d\n", FlexPWM4_2_B, invertFlexPWM4_2_B);
}
}
}
As I am pretty much a beginner to Teensy and Microcontrollers in general, I am very curious what you think about this solution and if there is an easier way to do this.
Greetings,
Jannik