Teensy 3.x inital support for 6pwm

Hi guys,

The initial 6pwm support for Teensy 3.x and Teensy LC boards is in the dev branch

For now simplefoc will support one 6PWM driver per Timer (FTMx) so only the boards Teensy 3.5 and Teensy3.6 will be able to support 2 motors.

The support is a preliminary and it would be really cool if you guys can test it and let us know what you think. For the next release we will try to work our way to Teensy 4.x boards and to a more flexible 6pwm implementation.

Supported boards

For now simplefoc supports 6pwm for boards:

  • Teensy 3.0 - chip MK20DX128
    Teensy 3.1/3.2 - chip MK20DX256
  • Teensy 3.5 - chip MK20DX128
  • Teensy LC - chip MKL26Z64
  • Teensy 3.5 - chip MK64FX512 - two 6pwm drivers
  • Teensy 3.6 - chip MK66FX1M0 - two 6pwm drivers

Supported pinouts

We support only the hardware 6PWM mode, meaning that all 6 pins have to belong to the same timer. As all the teensy boards 3.x/LC have at least 6 channels on their timer FTM0, this is a safe and most standard implementation. All these boards have

  • FTM0_CH0 - 22
  • FTM0_CH1 - 23
  • FTM0_CH2 - 9
  • FTM0_CH3 - 10
  • FTM0_CH4 - 6
  • FTM0_CH5 - 20

Boards 3.5/3.6 have 6 channels of the timer FTM3 as well so that can additionally support 6pwm on pins:

  • FTM3_CH0 - 2
  • FTM3_CH1 - 14
  • FTM3_CH2 - 7
  • FTM3_CH3 - 8
  • FTM3_CH4 - 35
  • FTM3_CH5 - 46

Example code

There is an example code in the library examples folder that you can use to start off your applications.

// 6pwm standalone example code for Teensy 3.x boards
#include <SimpleFOC.h>


// BLDC driver instance
// using FTM0 timer
BLDCDriver6PWM driver = BLDCDriver6PWM(22,23, 9,10, 6,20, 8);
// using FTM3 timer - available on Teensy3.5 and Teensy3.6
// BLDCDriver6PWM driver = BLDCDriver6PWM(2,14, 7,8, 35,36, 8);

void setup() {
  Serial.begin(115200);
  // Enable debugging
  // Driver init will show debugging output
  SimpleFOCDebug::enable(&Serial);

  // pwm frequency to be used [Hz]
  driver.pwm_frequency = 30000;
  // dead zone percentage of the duty cycle - default 0.02 - 2%
  driver.dead_zone=0.02;
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  // Max DC voltage allowed - default voltage_power_supply
  driver.voltage_limit = 12;
  
  // driver init
  driver.init();
  
  // enable driver
  driver.enable();
  
  _delay(1000);
}

void loop() {
  // setting pwm
  // phase A: 3V
  // phase B: 6V
  // phase C: 5V
  driver.setPwm(3,6,5);
}

The code has been tested and it outputs proper center-aligned PWM signal as well as correct dead-zone and pwm frequency provided by the driver.dead_zone and driver.pwm_frequency.

Let us know what you think.

3 Likes

@Antun_Skuric

That’s great! Only one comment, the example code is for fixed PWM and I’ve seen quite a few people running it blindly and wondering why the motor doesn’t move. Perhaps in the future we could provide an open loop example so they don’t get confused.

Cheers,
Valentine

You’re absolutely right. I’ve added a velocity openloop example in the library examples folder. It will be in the next release.

Here is a code example of how to use the 6pwm driver with Teensy 3x in the open loop velocity control:

// 6pwm openloop velocity example
#include <SimpleFOC.h>


// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(11);
// using FTM0 timer
// BLDCDriver6PWM(pwmA_H, pwmA_L, pwmB_H,pwmB_L, pwmC_H, pwmC_L)
BLDCDriver6PWM driver = BLDCDriver6PWM(22,23, 9,10, 6,20, 8);
// using FTM3 timer - available on Teensy3.5 and Teensy3.6
// BLDCDriver6PWM driver = BLDCDriver6PWM(2,14, 7,8, 35,36, 8);

// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&motor.target, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }

void setup() {

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  // limit the maximal dc voltage the driver can set
  // as a protection measure for the low-resistance motors
  // this value is fixed on startup
  driver.voltage_limit = 6;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  // limiting motor movements
  // limit the voltage to be set to the motor
  // start very low for high resistance motors
  // currnet = resistance*voltage, so try to be well under 1Amp
  motor.voltage_limit = 3;   // [V]
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();

  //initial motor target
  motor.target=0;

  // add target command T
  command.add('T', doTarget, "target velocity");
  command.add('L', doLimit, "voltage limit");

  Serial.begin(115200);
  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");
  _delay(1000);
}

void loop() {

  // open loop velocity movement
  // using motor.voltage_limit 
  motor.move();

  // user communication
  command.run();
}