Camera high-speed slider design

Hi I have a slightly different project in mind than many of the applications here (quick search didn’t throw up anything similar but if you know of something, please link it). I would like to make a rapidly accelerating (m/s^2 tbc) camera slider which can reach 5 m/s along a rail for a short distance, before braking/slowing at the other end. Example would be accelerate from standstill to 5m/s over 1 metre, maintain 5 m/s over 3 metres, decelerate to standstill over 1 metre. I expect to use something like:

  • ESP32 for SimpleFOC and control
  • Vslot, v-wheels/carriage and GT2 timing belt for the motion. Belt would be tensioned at either end of the rail, wrapped round the drive pulley, the drive motor and battery would be mounted on the carriage. V-slot bolted together in sections to make approx 5m long rail.
  • 5010 360 KV cheap BLDC motor.
  • Driver circuitry tbc - recommendations sought

I estimate the mass of the whole carriage assembly will be 500g unloaded (including motor, electronics and battery) and 1kg with camera mounted.

My questions are:

  • Is an approximately trapezoidal velocity profile reasonably easy to implement in SimpleFOC (velocity mode :man_shrugging: )?
  • I see a function to query current velocity - is there a way to call-back when target velocity is reached instead of having to poll outside the library?
  • Does my plan sound mad? Or possible but I need to drastically reconsider my anticipated hardware?
  • Are there immediate candidates for driver circuitry I should consider or do I need to go away and calculate torque and current profiles first?

Thanks for reading and responding.

We don’t have any callback functions when reaching targets. Or trapezoid planner, but there have been some past threads discussing it, so you can search around the forum for them. My first thought is to implement it using angle mode. Each frame, calculate where the camera should be if it were accelerating on the ideal profile, calculate motor angle for that position, and set that as the target.

Let’s do some calculations to test feasibility…
5m/s over 1m means average speed 2.5m/s over 1m, or 0.4 seconds acceleration time.
5m/s / 0.4s = 12.5N.
Let’s try 0.15Nm, which should be pretty easy for that motor.
0.15Nmx360kv/8.3=6.5A.
0.15Nm/12.5N=0.012m = 24mm diameter pulley.
5m/s / 0.012m = 417rad/s = 3978rpm.
3978rpm / 360kv = 11V.
All reasonable numbers. However there is also rotor inertia to consider…
5010 rotors are usually about 30g, so at about 24mm radius, accelerating to 417rad/s in 0.4 seconds should take an additional 0.030x0.024x417=0.3Nm of torque.
Not good! More torque used on the motor than the load. I think you’ll need a more long and skinny motor.
EDIT: Nevermind, it’s fine. I messed up the calculation, see my other post.

1 Like

Wow, you really seem to know your math! I wouldn’t know where to start.

But there is an even bigger issue with the v-rollers. They’d need a few of them and although they run relatively smooth, they need a certain tightness to run without play.

You can get a lot of hints by looking up the units Newton, Newton-meter, Joule, and Watt on wikipedia and looking at the equivalent conversions to other units :slight_smile:

But I messed up that final calculation, which I probably wouldn’t have if I’d written the units. First of all I forgot the seconds. That would make it 0.030kg x 0.024m x 417rad/s / 0.4s = 0.75kgm/s². But that’s the dimensions of a Newton, so to get torque, we must need radius squared (which makes sense, considering that it’s an acceleration). So the correct answer is 0.018Nm, no problem at all! The 5010 360kv motor driven by B-G431B-ESC1 should be plenty strong enough for this project. But the ESC1 is sensitive to overvoltage, so you’ll need to add a braking resistor circuit to burn off the deceleration energy. Here’s a good old thread on the topic Protect power supply against BEMF - #47 by Grizzly

It’s true that the V rollers will add some friction, but since rotor inertia is the much smaller component of torque, the pulley size can be reduced to get more power out of the motor.

P.S. Another nice mental trick when dealing with torque is to imagine 1Nm is a 1N force on the end of a 1m long stick. Picture that making one revolution, it sweeps out quite a large circle, 2pi meters. Especially helpful for calculations involving leadscrews, to understand where the huge force comes from when you reduce that 6.28m of circular motion to a few mm of linear motion.

1 Like

Great - thank you for such a helpful answer @dekutree64!
I looked at the available pulleys and either 36 or 40 tooth should fit my needs. I will have to work out a motor coupler and shaft support, given the radial forces we will be generating.

Thanks too for the recommendation of the B-G431B-ESC1. From the tag, that board can get hot so I will need to heat-sink it. It appears to support the AS5600 over I2C, will that encoder be sufficient for the angle mode approach (1kHz update limit, I2C speed etc)?

It seems that I won’t need ESP32 for anything if I go with this driver, other than if I want to wirelessly control it - is that how you understand it - all motor control would be in the STM32?

I did a similar project and may give you some hints, since your initial thoughts sounds familiar to me… :slight_smile: My dolly is around 4kg, including camera, batteries and transmitter - speed is limitted to 2m/s and acceleartion to 1.4m/s^2 - that’s the limit with my driver plus some margin.

  • I switched to small aluminium wheels (32mm diameter) on a 10mm-rubber wire for smooth operation
  • you will need a motion planner (I took the code from O-drive) and velocity feed forward
  • I also started with an ESP but switched to STM32G431 with current sense

Enjoy, it’s going to be lot of fun! :slight_smile:

Thomas

1 Like

Thanks @reufer that sounds pretty similar! Could you expand more on your wheels + rubber wire drive/motion parts? Is that solely for drive (capstan drive?) or is it the guide / rail too?

I will have to look into the motion planner and velocity feed-forward. What does that do which SimpleFOC doesn’t do (yet)?

