Step dir interface issue

hello everyone

I am a novice and do not understand code or hardware. The code was shared with me by someone else. Here, I would like to ask a question. I want to use BLDC for my 3D printer, with the interface being step dir. I can control it to rotate forward or backward, but its operating speed is too slow. When I adjust the PID smoothly, its speed is only 3-5 cycles per second. May I make it spin faster?

thank you!

#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(14);
BLDCDriver3PWM driver = BLDCDriver3PWM(32,33,25,22);

// encoder instance
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
TwoWire I2Cone = TwoWire(0);

// StepDirListener( step_pin, dir_pin, counter_to_value)
StepDirListener step_dir = StepDirListener(13, 15, 360.0/200.0); // receive the angle in degrees
void onStep() { step_dir.handle(); }

// inline current sensor instance
// check if your board has R010 (0.01 ohm resistor) or R006 (0.006 mOhm resistor)
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, 39, 36);

float target_velocity = 0;
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }

void setup() {
step_dir.init();
// enable interrupts
step_dir.enableInterrupt(onStep);
//step_dir.attach(&motor.target);
I2Cone.begin(19,18, 400000UL);
sensor.init(&I2Cone);
motor.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link driver
motor.linkDriver(&driver);

// TorqueControlType::foc_current
// TorqueControlType::voltage TorqueControlType::dc_current
motor.torque_controller = TorqueControlType::foc_current;
// set control loop type to be used
motor.controller = MotionControlType::angle;

// contoller configuration based on the controll type
motor.PID_velocity.P = 0.045;
motor.PID_velocity.I = 0;
motor.PID_velocity.D = 0;
// default voltage_power_supply
motor.voltage_limit = 12;
motor.current_limit = 2;
// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01;

// angle loop controller
motor.P_angle.P = 20;
// angle loop velocity limit
motor.velocity_limit = 20;

// use monitoring with serial for motor init
// monitoring port
Serial.begin(115200);

// current sense init and linking
current_sense.init();
current_sense.gain_b *= -1;
motor.linkCurrentSense(&current_sense);

// initialise motor
motor.init();
// align encoder and start FOC
motor.initFOC();
command.add(‘T’, doTarget, “target velocity”);

// set the inital target value
motor.target = 0;

_delay(1000);
}

void loop() {
Serial.println(step_dir.getValue());
// iterative setting FOC phase voltage
motor.loopFOC();

// iterative function setting the outter loop target
//motor.move(target_velocity);
motor.move(step_dir.getValue()*3.14/180);
//command.run();
}

Are you sure the motor has 28 magnets? The polepair number is #magnets/2

Always use motor.voltage_limit = 0.5* driver.voltage_power_supply

Not sure if that solves your problem, but it’s the right starting point

Dear @tony , welcome to SimpleFOC!

In addition to @o_lampe ‘s comments I would say you can’t print on each loop iteration… this will flood the serial port and cause blocking, slowing down your loop. But this loop has to execute as fast as possible so you can only print every 1000 iterations or so.

I have corrected my mistake, thank you very much for the answer from oulampe

1 Like

Hi Runger, is this the code?
// downsampling
motor.monitor_downsample = 100; // default 10
After adding this code, there was no improvement

No. I guess what @runger meant was adding a loopcounter variable:

[pseudo code]
void loop()
   if loopcounter >1000
      serial.println.......
     loopcounter = 0
  endif
...
...
...
loopcounter +=1

Hi o_lampe, thank you for your help. My motor is now running at high speed. Now it is 360/200=1.8 °/S. How can I set MICROSTEPS if I want to achieve higher accuracy?

You can change this declaration to
StepDirListener step_dir = StepDirListener(13, 15, 360.0/(200.0 * 16.0));
if you want 16 times microstepping. You also have to set the same value in the 3D printer config-file.
I wouldn’t recommend going too high with microstepping; the AS5600 doesn’t have such a high resolution. Maybe try 4 or 8 times microstepping first and see, if it makes a difference.

Thank you for this great open source project. I am still working hard to learn and I want to configure dual motors. I have almost copied a copy of the code. M0 motor can move, M1 motor only self checked and did not rotate. Did I do something wrong?

#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(32,33,25,22);
BLDCMotor motor1 = BLDCMotor(7);
BLDCDriver3PWM driver1 = BLDCDriver3PWM(26,27,14,12);

// encoder instance
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
MagneticSensorI2C sensor1 = MagneticSensorI2C(AS5600_I2C);
TwoWire I2Cone = TwoWire(0);
TwoWire I2Ctwo = TwoWire(1);

// StepDirListener( step_pin, dir_pin, counter_to_value)
StepDirListener step_dir = StepDirListener(13, 15, 360.0/(200.0 * 8.0)); // receive the angle in degrees
StepDirListener step_dir1 = StepDirListener(16, 17, 360.0/(200.0 * 8.0));
void onStep() { step_dir.handle(); }

// inline current sensor instance
// check if your board has R010 (0.01 ohm resistor) or R006 (0.006 mOhm resistor)
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, 39, 36);
InlineCurrentSense current_sense1 = InlineCurrentSense(0.01, 50.0, 35, 34);
float target_velocity = 0;
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }

