Sparkfun Brushless Gimbal Motor Driver, Sparkfun Gimbal motor, and Teensy 4.1

Hello,

I purchases the Sparkfun Brushless Gimbal motor driver which uses the TMC6300, as well as a Sparkfun BLDC Gimbal motor. I have been attempting to drive the motor using the PWM pins on the Teensy 4.1, but I have yet to make the motor move successfully. I am applying the driver 7.4 Volts (the motor has a nominal operating voltage of 7.4 V), and the blue LED turns on indicating that the driver is activated. I followed this SimpleFOC forum post for instructions on which pins to use on the Teensy 4.1, but I still have yet to get movement out of the motor.

Can anyone think of where my issues might lie?

Here is the code I am using (also copied and pasted from the above forum, with few alterations).

// 6pwm openloop velocity example
// 
// Teensy4.x 6pwm driver generates a 6pwm signal using FlexTimers and it doesn't support the QuadTimers
//  - Each high-low pair of the 6pwm has to be A and B channels of the same FlexTimer and to the same submodule 
// 
// List of available teensy 4.1 pins with their respective submodules and channels 
// FlexPWM(timer number)_(submodule)_(channel) 
// FlexPWM4_2_A   pin 2
// FlexPWM4_2_B   pin 3  
// FlexPWM1_3_B   pin 7  
// FlexPWM1_3_A   pin 8  
// FlexPWM2_2_A   pin 6  
// FlexPWM2_2_B   pin 9  
// FlexPWM3_1_B   pin 28  
// FlexPWM3_1_A   pin 29  
// FlexPWM2_3_A   pin 36  
// FlexPWM2_3_B   pin 37  
#include <SimpleFOC.h>


// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(8);
// make sure to provide channel A for high side and channel B for low side
// BLDCDriver6PWM(pwmA_H, pwmA_L, pwmB_H,pwmB_L, pwmC_H, pwmC_L)
// Example configuration 
BLDCDriver6PWM driver = BLDCDriver6PWM(2,3, 6,9, 8,7,32);

// 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 = 8;
  // 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 = 9;
  driver.init();
  // link the motor and the driver
  
  driver.enable();
  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 = 8;   // [V]
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();

  //initial motor target
  motor.target=10;

  // 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(2);
  

  // user communication
  command.run();
}

Thanks for any and all help!

This is another argument on the pile of both the importance of a standard hardware combo and also clearer and more prominent standard advice, and also standard proceedures for getting things working. There is example code, but because there is such an enormous range of hardware people are trying to use, usually for only minor reasons the examples often don’t help much. Not saying what has been done isn’t good, only I guess that more is needed, what else is new, I guess… But with wise strategy much more bang for the buck will be obtained.

There is a bracket missing on the 6PWM line.

You should use an oscilloscope or led to see if anything is coming out the pins, then get it working in open loop mode using the examples, and then print out the sensor values, then you can try to connect the stages together.

Sorry, that missing bracket is not the reason my code has not been working. I think that happened when I copy and pasted the code into the forum post and updated the pin numbers I was using. I checked the pins coming out of the Teensy with an oscilloscope, and they are outputting the correct PWMs. I then checked the U,V, and W phase outputs of the motor driver, and they are also giving the appropriate PWM outputs at 7.4 volts (the voltage specified by the motor data sheet). I’m honestly at a loss for how those pins could be outputting the PWM signals, and the motor be receiving them while exhibiting no behavior whatsoever. Even if the PWM signals were wrong, I would expect the motor to at least stall.

Hi @Xarbenence , welcome to SimpleFOC forums :slight_smile:

I agree, this is very strange. Normally when the motor receives some current on its phases it moves, hums, jerks around, makes grinding noises or otherwise shows some signs of life…

Assuming you have set things up in a safe way (e.g. current limit on the PSU, or voltage levels and motor resistance such that the current can’t rise too high!) you can call driver.setPwm(a,b,c); where a, b and c are voltages. If you set different values here you can verify the PWM signals are as expected. If your voltage_limit is 10V, and you set 5V to a phase, you should get 50% duty cycle…