The dolly runs on the rubber wire, it acts as the rails. I use it for TV productions, so smooth moves are more important than speed and the rubber has enough friction to drive the dolly.

With a motion planner you control the different phases of your move which gives you the possibility to synchronize your axes. In my setup I have five of them (pan, tilt, dolly, zoom & focus) and when moving from one preset to another I want to finish all axes at the same time. Feed forward, simply said, just drastically improves the dynamic behaviour of your control loop.

Thanks @reufer. It’s good to hear that there’s a similar successful project out there.

Yes, quite easy :slight_smile:

See: Arduino-FOC-drivers/src/utilities/trapezoids at master · simplefoc/Arduino-FOC-drivers · GitHub

There is also a forum thread with links to more advanced code, search for “trapezoidal” in this forum…

Ah, excellent - thank you @runger! I guess, not having followed the links yet, that this would deal with my relatively simple motion planning requirement (single motor ramp up velocity, hold velocity, reduce velocity). I don’t really care about the shape of the ramp up/down, as long as I get constant velocity once up to speed, until I decelerate.

I think it would definitely be a good starting point. The code is quite “forgiving” as it only uses the distance (sensor value) and so isn’t too sensitive to poorly tuned setups etc.

You may want to go to something more advanced and specific to your use case later, but I’m a fan of starting simple, if it works well enough then problem solved and move on to the next one :slight_smile:

1 Like

@runger thank you for your trapezoidal code.

EDIT: I found the culprit - I had forgotten to link the motor to the planner:

  trapezoidal.linkMotor(motor);

Read on if you want to see the rest of the code. I think I definitely have enough of a proof of concept to order the driver boards.


I tried it today but have had some issues. I would be very grateful if you could help me work out what is going on.

First, a little bit about my setup. I’m using what I have on-hand, so the setup isn’t ideal. I’ve got the 5010 motor hooked up with an AS5600 connected to a SimpleFOC Mini driver board, all controlled with an ESP32. I do have to carefully set the power supply voltage to the SimpleFOC as I realise the phase resistance on that motor is probably too low and it does trip if I set it a bit high.

I have used example velocity mode successfully from the SimpleFOC library. But I’m having trouble when I add the trapezoid parts. I know the code example in the repo is incomplete so I have done my best to merge / construct a full application:

/**
   ESP32 position motion control with magnetic sensor and trapezoidal profile
*/
#include <SimpleFOC.h>
#include <SimpleFOCDrivers.h>
#include <utilities\trapezoids\TrapezoidalPlanner.h>

// I2C Magnetic sensor instance (AS5600)
// make sure to use the pull-ups and connect DIR pin to GND or VCC!!
// SDA 21
// SCL 22
// magnetic sensor instance - I2C
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

// instantiate the commander
Commander command = Commander(Serial);

// Motor instance with 12N 14P(7 pairs)
BLDCMotor motor = BLDCMotor(7);

TrapezoidalPlanner trapezoidal = TrapezoidalPlanner(5.0f, 1.0f, 0.25f, 0.2f);

BLDCDriver3PWM driver = BLDCDriver3PWM(25, 26, 27, 14);

// angle set point variable
float target_angle = 0.0f;

void onTarget(char* cmd) {
  command.scalar(&target_angle, cmd);
  trapezoidal.setTarget(target_angle);
}

void setup()
{
  // use monitoring with serial
  Serial.begin(115200);
  // enable more verbose output for debugging
  // comment out if not needed
  SimpleFOCDebug::enable(&Serial);

  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);
  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);
  // choose FOC modulation (optional)
  //motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  // set motion control loop to be used
  motor.controller = MotionControlType::velocity;
  // contoller configuration
  // default parameters in defaults.h
  // velocity PI controller parameters
  motor.PID_velocity.P = 0.2f;
  motor.PID_velocity.I = 20;
  motor.PID_velocity.D = 0;
  // maximal voltage to be set to the motor
  motor.voltage_limit = 6;
  // jerk control using voltage voltage ramp
  // default value is 300 volts per sec  ~ 0.3V per millisecond
  motor.PID_velocity.output_ramp = 1000;
  // velocity low pass filtering time constant
  // the lower the less filtered
  motor.LPF_velocity.Tf = 0.01f;

  // comment out if not needed
  motor.useMonitoring(Serial);
  // initialize motor
  motor.init();
  // align sensor and start FOC
  motor.initFOC();

  command.add('T', onTarget, "target angle");
 //while(1){} // block
 trapezoidal.setTarget(target_angle);
 // _delay(1000);
 //while(1){} // block
}

int32_t downsample = 50;    // depending on your MCU's speed, you might want a value between 5 and 50...
int32_t downsample_cnt = 0;

void loop() {
  if (downsample > 0 && --downsample_cnt <= 0) {
    motor.target = trapezoidal.run();
    downsample_cnt = downsample;
  }
  motor.move();
  motor.loopFOC();
  command.run();
}

When the code runs trapezoidal.setTarget(target_angle) the ESP32 resets repeatedly. I had a compilation failure with the exact line
void onTarget(char* cmd){ command.scalar(&target_angle); trapezoidal.setTarget(target_angle); }
so I changed this to
void onTarget(char* cmd){ command.scalar(&target_angle,cmd); trapezoidal.setTarget(target_angle); }

I realise this could be the cause of the issue but I can’t seem to compile without changing command.scalar(&target_angle).

Any ideas would be gratefully received.

1 Like

Hi,

As per my knowledge, SimpleFOC doesn’t provide a direct callback mechanism when a target velocity is reached. However, you can implement a simple check within your loop to monitor the current velocity and trigger actions when the target velocity is achieved.

Thanks

1 Like