void setup() {
step_dir.init();
step_dir1.init();

// enable interrupts
step_dir.enableInterrupt(onStep);
step_dir1.enableInterrupt(onStep);

//step_dir.attach(&motor.target);
I2Cone.begin(19,18, 400000UL);
I2Ctwo.begin(23,5, 400000UL);
sensor.init(&I2Cone);
sensor1.init(&I2Ctwo);
motor.linkSensor(&sensor);
motor1.linkSensor(&sensor);

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
driver1.voltage_power_supply = 12;
driver1.init();

// link driver
motor.linkDriver(&driver);
motor1.linkDriver(&driver1);

// TorqueControlType::foc_current
// TorqueControlType::voltage TorqueControlType::dc_current
motor.torque_controller = TorqueControlType::foc_current;
motor1.torque_controller = TorqueControlType::foc_current;
// set control loop type to be used
motor.controller = MotionControlType::angle;
motor1.controller = MotionControlType::angle;

// contoller configuration based on the controll type
motor.PID_velocity.P = 0.05;
motor1.PID_velocity.P = 0.05;
motor.PID_velocity.I = 0;
motor1.PID_velocity.I = 0;

// default voltage_power_supply
motor.voltage_limit = 0.5* driver.voltage_power_supply;
motor1.voltage_limit = 0.5* driver.voltage_power_supply;
motor.current_limit = 5;
motor1.current_limit = 5;

// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01;
motor1.LPF_velocity.Tf = 0.01;

// angle loop controller
motor.P_angle.P = 20;
motor1.P_angle.P = 20;

// angle loop velocity limit
motor.velocity_limit = 200;
motor1.velocity_limit = 200;

// use monitoring with serial for motor init
// monitoring port
Serial.begin(115200);
motor.useMonitoring(Serial);
motor1.useMonitoring(Serial);

// current sense init and linking
current_sense.init();
current_sense.gain_b *= -1;
current_sense1.init();
current_sense1.gain_b *= -1;
motor.linkCurrentSense(&current_sense);
motor1.linkCurrentSense(&current_sense);

// initialise motor
motor.init();
motor1.init();

// align encoder and start FOC
motor.initFOC();
motor1.initFOC();
command.add(‘T’, doTarget, “target velocity”);

// set the inital target value
motor.target = 0;
motor1.target = 0;

_delay(1000);
}

void loop() {

// iterative setting FOC phase voltage
motor.loopFOC();
motor1.loopFOC();

// iterative function setting the outter loop target
//motor.move(target_velocity);
motor.move(step_dir.getValue()*3.14/180);
motor1.move(step_dir.getValue()*3.14/180);
//command.run();
}

Hi everyone!
Now everything is configured and the test runs smoothly, using SimpleFOC on the precision instruments of the observatory to replace the original stepper motor. The original stepper motor combined with the reduction gear rotates 360 ° in 10 minutes to track the movement of celestial bodies. After replacing SimpleFOC, BLDC rotates 360 ° in 12 seconds, but SimpleFOC fails to run at the speed of the stepper motor. The micro step setting is the same. Can anyone help me?

Hi @tony ,

It sounds like you are very close :slight_smile:

Are you still using the reduction gear?
And are you sending the step-Dir pulses at the same speed as with the old stepper?

At the moment you are turning to the position step_dir.getValue()*3.14/180 .
You can change these scaling factors to be anything you want. So if it is now 12 seconds and before it was 10 minutes, you need to slow it down 50x.
So change it to:
step_dir.getValue()*3.14/180.0/50.0

And then it will be 50x slower!

Let us know how it goes :slight_smile:

Hi, @ Runger
I’m glad you replied to me
The gear reduction ratio is 1:144
The old stepper sends the Step Dr pulse at the same speed as the old stepper. With a micro step setting of 8, the old stepper takes 640 steps per degree, but SimpleFOC does not follow this rule and instead rotates freely. Even when setting different micro steps, the motor speed is different, which exceeds my imagination. In principle, the speed will not change with the old stepper and SimpleFOC micro steps.
Tracking stars requires very precise rotational speed: 24 hours a day=86400 seconds/144=600 seconds, requiring the motor to rotate 360 ° accurately for 600 seconds.
I visually measured each lap for 12 seconds, which is unscientific, so I cannot simply give it a/50.0
The old stepper is actually a celestial tracking system that sends different pulse frequencies to track celestial bodies based on their speed.

Hey,

In terms of the maths if it’s not 50:1 then maybe it’s 47.88893:1 or 72.44412:1 - it doesn’t matter, you can use any value that you need to make it work.

You have 3 places to modify the setup:

  1. the gear-train - as a mechanical system, it is the most hard to change, so let’s assume it’s fixed at 144:1

  2. the controller - here you probably want to keep the device you already have, so you can play with the microstepping settings and other configuration parameters you may have available there. In the end the controller will produce a series of pulses for the step-dir according to those settings.

  3. your motor driver setup. This is the part you are changing. So here you should set up the motor control logic to convert between the controller output (step dir signal) to the motor rotation. You can do it any way you want. I think angle mode like you are doing can be a good way to start. Then it’s just a matter of finding the right conversion factor between steps and radians.