I am just starting to get to know SimpleFOC, so please excuse my possibly dumb questions. I have a GBM2804H with encoder ( IFlight IPower GBM2804H-100T / GM2804 Brushless Gimbal Motor with AS5048A Encoder/Aluminum Case for Camera Stabilizing Systems - AliExpress 26 ) to use with the SimpleFOCMini board. My general goal is to build a small machine that adds impulses to a spring mechanism to create an endless bouncing swing (hard to explain as a non-native English speaker). There is a spring attached to the ceiling, with a ~4 kg weight hanging from it. The idea is to have an algorithm that learns the amplitude and frequency, and then uses a pulley (connected via a wire to the bottom of the spring) to pull the spring whenever it contracts (it will be around ~10cm amplitude with around 1-2Hz).
Here are my questions that I cannot really figure out:
In the SimpleFOCMini documentation, it says I should not use motors with less than 10 Ohm resistance. The one I am using (because I had it from another project) has 5–6 Ohms. What can I expect—what is going to happen? Is there a risk of damaging the driver or motor?
I want to use a 12 V power supply. How much voltage can I safely use to make the motor pull the spring? How do I know what voltage is safe to use? What is a safe voltage to start with?
How much torque can I expect from a motor like this? Is there any way to calculate it more or less accurately?
maybe someone has a general thought about this project and can tell me that i am completely on the wrong track with BLDC + FOC. (since my first idea was to use stepper motors, but i did find them to be too slow, because they have to at least match the speed of the contracting spring.
Thank you for your help!
PS.: i have added the best drawing in the history of the world for better understanding:
That’s plenty of resistance. Even in the worst case it will take a while to burn anything.
Best to find it by experimentation. Use open loop mode and gradually increase motor.voltage_limit until the motor and/or driver gets hot. And it’s confusing because the motor voltage gets multiplied by a sine wave which ranges -1 to +1, so 6V motor limit actually uses the full 12V supply range Field Oriented Control | Arduino-FOC
From my measurements, most small BLDC motors can handle about 1Nm/kg continuously without getting uncomfortably hot to touch. That motor is 51 grams, but a lot of it is the position sensor, so I’d estimate around 30mNm. But you can use at least twice that much for a few seconds without anything bad happening, which should be fine for your application periodically tugging on a string. It doesn’t list the kv, so I’m not sure what current will give that torque. Maybe 1-2 amps?
Hopefully 12V will be enough to get the acceleration you need from that motor. If not, you’ll have to go up to 24V supply. Greater possibility of burning, but still unlikely as long as you’re reasonably cautious.
I think i got a little bit further but struggle now on one issue:
enabling / disabling the motor makes a little klick sound (the high pich click sound comes from the motor, the other noises are from spring etc, and will be eleiminated with a more sophisticated mechanic.. its still in a very early testing phase ):
is there any way to make the power on/off a little bit smoother so that the clicking gets less (or disappears all the way)?
here is the pseudo-code how the thing works:
setup:
init serial, encoder, driver, motor (velocity mode, PID), feste FOC-Parameter
print Status
loop:
motor.loopFOC()
vel = motor.shaftVelocity()
angle = motor.shaftAngle()
if !hasZero: displacement0 = angle_to_meters(angle)
disp = angle_to_meters(angle) - displacement0
crossedTop = lastVel > 0 && vel <= 0
if crossedTop:
peak = disp
error = targetAmp - |peak|
if |error| <= deadband: keep boostScale
else if error > 0: boostScale = base + kp_up*error
else: boostScale = 0
clamp(boostScale, minScale, maxScale)
lastVel = vel
if !driveEnabled && vel > onThreshold: motor.enable(); driveEnabled = true
else if driveEnabled && vel < offThreshold: motor.disable(); driveEnabled = false
if driveEnabled:
boost = boostScale * (bias + gain*|vel|)
target = directionSign * (vel + boost)
clamp target to [minTarget, maxTarget] with sign preserved
motor.target = target
motor.move()
else:
motor.target = 0 // freewheel
every MONITORING_INTERVAL: print t, vel, target, disp, lastPeak, boostScale