Do you have another motor with which to test? Or have you seen this motor move (for example via other software)? Might it be a problem of the motor being broken?

In terms of your code:

if the driver.voltage_power_supply is 8V, the driver.voltage_limit should be 8V or less. The limit can’t be higher than the PSU voltage.

if the driver.voltage_limit is 8V then the motor.voltage_limit should be 4V (or less).
The driver limit is absolute, while the motor limit acts on the Uq which can be positive or negative. So a 4V limit here gives the same range as the 8V driver limit.

driver.enable(); → please remove this. It gets enabled automatically when the motor is enabled.

motor.move(2); → this will always set the target to 2rad/s, this is probably not what you want given that you wrote code to set the target via the commander.
Either remove the 2 and just call motor.move(); with no parameter. Then it will start with a target of 0, and you can change it via the commander.
Or introduce a new variable, float target = 2; and call motor.move(target);. Then adjust the commander code to change the value of target rather than motor.target.

But actually none of these problems really explains why your motor isn’t moving at all :slightly_frowning_face:

1 Like

Well the motor has to do something if it’s not borked and the voltage and current are there. Check the motor with an ohmeter, then connect things and chec the voltages while it’s actually connected, I guess. Sorry no quick solution, just a proceedure. BTW I have a ton of old motors if you want any, like 30 of them, they are not quite the same but pretty nice.

Hi @Runger, you said something really interesting that I wasn’t aware of. This is a screenshot of the datasheet from the gimbal motor I’m using:


You said if my drive.voltage_limit is 8V, then my motor.voltage_limit should be 4 V or less. Since the data sheet gives a rated voltage of 7.4 V DC. Does that mean I should limit the motor voltage to ± 3.7 V? Or should I instead by supplying twice the voltage to the driver (~14 V). I’m a bit confused about what the Uq is that you’re referring to.

Here is an image of what I saw when I observed one of the three phase wires connected to my motor with my oscilloscope.


As you can see, the phase is either +7.4 V or 0. Would this be a reason that the motor isn’t spinning? Does it need to be ± 3.7 V? Thanks so much for your response!

No, that waveform is fine. The driver’s output is a square wave PWM signal at several kHz frequency.
In your picture the PWM duty cycle looks to be around 50%.

But the motor is an inductive load which can’t follow the voltage changes at this frequency. It acts as a filter that smooths the PWM into an average voltage. So for 50% duty cycle PWM 0-7.4V the motor would see this signal as 3.7V.

You could. But the Datasheet also says operating range is 6-8V, so the 8V/4V limit seems fine to me. Changing it by 0.6V/0.3V won’t make much difference…

No definitely not! The 8V driver limit is the right one to use.

For some infos on what is Uq and how FOC works please take a look at our docs, in the „Theory Corner“, and the section on the motion control modes…

The motor voltages are not very useful without actual working commutation… just think in terms of the restistance, inductance, heat dissipation limits and current. The motor is a bunch of electromagnets, the voltage is not actually a limit, they just tell you that to give you an idea of what the voltage should be when the whole thing is driving a load at a reasonable speed and torque with working commutation. 4 volts can easily burn out a motor if it’s open loop an not moving. I set my gimbal motor to 1 volt. Also using a current limited power supply has saved me more than once probably.

I too am seeing this issue for a very similar setup, and I have a clue, just not sure how to fix it.

Setup: Teensy 4.0, TMC6300, Similar motor to the above.
(Connecting the same pins in the code above)

When “running” the motor doesn’t turn, but I feel resistance if I turn it manually while it is on.

All the signals look correct, but they do not change. They are fixed at 50% duty cycle. Inverted and non-inverted look fine.

I tried running driver.setPwm(3,6,5);
The duty cycles stayed at 50% (average voltage didn’t change for the channels)

So maybe there’s an issue with setPWM for Teensy that has come up?

