I’m thinking of building a sort of exercise machine to see if this works https://onlinelibrary.wiley.com/doi/abs/10.1111/sms.14220. An exercise machine that can provide constant torque when needed for an eccentric movement, then moved back to the starting position with no effort.
Basically, I need a motor that when powered on will exert a constant torque at stall speed, then maintain that same torque while slowly pulling and winding a rope (and the user resisting the force and slowly moving along). Turn it off, move the handle in the starting position again, re-engage the motor to repeat the same movement as above. The amount of torque will depend on the gearing of the machine and various levers, still all TBD.
I started looking at SimpleFOC as a solution and tried with a few of the brushless motors I have, but none seems to be the right type of motor. The lowest kV motor I have is a 360kV one, and it’s clear that it will not work: torque at close to stall speeds is a fraction of the motor potential, not to mention quick overheating (ok, it’s a drone motor, so that might improve with a fan, which is an option). I will probably need a gimbal-like motor, but those get expensive quickly. I also have bought a used hoverboard and plan to test its motor next.
I started wondering if, though, a stepper motor might be better for my use. Stepper motors have the highest torque at stall speeds, and even NEMA34 motors with lots of torque can be had for not much more than $50-$75.
Asking the experts here: what are the best options to experiment with? I can definitely look at using a gearbox, but low/stall speeds will still be required.
I was going to suggest a hoverboard motor Though the built-in hall sensors are not ideal, as they will move in 4 degree steps. But most likely it would be possible to replace them with linear halls and transform the three signals into a more precise angle. That’s on my to-do list, but I probably won’t get to it for a few months at least. If you want to try it, I’ll mail you some 49E sensors. I bought a 100 pack a while back because it was about the same price as 10, so I have more than I’ll ever need.
If the signals they produce are sinusoidal, I think you could use Clarke+Park transform to get the angle. But most likely there will be a lot of saturation due to the close proximity to the magnets, so it will need a little more work. Possibly just throwing out the most saturated one and using a + b + c = 0 to calculate its value from the other two.
Stepper could certainly work too. Good use for Juan-Antonio’s new driver
I’ve done this. Use a hoverboard motor. Or a large AC servo motor. Industrial AC servos are designed to minimize cogging torque. Make sure to use an encoder as opposed to halls. Also, you will regenerate significant energy when you rotate against a torque, so make sure you use a battery, or have a circuit to shunt the current on the DC bus and prevent the voltage from rising.
You can use SimpleFOC to control the torque as a function of angular position, etc.
Thanks for the info and the offer to send hall sensors. Given the low velocity I was actually thinking of using an encoder (optical or magnetic). Would using 3 hall sensors inside the motor be better? I mean, obviously more compact and easier from a mechanical point of view, but I’m asking from a control point of view. In my still limited understanding, an encoder should provide the best possible control loop especially for near-stall speeds.
And, yes, I have been keeping an eye on the Field Stack driver, really cool.
In my case, when the motor is providing torque, the movement is always driven by the motor rotation direction, so there should be no regen. The idea of the machine is to use the muscles in “eccentric mode”, i.e. the muscle resists movement and slowly gives, like when you lower slowly a weight after having lifted it.
The return phase, I was thinking of setting the driver output in high-z mode, and basically disconnecting the motor from the power source. A freely rotating brushless motor should not generate significant energy, or am I wrong?
Unless I looked at the wrong products, AC servo motors seem to be rather expensive (compared to steppers or hoverboard motors) due to the extra driver circuit. Do you have any to suggest looking at?
Hoverboard motor with metal housing and drill holes on both sides for air cooling, add a large computer 12v cooling fan for forced convection. Remove the rubber tire and you got exactly what you need. The built-in halls are more than enough for what you need. You can get this whole thing for may be less that $50. I’ve done something very similar for a different project.
A much bigger question is will your motor driver support this motor.
Gotcha. If you’re just controlling the eccentric then you’ll be fine as power will be going into the motor. Yep, AC servo motors are expensive…you can usually find them pretty cheap on eBay though. The nice thing about them is they have near zero cogging…
Overall, going the hoverboard route will work, as the pole count is pretty high and cogging torque is not that much. +1 to @Valentine s comment on cooling. You’ll definitely want to use an encoder. Something around 1000 CPR should work well.
I have a DRV8302 Aliexpress board (same as DRV8302 example | Arduino-FOC). That is supposed to be 45V, 15A, and should be enough for a 36V, 10A motor, possibly with extra cooling.
I’m assuming I will have to use torque control and monitor the current… is that correct? Actually, any pointer on what to look out for would help. I never tried to drive a motor at constant torque near stall velocity and I’m still a bit confused on how it will work
BEWARE📢
Up to this moment (version 1.4.1 ) the library doesn’t implement the current control loop. The motor torque is controlled via voltage directly.
I think I saw current control (low side) working for that board. It requires a fast MCU with low side current sensing, but I plan to use a Nucleo G474, with should be plenty fast (worst case, I also have a Nucleo H741, which is a beast ). Is that warning simply an old leftover in the docs, or would the DRV8302 be a bad board for what I have in mind?
For what you need you only implement voltage position control. It’s a really simple use case. Forget about current , etc. The torque is estimated with voltage, start the motor, set the position, lock it and done.
Then when you start pilling the rope to unwind it, the motor will keep constant torque by trying to bring the motor to zero. Control the torque by changing the phase voltage.
There was a guy he did something exactly the same but with a smaller motor for performing some magic tricks, that was last year. If I got the time I may find the posts. I ended up designing a tiny driver for him because the magic required something really small.
You’re right and an encoder or magnetic sensor (SPI-based) would be far better for low speed / holding position type applications than the hall sensors…
Encoder is better, go with that. It’s just mechanically more difficult to set up, but on second thought it probably won’t be too bad in a stationary exercise machine compared to most robotics stuff that I’m used to.
I would say that you may be able to use voltage mode to control torque, but by doing do, you implicitly couple motor torque and speed, and that may not be what you want. If you use true current control, the motor torque becomes independent of speed, which may be better for your application. As @Valentine said, you could control the voltage based on position to overcome this coupling of torque and speed, but if you use current control, then you don’t need to go through that effort.
In my setup, I used a DRV8302 board from AliExpress with a hoverboard motor and used full current control, all run by a Nucleo F401RE. It worked well for me, and I did exactly the same thing you’re trying to do here.
Terrific, thanks! Would you consider sharing your code? (or a generic framework I could use as a starting point, if you don’t want to share everything?)
In my initial G431B-ESC experiments I had quite a lot of problems figuring out parameters to avoid excessive currents and avoid problems. And I’m a bit scared by how powerful the hoverboard motor is Your setup is basically identical to what I plan to use
@robca I’ve also been able to use the same technique with the B-G431 board - we can message about that if you want. I think I have a decent understanding how to get it working with current control and an I2C or incremental encoder.
Below is the code I used with my large AC servo motor and the DRV8302 board, along with a Nucleo F401RE board. I use PlatformIO for development. This is just to get you started - you can play around with the logic to get the control you want. I like setting the torque as a function of rotor angle…
#include <Arduino.h>
#include <SimpleFOC.h>
// DRV8302 pins connections
#define INH_A PA8
#define INH_B PA9
#define INH_C PA10
#define EN_GATE PC4
#define M_PWM PB4
#define M_OC PB3
#define OC_ADJ PB13
#define OC_GAIN PB5
#define IOUTA A0
#define IOUTB A1
#define IOUTC A2
#define button PC13
// Motor instance
BLDCMotor motor = BLDCMotor(21);
BLDCDriver3PWM driver = BLDCDriver3PWM(INH_A, INH_B, INH_C, EN_GATE);
// DRV8302 board has 0.005Ohm shunt resistors and the gain of 12.22 V/V
LowsideCurrentSense cs = LowsideCurrentSense(0.005f, 12.22f, IOUTA, IOUTB, IOUTC);
// encoder instance
MagneticSensorSPI encoder = MagneticSensorSPI(AS5048_SPI, 14);
// commander interface
Commander command = Commander(Serial);
void onMotor(char* cmd){ command.motor(&motor, cmd); }
void setup() {
pinMode(button, INPUT_PULLUP);
// initialize encoder sensor hardware
encoder.init();
// link the motor to the sensor
motor.linkSensor(&encoder);
// DRV8302 specific code
// M_OC - enable overcurrent protection
pinMode(M_OC,OUTPUT);
digitalWrite(M_OC,LOW);
// M_PWM - enable 3pwm mode
pinMode(M_PWM,OUTPUT);
digitalWrite(M_PWM,HIGH);
// OD_ADJ - set the maximum overcurrent limit possible
// Better option would be to use voltage divisor to set exact value
pinMode(OC_ADJ,OUTPUT);
digitalWrite(OC_ADJ,HIGH);
pinMode(OC_GAIN,OUTPUT);
digitalWrite(OC_GAIN,LOW);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12.0;
driver.pwm_frequency = 20000; // suggested under 18khz
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// link current sense and the driver
cs.linkDriver(&driver);
// align voltage
motor.voltage_sensor_align = 0.9;
// control loop type and torque mode
motor.torque_controller = TorqueControlType::foc_current;
motor.controller = MotionControlType::torque;
motor.motion_downsample = 3.0;
// velocity loop PID
motor.PID_velocity.P = 0.4;
motor.PID_velocity.I = 6.0;
motor.LPF_velocity.Tf = 0.009;
// angle loop PID
motor.P_angle.P = 20.0;
motor.LPF_angle.Tf = 0.005;
// current q loop PID
motor.PID_current_q.P = 2.0;
motor.PID_current_q.I = 200.0;
motor.LPF_current_q.Tf = 0.004;
// current d loop PID
motor.PID_current_d.P = 2.0;
motor.PID_current_d.I = 200.0;
motor.LPF_current_d.Tf = 0.004;
// Limits
motor.velocity_limit = 2.0;
motor.voltage_limit = 7.0;
motor.current_limit = 1.5;
// use monitoring with serial for motor init
// monitoring port
Serial.begin(115200);
motor.useMonitoring(Serial);
motor.monitor_variables = _MON_CURR_Q | _MON_CURR_D; // monitor the two currents d and q
motor.monitor_downsample = 0;
// initialise motor
motor.init();
cs.init();
cs.skip_align = true;
// driver 8302 has inverted gains on all channels
cs.gain_a *= -1;
cs.gain_b *= -1;
cs.gain_c *= -1;
motor.linkCurrentSense(&cs);
// align encoder and start FOC
motor.initFOC();
// set the inital target value
motor.target = 0.0;
// define the motor id
command.add('M', onMotor, "motor");
_delay(1000);
}
void loop() {
motor.loopFOC();
motor.move();
motor.monitor();
command.run();
}
I think you will need to use a large gearing ratio anyway, and thus the frequency of the cogging torque will be increased, in terms of cogs per revolution. I doubt you need a low cogging motor for this. I have investigated low cogging motors and was able to get some but they are not common. The Surface mount type motors( SMPMSM, surface magnet permanent magnet synchronous machine) tend to be considerably lower cogging than IP (internal plate) plate type motors, that was enough for my purposes. Gimbal motors tend to be good as they are supposed to be controlling a camera, but not all of them, and sounds like you would need a pretty big one.
Just one question: I was under the impression that 6pwm gives more control than 3pwm. Do you have a specific reason to use 3pwm? Actually, I’m not entirely sure if loopFOC really does anything different with 6pwm compared to 3pwm… maybe 6pwm only adds value if I implement my control logic using the driver directly without loopFOC?
Possibly, yes. But since I plan to use a rope to connect to the handle, I also can use the diameter of the shaft as a sort of gearing ratio. A very small shaft wrapping a rope needs many turns to move the handle a small amount. I might even actually use a couple of pulleys if I only need an additional 2:1 ratio. That would be cheaper and simpler than finding the right motor with the right gearbox. A rope also reduces the cogging effect somewhat.
Glad to help! I’m not an expert on motor control, but I think using 6 PWM gives you the ability to independently control the high and low side FETs, instead of relying on the driver chip to do so automatically. This could allow you to alter the deadtime value between FET transitions, or control only the low side ones to do things like active regeneration (instead of passive regen with the FET body diodes). I’m not sure how the loopFOC() function acts when using 6 PWM, outside of being able to control deadtime based on a user supplied value.
FWIW, 3 PWM worked well in my application which was nearly the same as yours.
Re: gearing - I dont think you’ll need it if you use a hoverboard motor and a pulley attached with the proper diameter to get the torque/speed you require.