Hi, I’m starting a project to design a board based on STM32 and DRV8412 to control a stepper motor using SimpleFOC. Before sending the boards to produce I am doing a firmware validation to be sure that I can get it to work.
The test setup is made up of a Nema 17 Stepper Motor (Hanpose 17HS4401) a L298N driver and an STM32 as µController.
1.- My motor has step angle: 1.8 degrees. I assumed 50 pole pairs . How can I know how many magnetic poles my steper motor has? In Open loop it works quite correctly although it doesn’t make a complete turn every 3 Pi radians. Could it be due to an incorrect configuration of the magnetic poles?
2.- In closed loop it does not work. The behavior is completely erratic. I have verified that the magnetic position sensor works correctly. Is there something wrong with my caigo that could cause the problem?
You can see the formulas for relationship between number of teeth on the rotor (poles) , number of phases, and the resolution here: Stepper Motor Basics: PM vs VR vs Hybrid
For regular stepper motors this is the “permanent magnet” type. With parameters 1.8 degree and 2 phases, you get 50 poles. So maybe you should try with 25 pairs? I think 50 teeth is the regular stepper motor configuration unless you have special requirements.
For open loop, the pole pair count is not so important, but this can cause lots of problems with closed loop. It might just be an issue with this.
Thank you for your answer My motor is nothing especial. As you can see in the following picture it has 50 teeth.
25 magnetic poles: Not move at all in any control mode
100 magnetic poles: It moves using open loop velocity mode but not move al all using using open loop angle mode.
50 magnetic poles: It moves both with open loop velocity and able mode but the behavior seems quite messy since request to go to 2Pi position instead af performing a full rotation it performs more or less a half rotation. Why asking to come back to 0 position wt always return to the same position where departed,
I have tested the magnetic position sensor in stand alone and it works perfectly.
Does anyone know what could be wrong with my setup?
I think taking the stepper motor apart causes problems, because the rotor is magnetized after it is installed, and the eddy current formed when removing it might demagnetize it. Do you have a motor which was not opened to try?
The motor presents the same as before being opened. Fortunately, it hasn’t gotten worse… nor has it improved.
Yes, I have a similar motor that I have never noticed but the behavior is exactly the same.
I guess when I’m in the open loop position I command the motor to go to the 2Pi position, it should make one full turn… which it doesn’t. Do you know what could be the cause of it?
Here is some very old code (Oct 2020 - SimpleFoc v1.6) that I made to go along with this video with closed loop nema 17. Perhaps it’ll give some clues:
#include <SimpleFOC.h>
MagneticSensorSPI sensor = MagneticSensorSPI(AS5147_SPI, PA15);
StepperMotor motor = StepperMotor(PB1, PB0, PA6, PA7, 50);
// these are valid pins (mosi, miso, sclk) for 2nd SPI bus on storm32 board (stm32f107rc)
SPIClass SPI_2(PB15, PB14, PB13);
float target = 8;
// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
// a string to hold incoming data
static String received_chars;
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the string buffer:
received_chars += inChar;
// end of user input
if (inChar == '\n') {
// change the motor target
target = received_chars.toFloat();
Serial.print("Target velocity: ");
Serial.println(target);
// reset the command buffer
received_chars = "";
}
}
}
void setup() {
// monitoring port
Serial.begin(1000000);
delay(750);
// SPI_2.setClockDivider(4);
sensor.init(&SPI_2);
motor.LPF_velocity.Tf = 0.1;
motor.linkSensor(&sensor);
motor.voltage_sensor_align = 2;
motor.voltage_limit = 5;
motor.PID_velocity.P = 3;
motor.PID_velocity.I = 2;
motor.PID_velocity.D = 0.0;//01;
// motor.PID_velocity.D = 1000;
motor.P_angle.P = 2;
motor.P_angle.I = 0;
motor.P_angle.D = 0.0;//01;
motor.controller = ControlType::angle;
motor.useMonitoring(Serial);
motor.init();
motor.initFOC();
Serial.println("Sensor ready");
sensor.getVelocity();
// _delay(1000);
}
int sensorHz = 800;
long sensor_interval_micros = 1000000 / 200;
void loop() {
// display the angle and the angular velocity to the terminal
// delay(200);
// sensor.getAngle();
motor.loopFOC();
static long last = micros();
long now = micros();
if (now - last > sensor_interval_micros) {
motor.move(target);
// Serial.println(sensor.absolute_angle);
last = now;
}
Serial.print(" "); Serial.print(" "); Serial.print(sensor.getVelocity2()); Serial.println();
serialReceiveUserCommand();
}
I seem to remember sensor alignment was hard - I may have tweaked the alignment value after auto alignment. If you notice that motor behaves better in one direction (clockwise vs anticlockwise) it is probably sensor alignment being slightly off.
Also I can see I did something equivalent to motor.motion_downsample to reduce the amount motor.move is called.
Thank you very much @Owen_Williams I will test your code to see if makes any difference.
What gets me crazy is tahr in open loop, without magnetic sensor when I command to turn to the 2Pi position, instead of making a full rotation it just performs about a half rotation. I can not understand what can be the reason to behave in tat way Any idea about what could be the cause ?
the sensor is “doubled” - this happens for example when the bit-positions are “off by one” and you’re reading the angle values shifted to the left by 1 position. Then the sensor will return 2 rotations for each real rotation, if you see what I mean.
in open-loop mode, the pole-pairs are wrong (by 2x) - so if you set 50PP, then the real value is 100PP… in open loop mode, setting the PP wrong won’t affect the function, except the real angle values will be scaled by the PP error. So this would also explain why you get 1/2 rotation instead of a full rotation.
I seem to have made some progress, at least now it seems to work perfectly fine using open loop modes, but it still has strange behavior when switched to closed loop. To make it work in openloop mode, the maximum speed was limited to 5. It seems that when the limit was 20 it was as if it was “losing steps”. I’m not sure why it can’t work with a speed limit of 20.
t seems to work but suddenly loses control and later regains control again. These cycles of control and loss of control are repeated.
When I test the magnetic sensor in standalone mode itself it works correctly offering consistent readings without noise.
Any idea what could be the origin of the sudden loss of control that you the motor suffers?
You can see in this video that its seems to keep a velocity, the it get crazy and suddenly recovers the control until loses the control again ,
EDIT1: I have also observed that if I command a low velocity it permiso much better . I continues loosing control but it happens less frequently and for shorter periods os time
It seem to me that you are using a Storm32 controller to drive the stepper motor. How do you connect the stepper motor that requires 4 pins to the Storm32 the has 3 output pins ?
I briefly show in the video 26 seconds in. The storm32 can drive 3 gimbals so has 9 PWM outputs. I use 4 of those 9 to drive the stepper. It worked, I probably got lucky, i.e the pins I chose were on the same timer.
The storm32s are fun to play with - e.g I also rewired part of the board to free up an SPI (i think from an LED perhaps?).
After this experiment I concluded that nema 17s were hard to work with - hard to align and that I couldn’t get them going very fast. I went back to using gimbals.
Ok, I understand where the trick is!!! I assumed that Storm32 was the typical controller capable of controlling a single BLDC motor but, in fact, it is capable of controlling 3 BLDCs. Since you have 9 half-bridges, you can use 4 of them to drive a single stepper motor, or 8 to drive a pair of steppers
I agree that if I don’t run it at low speed the motor “loses steps” even when I run it in open loop mode.
What I don’t know is if it is due to L298N limitations, if the same happens with other drivers or the source of this behavior is due to the NEMA17 and can be avoid using a better stepper stepper motors.
Could you time just the sensor doing 10.000 reads / iterations ? When I was testing the MT6835 I saw a lot of improvement when sampling without SPI.begintransaction(). Dont know the AS5048A implementation.
Yes you are right . Without Serial.println it takes just 260 µS. I continue to struggle figuring out what can be the case of the erratic behavior when running in closed loop mode
I had an issue with a different encoder (MT6071 on I2C)where the bitmask used for returning the angle between the upper and lower register data was wrong.
Could you try to just plot output values from the sensor, and turn it _2PI degrees, and read the angle?
If you are thinking it’s an issue with local field made by the motor, you can also just set the phase voltage for one or both phases, and then backdrive by hand for a similar exercise but with static external B field.
When I test the magnetic sensor in standalone configuration everything seems to works perfectly , I have also used this same magnetic sensor with BLDCs motors in closed loop configuration and worked perfectly fine. My guess is that is not a firmware problem. Maybe I have to try with a different motor or a different magnetic sensor to try to overcome the issue.