@andyg, Very interesting indeed.

I was wondering if my motors were the issue, since I was getting nothing out of them. Just now, I accidentally plugged one of the phase wires into the SEN pin of my driver (the current sense pin). It was really interesting, because the motor locked up. It’s not spinning, but it’s snapping to positions when I try to rotate it manually (snapping to the motor poles, I presume). Ironically, no movement/resistance when I have the 3 phase wires connected to the actual motor driver outputs. I connected all three phase wires up on a scope, and here is what is coming out of of them:


Voltage level and 50% duty cycle looks good on all three lines. Since I know that the motor is functional, is there any reason you could think of that it wouldn’t respond to an actual PWM signal?

As a follow up: I decided to hook up one motor phase line to the current sense pin while also observing the other two lines with the regular PWM.


Turns out, the current sense pin is putting out a 100 mV PWM at 50% duty cycle, in phase with the other two lines. I don’t understand why connecting one of the motor wires to that small voltage PWM is resulting in some behavior, but connecting it to the correct voltage PWM in the above image doesn’t yield anything.

Quick little side note: I left the motor connected to the two regular PWM lines and the current sense line when writing the above post. After publishing, I picked up the motor, and it was warm. I think it was just sitting at it’s stall torque. No damage, it wasn’t too hot to pickup, and I disconnected it immediately, but I thought it was interesting enough to note.

Xarbenence
Glad you didn’t cause any damage-
Ok- got this working. But I switched to an ESP32 (Wemos D1 Mini), and for open loop velocity used these pins:
BLDCDriver6PWM driver = BLDCDriver6PWM(25,27, 4,32, 2,17, 16);

When I looked at it on the scope I saw the accordion like pwm signals changing corresponding to the “average voltage” sine waves they are creating for the 3 channels. With the Teensy I was just seeing unchanging PWM signals, so perhaps I was doing something wrong there. Or, there might be a software issue with the pwm Teensy implementation. If you’re seeing square waves that aren’t changing and you’re running the open loop velocity code (and the wires are hooked up right…). PWM is not changing as it should.

Hey guys,

Are you using the last library version, v2.3.0?

There seem to be several issues with teensy and 6pwm lately, maybe its a low level firmware change as well, we’ll have to investigate that.

Yes, I’m on v2.3.0, thanks for looking into this!

Hello!

So, I decided to try and use a Raspberry Pi Pico, since I had one on hand. When I watch the PWM lines going into the motor, they all still appear to be in phase. When I’m commanding a velocity, shouldn’t the three PWM lines be out of phase?

I will say: when I start commanding a velocity of around 200 rad/sec via the serial prompt, I can hear the motor start giving a quiet whine. It’s not rotating, but when I pick it up I can feel a slight vibration. Is this perhaps due to the motor receiving the incorrect PWM signals?

Thanks for all your guys’ help.

~Alex

I can’t say what’s up on the Teensy, but as Antun says it seems the PWM output is not correct.

On the RPi Pico it should be working. If you are using 3-PWM, the signals should be all in phase, but should have different duty cycles as you change the motor position / velocity.
In 6-PWM, there should be 3 pairs of signals, where each pair is complementary (out of phase) but with (almost) the same duty cycle.

Are y’all using PlatformIO or ArduinoIDE?

1 Like

RBpi for the win. Too slow for my application, but otherwise I think it’s the way to go.

I’m using the Arduino IDE, though I suppose I could try on PlatformIO.

@runger, I have this relatively new driver from sparkfun .
Referring to this Pico Pinout:


I’m wiring PWM_A[0] to UH, PWM_B[0] to UL,
PWM_A[1] to VH, PWM_B[1] to VL, and PWM_A[7] to WH, PWM_B[7] to WL.

Those are how I have the 3 signal pairs going into the motor driver, and when I was sending pictures of the driver outputs (U,V,W), I saw that the PWMs signals getting sent to the motor by the driver were all in phase. Does my wiring sound correct?